fix: resolve format/build failures
This commit is contained in:
@@ -482,20 +482,20 @@ export function createExecTool(
|
||||
"exec.approval.request",
|
||||
{ timeoutMs: 130_000 },
|
||||
{
|
||||
command: params.command,
|
||||
cwd: workdir,
|
||||
host: "node",
|
||||
security: hostSecurity,
|
||||
ask: hostAsk,
|
||||
agentId: defaults?.agentId,
|
||||
resolvedPath: resolution?.resolvedPath ?? null,
|
||||
sessionKey: defaults?.sessionKey ?? null,
|
||||
timeoutMs: 120_000,
|
||||
command: params.command,
|
||||
cwd: workdir,
|
||||
host: "node",
|
||||
security: hostSecurity,
|
||||
ask: hostAsk,
|
||||
agentId: defaults?.agentId,
|
||||
resolvedPath: resolution?.resolvedPath ?? null,
|
||||
sessionKey: defaults?.sessionKey ?? null,
|
||||
timeoutMs: 120_000,
|
||||
},
|
||||
)) as { decision?: string } | null;
|
||||
const decision =
|
||||
decisionResult && typeof decisionResult === "object"
|
||||
? decisionResult.decision ?? null
|
||||
? (decisionResult.decision ?? null)
|
||||
: null;
|
||||
|
||||
if (decision === "deny") {
|
||||
@@ -506,9 +506,7 @@ export function createExecTool(
|
||||
approvedByAsk = true;
|
||||
} else if (askFallback === "allowlist") {
|
||||
if (!allowlistMatch) {
|
||||
throw new Error(
|
||||
"exec denied: approval required (approval UI not available)",
|
||||
);
|
||||
throw new Error("exec denied: approval required (approval UI not available)");
|
||||
}
|
||||
approvedByAsk = true;
|
||||
} else {
|
||||
@@ -611,20 +609,20 @@ export function createExecTool(
|
||||
"exec.approval.request",
|
||||
{ timeoutMs: 130_000 },
|
||||
{
|
||||
command: params.command,
|
||||
cwd: workdir,
|
||||
host: "gateway",
|
||||
security: hostSecurity,
|
||||
ask: hostAsk,
|
||||
agentId: defaults?.agentId,
|
||||
resolvedPath: resolution?.resolvedPath ?? null,
|
||||
sessionKey: defaults?.sessionKey ?? null,
|
||||
timeoutMs: 120_000,
|
||||
command: params.command,
|
||||
cwd: workdir,
|
||||
host: "gateway",
|
||||
security: hostSecurity,
|
||||
ask: hostAsk,
|
||||
agentId: defaults?.agentId,
|
||||
resolvedPath: resolution?.resolvedPath ?? null,
|
||||
sessionKey: defaults?.sessionKey ?? null,
|
||||
timeoutMs: 120_000,
|
||||
},
|
||||
)) as { decision?: string } | null;
|
||||
const decision =
|
||||
decisionResult && typeof decisionResult === "object"
|
||||
? decisionResult.decision ?? null
|
||||
? (decisionResult.decision ?? null)
|
||||
: null;
|
||||
|
||||
if (decision === "deny") {
|
||||
@@ -635,9 +633,7 @@ export function createExecTool(
|
||||
approvedByAsk = true;
|
||||
} else if (askFallback === "allowlist") {
|
||||
if (!allowlistMatch) {
|
||||
throw new Error(
|
||||
"exec denied: approval required (approval UI not available)",
|
||||
);
|
||||
throw new Error("exec denied: approval required (approval UI not available)");
|
||||
}
|
||||
approvedByAsk = true;
|
||||
} else {
|
||||
|
||||
@@ -55,7 +55,9 @@ function resolveAgentIdByWorkspace(
|
||||
): string[] {
|
||||
const list = listAgentEntries(cfg);
|
||||
const ids =
|
||||
list.length > 0 ? list.map((entry) => normalizeAgentId(entry.id)) : [resolveDefaultAgentId(cfg)];
|
||||
list.length > 0
|
||||
? list.map((entry) => normalizeAgentId(entry.id))
|
||||
: [resolveDefaultAgentId(cfg)];
|
||||
const normalizedTarget = normalizeWorkspacePath(workspaceDir);
|
||||
return ids.filter(
|
||||
(id) => normalizeWorkspacePath(resolveAgentWorkspaceDir(cfg, id)) === normalizedTarget,
|
||||
@@ -134,10 +136,7 @@ export async function agentsSetIdentityCommand(
|
||||
}
|
||||
|
||||
const fileTheme =
|
||||
identityFromFile?.theme ??
|
||||
identityFromFile?.creature ??
|
||||
identityFromFile?.vibe ??
|
||||
undefined;
|
||||
identityFromFile?.theme ?? identityFromFile?.creature ?? identityFromFile?.vibe ?? undefined;
|
||||
const incomingIdentity: IdentityConfig = {
|
||||
...(nameRaw || identityFromFile?.name ? { name: nameRaw ?? identityFromFile?.name } : {}),
|
||||
...(emojiRaw || identityFromFile?.emoji ? { emoji: emojiRaw ?? identityFromFile?.emoji } : {}),
|
||||
|
||||
@@ -79,11 +79,7 @@ export function parseIdentityMarkdown(content: string): AgentIdentity {
|
||||
const cleaned = line.trim().replace(/^\s*-\s*/, "");
|
||||
const colonIndex = cleaned.indexOf(":");
|
||||
if (colonIndex === -1) continue;
|
||||
const label = cleaned
|
||||
.slice(0, colonIndex)
|
||||
.replace(/[*_]/g, "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const label = cleaned.slice(0, colonIndex).replace(/[*_]/g, "").trim().toLowerCase();
|
||||
const value = cleaned
|
||||
.slice(colonIndex + 1)
|
||||
.replace(/^[*_]+|[*_]+$/g, "")
|
||||
|
||||
@@ -93,7 +93,12 @@ describe("agents set-identity command", () => {
|
||||
configMocks.readConfigFileSnapshot.mockResolvedValue({
|
||||
...baseSnapshot,
|
||||
config: {
|
||||
agents: { list: [{ id: "main", workspace }, { id: "ops", workspace }] },
|
||||
agents: {
|
||||
list: [
|
||||
{ id: "main", workspace },
|
||||
{ id: "ops", workspace },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,12 @@ import type { LoggingConfig, SessionConfig, WebConfig } from "./types.base.js";
|
||||
import type { BrowserConfig } from "./types.browser.js";
|
||||
import type { ChannelsConfig } from "./types.channels.js";
|
||||
import type { CronConfig } from "./types.cron.js";
|
||||
import type { CanvasHostConfig, DiscoveryConfig, GatewayConfig, TalkConfig } from "./types.gateway.js";
|
||||
import type {
|
||||
CanvasHostConfig,
|
||||
DiscoveryConfig,
|
||||
GatewayConfig,
|
||||
TalkConfig,
|
||||
} from "./types.gateway.js";
|
||||
import type { HooksConfig } from "./types.hooks.js";
|
||||
import type {
|
||||
AudioConfig,
|
||||
|
||||
@@ -113,7 +113,6 @@ export type GatewayHttpConfig = {
|
||||
endpoints?: GatewayHttpEndpointsConfig;
|
||||
};
|
||||
|
||||
|
||||
export type GatewayConfig = {
|
||||
/** Single multiplexed port for Gateway WS + HTTP (default: 18789). */
|
||||
port?: number;
|
||||
|
||||
@@ -231,12 +231,7 @@ export const ClawdbotSchema = z
|
||||
port: z.number().int().positive().optional(),
|
||||
mode: z.union([z.literal("local"), z.literal("remote")]).optional(),
|
||||
bind: z
|
||||
.union([
|
||||
z.literal("auto"),
|
||||
z.literal("lan"),
|
||||
z.literal("loopback"),
|
||||
z.literal("custom"),
|
||||
])
|
||||
.union([z.literal("auto"), z.literal("lan"), z.literal("loopback"), z.literal("custom")])
|
||||
.optional(),
|
||||
controlUi: z
|
||||
.object({
|
||||
|
||||
@@ -136,10 +136,7 @@ export async function callGateway<T = unknown>(opts: CallGatewayOptions): Promis
|
||||
});
|
||||
const url = connectionDetails.url;
|
||||
const useLocalTls =
|
||||
config.gateway?.tls?.enabled === true &&
|
||||
!urlOverride &&
|
||||
!remoteUrl &&
|
||||
url.startsWith("wss://");
|
||||
config.gateway?.tls?.enabled === true && !urlOverride && !remoteUrl && url.startsWith("wss://");
|
||||
const tlsRuntime = useLocalTls ? await loadGatewayTlsRuntime(config.gateway?.tls) : undefined;
|
||||
const tlsFingerprint = tlsRuntime?.enabled ? tlsRuntime.fingerprintSha256 : undefined;
|
||||
const token =
|
||||
|
||||
@@ -93,22 +93,14 @@ export class GatewayClient {
|
||||
wsOptions.checkServerIdentity = (_host: string, cert: CertMeta) => {
|
||||
const fingerprintValue =
|
||||
typeof cert === "object" && cert && "fingerprint256" in cert
|
||||
? (cert as { fingerprint256?: string }).fingerprint256 ?? ""
|
||||
? ((cert as { fingerprint256?: string }).fingerprint256 ?? "")
|
||||
: "";
|
||||
const fingerprint = normalizeFingerprint(
|
||||
typeof fingerprintValue === "string" ? fingerprintValue : "",
|
||||
);
|
||||
const expected = normalizeFingerprint(this.opts.tlsFingerprint ?? "");
|
||||
if (!expected) {
|
||||
return new Error("gateway tls fingerprint missing");
|
||||
}
|
||||
if (!fingerprint) {
|
||||
return new Error("gateway tls fingerprint unavailable");
|
||||
}
|
||||
if (fingerprint !== expected) {
|
||||
return new Error("gateway tls fingerprint mismatch");
|
||||
}
|
||||
return undefined;
|
||||
if (!expected || !fingerprint) return false;
|
||||
return fingerprint === expected;
|
||||
};
|
||||
}
|
||||
this.ws = new WebSocket(url, wsOptions);
|
||||
|
||||
@@ -45,7 +45,10 @@ export class ExecApprovalManager {
|
||||
return record;
|
||||
}
|
||||
|
||||
async waitForDecision(record: ExecApprovalRecord, timeoutMs: number): Promise<ExecApprovalDecision | null> {
|
||||
async waitForDecision(
|
||||
record: ExecApprovalRecord,
|
||||
timeoutMs: number,
|
||||
): Promise<ExecApprovalDecision | null> {
|
||||
return await new Promise<ExecApprovalDecision | null>((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
this.pending.delete(record.id);
|
||||
|
||||
@@ -45,7 +45,7 @@ export class NodeRegistry {
|
||||
const nodeId = connect.device?.id ?? connect.client.id;
|
||||
const caps = Array.isArray(connect.caps) ? connect.caps : [];
|
||||
const commands = Array.isArray((connect as { commands?: string[] }).commands)
|
||||
? (connect as { commands?: string[] }).commands ?? []
|
||||
? ((connect as { commands?: string[] }).commands ?? [])
|
||||
: [];
|
||||
const permissions =
|
||||
typeof (connect as { permissions?: Record<string, boolean> }).permissions === "object"
|
||||
|
||||
@@ -222,7 +222,7 @@ export function createAgentEventHandler({
|
||||
evt.stream === "lifecycle" && typeof evt.data?.phase === "string" ? evt.data.phase : null;
|
||||
|
||||
if (sessionKey) {
|
||||
nodeSendToSession(sessionKey, "agent", agentPayload);
|
||||
nodeSendToSession(sessionKey, "agent", agentPayload);
|
||||
if (!isAborted && evt.stream === "assistant" && typeof evt.data?.text === "string") {
|
||||
emitChatDelta(sessionKey, clientRunId, evt.seq, evt.data.text);
|
||||
} else if (!isAborted && (lifecyclePhase === "end" || lifecyclePhase === "error")) {
|
||||
|
||||
@@ -9,9 +9,7 @@ import {
|
||||
} from "../protocol/index.js";
|
||||
import type { GatewayRequestHandlers } from "./types.js";
|
||||
|
||||
export function createExecApprovalHandlers(
|
||||
manager: ExecApprovalManager,
|
||||
): GatewayRequestHandlers {
|
||||
export function createExecApprovalHandlers(manager: ExecApprovalManager): GatewayRequestHandlers {
|
||||
return {
|
||||
"exec.approval.request": async ({ params, respond, context }) => {
|
||||
if (!validateExecApprovalRequestParams(params)) {
|
||||
@@ -61,12 +59,16 @@ export function createExecApprovalHandlers(
|
||||
{ dropIfSlow: true },
|
||||
);
|
||||
const decision = await manager.waitForDecision(record, timeoutMs);
|
||||
respond(true, {
|
||||
id: record.id,
|
||||
decision,
|
||||
createdAtMs: record.createdAtMs,
|
||||
expiresAtMs: record.expiresAtMs,
|
||||
}, undefined);
|
||||
respond(
|
||||
true,
|
||||
{
|
||||
id: record.id,
|
||||
decision,
|
||||
createdAtMs: record.createdAtMs,
|
||||
expiresAtMs: record.expiresAtMs,
|
||||
},
|
||||
undefined,
|
||||
);
|
||||
},
|
||||
"exec.approval.resolve": async ({ params, respond, client, context }) => {
|
||||
if (!validateExecApprovalResolveParams(params)) {
|
||||
|
||||
@@ -453,14 +453,10 @@ export const nodeHandlers: GatewayRequestHandlers = {
|
||||
loadGatewayModelCatalog: context.loadGatewayModelCatalog,
|
||||
logGateway: { warn: context.logGateway.warn },
|
||||
};
|
||||
await handleNodeEvent(
|
||||
nodeContext,
|
||||
"node",
|
||||
{
|
||||
event: p.event,
|
||||
payloadJSON,
|
||||
},
|
||||
);
|
||||
await handleNodeEvent(nodeContext, "node", {
|
||||
event: p.event,
|
||||
payloadJSON,
|
||||
});
|
||||
respond(true, { ok: true }, undefined);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -11,11 +11,7 @@ import type { NodeEvent, NodeEventContext } from "./server-node-events-types.js"
|
||||
import { loadSessionEntry } from "./session-utils.js";
|
||||
import { formatForLog } from "./ws-log.js";
|
||||
|
||||
export const handleNodeEvent = async (
|
||||
ctx: NodeEventContext,
|
||||
nodeId: string,
|
||||
evt: NodeEvent,
|
||||
) => {
|
||||
export const handleNodeEvent = async (ctx: NodeEventContext, nodeId: string, evt: NodeEvent) => {
|
||||
switch (evt.event) {
|
||||
case "voice.transcript": {
|
||||
if (!evt.payloadJSON) return;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import type { GatewayAuthConfig, GatewayBindMode, GatewayTailscaleConfig, loadConfig } from "../config/config.js";
|
||||
import type {
|
||||
GatewayAuthConfig,
|
||||
GatewayBindMode,
|
||||
GatewayTailscaleConfig,
|
||||
loadConfig,
|
||||
} from "../config/config.js";
|
||||
import {
|
||||
assertGatewayAuthConfigured,
|
||||
type ResolvedGatewayAuth,
|
||||
|
||||
@@ -22,7 +22,9 @@ export function logGatewayStartup(params: {
|
||||
consoleMessage: `agent model: ${chalk.whiteBright(modelRef)}`,
|
||||
});
|
||||
const scheme = params.tlsEnabled ? "wss" : "ws";
|
||||
params.log.info(`listening on ${scheme}://${params.bindHost}:${params.port} (PID ${process.pid})`);
|
||||
params.log.info(
|
||||
`listening on ${scheme}://${params.bindHost}:${params.port} (PID ${process.pid})`,
|
||||
);
|
||||
params.log.info(`log file: ${getResolvedLoggerSettings().file}`);
|
||||
if (params.isNixMode) {
|
||||
params.log.info("gateway: running in Nix mode (config managed externally)");
|
||||
|
||||
@@ -260,5 +260,4 @@ describe("gateway server models + voicewake", () => {
|
||||
ws.close();
|
||||
await server.close();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -499,7 +499,9 @@ export function attachGatewayWsMessageHandler(params: {
|
||||
commands: nodeSession.commands,
|
||||
cfg: loadConfig(),
|
||||
}).catch((err) =>
|
||||
logGateway.warn(`remote bin probe failed for ${nodeSession.nodeId}: ${formatForLog(err)}`),
|
||||
logGateway.warn(
|
||||
`remote bin probe failed for ${nodeSession.nodeId}: ${formatForLog(err)}`,
|
||||
),
|
||||
);
|
||||
void loadVoiceWakeConfig()
|
||||
.then((cfg) => {
|
||||
|
||||
@@ -13,7 +13,6 @@ import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js";
|
||||
|
||||
|
||||
type StubChannelOptions = {
|
||||
id: ChannelPlugin["id"];
|
||||
label: string;
|
||||
|
||||
@@ -27,11 +27,7 @@ function ensureDir(filePath: string) {
|
||||
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
||||
|
||||
function base64UrlEncode(buf: Buffer): string {
|
||||
return buf
|
||||
.toString("base64")
|
||||
.replaceAll("+", "-")
|
||||
.replaceAll("/", "_")
|
||||
.replace(/=+$/g, "");
|
||||
return buf.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, "");
|
||||
}
|
||||
|
||||
function base64UrlDecode(input: string): Buffer {
|
||||
|
||||
@@ -26,10 +26,7 @@ import { getMachineDisplayName } from "../infra/machine-name.js";
|
||||
import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import { VERSION } from "../version.js";
|
||||
import {
|
||||
GATEWAY_CLIENT_MODES,
|
||||
GATEWAY_CLIENT_NAMES,
|
||||
} from "../utils/message-channel.js";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
|
||||
|
||||
import { ensureNodeHostConfig, saveNodeHostConfig, type NodeHostGatewayConfig } from "./config.js";
|
||||
import { GatewayClient } from "../gateway/client.js";
|
||||
@@ -804,8 +801,7 @@ function coerceNodeInvokePayload(payload: unknown): NodeInvokeRequestPayload | n
|
||||
? JSON.stringify(obj.params)
|
||||
: null;
|
||||
const timeoutMs = typeof obj.timeoutMs === "number" ? obj.timeoutMs : null;
|
||||
const idempotencyKey =
|
||||
typeof obj.idempotencyKey === "string" ? obj.idempotencyKey : null;
|
||||
const idempotencyKey = typeof obj.idempotencyKey === "string" ? obj.idempotencyKey : null;
|
||||
return {
|
||||
id,
|
||||
nodeId,
|
||||
@@ -840,11 +836,7 @@ async function sendInvokeResult(
|
||||
}
|
||||
}
|
||||
|
||||
async function sendNodeEvent(
|
||||
client: GatewayClient,
|
||||
event: string,
|
||||
payload: unknown,
|
||||
) {
|
||||
async function sendNodeEvent(client: GatewayClient, event: string, payload: unknown) {
|
||||
try {
|
||||
await client.request("node.event", {
|
||||
event,
|
||||
|
||||
Reference in New Issue
Block a user