@robota-sdk/agent-core 3.0.0-beta.82 → 3.0.0-beta.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -0
- package/README.md +160 -110
- package/dist/browser/bounded-output-D3cgiOrh.js +2 -0
- package/dist/browser/bounded-output-D3cgiOrh.js.map +1 -0
- package/dist/browser/{command-executor-cI7XJ374.js → command-executor-BsBTcghZ.js} +2 -2
- package/dist/browser/{command-executor-cI7XJ374.js.map → command-executor-BsBTcghZ.js.map} +1 -1
- package/dist/browser/index.d.ts +1265 -892
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +11 -11
- package/dist/browser/index.js.map +1 -1
- package/dist/node/bounded-output-D3cgiOrh.js +2 -0
- package/dist/node/bounded-output-D3cgiOrh.js.map +1 -0
- package/dist/node/{command-executor-DV-H2oD6.js → command-executor-BdE1zg3q.js} +2 -2
- package/dist/node/{command-executor-DV-H2oD6.js.map → command-executor-BdE1zg3q.js.map} +1 -1
- package/dist/node/{command-executor-Aat_q7P2.cjs → command-executor-CPGK8I8l.cjs} +1 -1
- package/dist/node/{http-executor-71JiIdFP.cjs → http-executor-BYiKn8h3.cjs} +1 -1
- package/dist/node/{index-BhfNtQJk.d.cts → index-DXZ-pyEr.d.ts} +1267 -893
- package/dist/node/index-DXZ-pyEr.d.ts.map +1 -0
- package/dist/node/{index-D2rky0wZ.d.ts → index-gEUh4G-t.d.cts} +1267 -893
- package/dist/node/index-gEUh4G-t.d.cts.map +1 -0
- package/dist/node/index.cjs +9 -9
- package/dist/node/index.d.cts +3 -3
- package/dist/node/index.d.ts +3 -3
- package/dist/node/index.js +9 -9
- package/dist/node/index.js.map +1 -1
- package/dist/node/node.cjs +1 -1
- package/dist/node/node.d.cts +1 -1
- package/dist/node/node.d.ts +1 -1
- package/dist/node/node.js +1 -1
- package/dist/node/testing/index.d.cts +1 -1
- package/dist/node/testing/index.d.ts +1 -1
- package/dist/node/{types-gNrckgFE.d.ts → types-BQ-sKCQS.d.cts} +3 -4
- package/dist/node/types-BQ-sKCQS.d.cts.map +1 -0
- package/dist/node/{types-gNrckgFE.d.cts → types-BQ-sKCQS.d.ts} +3 -4
- package/dist/node/types-BQ-sKCQS.d.ts.map +1 -0
- package/dist/node/verdict-decoder-D412SAGd.cjs +1 -0
- package/package.json +8 -4
- package/dist/browser/bounded-output-DpjpS98g.js +0 -2
- package/dist/browser/bounded-output-DpjpS98g.js.map +0 -1
- package/dist/node/bounded-output-DpjpS98g.js +0 -2
- package/dist/node/bounded-output-DpjpS98g.js.map +0 -1
- package/dist/node/index-BhfNtQJk.d.cts.map +0 -1
- package/dist/node/index-D2rky0wZ.d.ts.map +0 -1
- package/dist/node/types-gNrckgFE.d.cts.map +0 -1
- package/dist/node/types-gNrckgFE.d.ts.map +0 -1
- package/dist/node/verdict-decoder-Estx9MtY.cjs +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-executor-
|
|
1
|
+
{"version":3,"file":"command-executor-BsBTcghZ.js","names":[],"sources":["../../src/hooks/executors/command-executor.ts"],"sourcesContent":["/**\n * Command hook executor — executes shell commands with JSON input on stdin.\n *\n * Exit-code mapping (SEC-015):\n * - `0` → `allow`, stdout carried for the runner's response-protocol decode\n * - `2` → `deny`, stderr carried as the reason\n * - any other code → `error` / `nonzero-exit`\n * - killed by a signal (exit code `null`) → `error` / `nonzero-exit`, signal named in the reason\n * - deadline elapsed → `error` / `timeout`\n * - the process never started → `error` / `spawn-failure`\n *\n * The last four used to be one number. A missing binary exits `127` and a timeout resolved `1`, and\n * the runner discarded both alike, so a gate that never ran was indistinguishable from one that\n * approved.\n */\n\nimport { spawn } from 'node:child_process';\n\nimport { createBoundedOutput, type IBoundedOutput } from '../../utils/bounded-output.js';\nimport { resolvePlatformShell } from '../../utils/platform-shell.js';\nimport { subprocessTraceEnvironment } from '../../utils/trace-context.js';\n\nimport type { ISubprocessTraceEnv } from '../../interfaces/trace-context.js';\nimport type {\n ICommandHookDefinition,\n IHookInput,\n THookOutcome,\n IHookTypeExecutor,\n} from '../types.js';\n\n/** Default timeout in seconds — matches Claude Code's 600s default */\nconst DEFAULT_TIMEOUT_SECONDS = 600;\n/** ARCH-056: most bytes retained per hook stream (stdout head, stderr tail). */\nconst MAX_HOOK_OUTPUT_BYTES = 1_000_000;\n\n/**\n * How a finished process maps onto an outcome — a pure function of what the process reported.\n *\n * Extracted from `execute` because it is the part that carries the contract: `execute` owns spawning\n * and settling exactly once, this owns what the result MEANS, and the two change for different\n * reasons.\n */\n/**\n * Attach the output collectors and feed the hook input to stdin.\n *\n * Separated from `execute` so the promise body reads as the three things that can settle it —\n * timeout, close, spawn error — rather than as stream plumbing interleaved with them. The\n * `settled` guard those three share is the invariant worth keeping visible in one place.\n */\nfunction wireChildIo(\n child: ReturnType<typeof spawn>,\n inputJson: string,\n): { stdoutOutput: IBoundedOutput; stderrOutput: IBoundedOutput } {\n // ARCH-056: bounded while reading; a hook that floods stdout cannot grow the parent's memory.\n const stdoutOutput = createBoundedOutput({ maxBytes: MAX_HOOK_OUTPUT_BYTES });\n const stderrOutput = createBoundedOutput({ maxBytes: MAX_HOOK_OUTPUT_BYTES, retain: 'tail' });\n child.stdout?.on('data', (chunk: Buffer) => stdoutOutput.append(chunk));\n child.stderr?.on('data', (chunk: Buffer) => stderrOutput.append(chunk));\n child.stdin?.on('error', () => {\n // EPIPE: child closed stdin before we finished writing — safe to ignore\n });\n child.stdin?.write(inputJson);\n child.stdin?.end();\n return { stdoutOutput, stderrOutput };\n}\n\nfunction outcomeOfExit(\n code: number | null,\n signal: NodeJS.Signals | null,\n stdout: string,\n stderr: string,\n): THookOutcome {\n if (code === 0) return { outcome: 'allow', source: 'command', stdout };\n if (code === 2) {\n return { outcome: 'deny', source: 'command', reason: stderr.trim() || 'Blocked by hook' };\n }\n const detail = stderr.trim() ? `: ${stderr.trim()}` : '';\n return {\n outcome: 'error',\n source: 'command',\n kind: 'nonzero-exit',\n // `code === null` means a signal ended it. That is not an exit code and must not be read as\n // one — the old `code ?? 1` made a SIGKILLed hook indistinguishable from one that exited 1.\n reason:\n code === null\n ? `Hook terminated by signal ${signal ?? 'unknown'}${detail}`\n : `Hook exited ${code}${detail}`,\n };\n}\n\nexport class CommandExecutor implements IHookTypeExecutor {\n readonly type = 'command' as const;\n\n constructor(private readonly shellExecutable?: string) {}\n\n /**\n * `traceEnv` is the prompt's trace for this child, handed separately so it never reaches the\n * stdin JSON. The child sees `process.env`, then Robota's value, then the hook's own `env`; a hook\n * that sets its own `TRACEPARENT` wins and gets the ambient environment unchanged.\n */\n execute(\n definition: ICommandHookDefinition,\n input: IHookInput,\n traceEnv?: ISubprocessTraceEnv,\n ): Promise<THookOutcome> {\n const timeoutSeconds = definition.timeout ?? DEFAULT_TIMEOUT_SECONDS;\n const timeoutMs = timeoutSeconds * 1000;\n const inputJson = JSON.stringify(input);\n\n return new Promise<THookOutcome>((resolve) => {\n let settled = false;\n const shell = resolvePlatformShell({ executable: this.shellExecutable });\n const child = spawn(shell.command, shell.commandArgs(definition.command), {\n cwd: input.cwd,\n env: subprocessTraceEnvironment(process.env, traceEnv, input.env),\n });\n const { stdoutOutput, stderrOutput } = wireChildIo(child, inputJson);\n\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n child.kill('SIGTERM');\n resolve({\n outcome: 'error',\n source: 'command',\n kind: 'timeout',\n reason: `Hook timed out after ${timeoutSeconds}s`,\n });\n }\n }, timeoutMs);\n\n child.on('close', (code: number | null, signal: NodeJS.Signals | null) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(outcomeOfExit(code, signal, stdoutOutput.toString(), stderrOutput.toString()));\n });\n\n child.on('error', (err: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve({\n outcome: 'error',\n source: 'command',\n kind: 'spawn-failure',\n reason: err.message,\n });\n });\n });\n }\n}\n"],"mappings":"0GA+BA,MAEM,EAAwB,IAgB9B,SAAS,EACP,EACA,EACgE,CAEhE,IAAM,EAAe,EAAoB,CAAE,SAAU,CAAsB,CAAC,EACtE,EAAe,EAAoB,CAAE,SAAU,EAAuB,OAAQ,MAAO,CAAC,EAQ5F,OAPA,EAAM,QAAQ,GAAG,OAAS,GAAkB,EAAa,OAAO,CAAK,CAAC,EACtE,EAAM,QAAQ,GAAG,OAAS,GAAkB,EAAa,OAAO,CAAK,CAAC,EACtE,EAAM,OAAO,GAAG,YAAe,CAE/B,CAAC,EACD,EAAM,OAAO,MAAM,CAAS,EAC5B,EAAM,OAAO,IAAI,EACV,CAAE,eAAc,cAAa,CACtC,CAEA,SAAS,EACP,EACA,EACA,EACA,EACc,CACd,GAAI,IAAS,EAAG,MAAO,CAAE,QAAS,QAAS,OAAQ,UAAW,QAAO,EACrE,GAAI,IAAS,EACX,MAAO,CAAE,QAAS,OAAQ,OAAQ,UAAW,OAAQ,EAAO,KAAK,GAAK,iBAAkB,EAE1F,IAAM,EAAS,EAAO,KAAK,EAAI,KAAK,EAAO,KAAK,IAAM,GACtD,MAAO,CACL,QAAS,QACT,OAAQ,UACR,KAAM,eAGN,OACE,IAAS,KACL,6BAA6B,GAAU,YAAY,IACnD,eAAe,IAAO,GAC9B,CACF,CAEA,IAAa,EAAb,KAA0D,CAG3B,gBAF7B,KAAgB,UAEhB,YAAY,EAA2C,CAA1B,KAAA,gBAAA,CAA2B,CAOxD,QACE,EACA,EACA,EACuB,CACvB,IAAM,EAAiB,EAAW,SAAW,IACvC,EAAY,EAAiB,IAC7B,EAAY,KAAK,UAAU,CAAK,EAEtC,OAAO,IAAI,QAAuB,GAAY,CAC5C,IAAI,EAAU,GACR,EAAQ,EAAqB,CAAE,WAAY,KAAK,eAAgB,CAAC,EACjE,EAAQ,EAAM,EAAM,QAAS,EAAM,YAAY,EAAW,OAAO,EAAG,CACxE,IAAK,EAAM,IACX,IAAK,EAA2B,QAAQ,IAAK,EAAU,EAAM,GAAG,CAClE,CAAC,EACK,CAAE,eAAc,gBAAiB,EAAY,EAAO,CAAS,EAE7D,EAAQ,eAAiB,CACxB,IACH,EAAU,GACV,EAAM,KAAK,SAAS,EACpB,EAAQ,CACN,QAAS,QACT,OAAQ,UACR,KAAM,UACN,OAAQ,wBAAwB,EAAe,EACjD,CAAC,EAEL,EAAG,CAAS,EAEZ,EAAM,GAAG,SAAU,EAAqB,IAAkC,CACpE,IACJ,EAAU,GACV,aAAa,CAAK,EAClB,EAAQ,EAAc,EAAM,EAAQ,EAAa,SAAS,EAAG,EAAa,SAAS,CAAC,CAAC,EACvF,CAAC,EAED,EAAM,GAAG,QAAU,GAAe,CAC5B,IACJ,EAAU,GACV,aAAa,CAAK,EAClB,EAAQ,CACN,QAAS,QACT,OAAQ,UACR,KAAM,gBACN,OAAQ,EAAI,OACd,CAAC,EACH,CAAC,CACH,CAAC,CACH,CACF"}
|