@robota-sdk/agent-core 3.0.0-beta.83 → 3.0.0-beta.85
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 +103 -0
- package/README.md +154 -116
- package/dist/browser/bounded-output-Bgx2Cgkx.js +2 -0
- package/dist/browser/bounded-output-Bgx2Cgkx.js.map +1 -0
- package/dist/browser/{command-executor-cI7XJ374.js → command-executor-C0XXfBnt.js} +2 -2
- package/dist/browser/{command-executor-cI7XJ374.js.map → command-executor-C0XXfBnt.js.map} +1 -1
- package/dist/browser/{http-executor-CHy6UeBU.js → http-executor-B4YgCJg7.js} +2 -2
- package/dist/browser/{http-executor-CHy6UeBU.js.map → http-executor-B4YgCJg7.js.map} +1 -1
- package/dist/browser/index.d.ts +1251 -918
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +10 -10
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/{verdict-decoder-Dk_w2NG9.js → verdict-decoder-Dz_rjoIZ.js} +2 -2
- package/dist/browser/verdict-decoder-Dz_rjoIZ.js.map +1 -0
- package/dist/node/bounded-output-Bgx2Cgkx.js +2 -0
- package/dist/node/bounded-output-Bgx2Cgkx.js.map +1 -0
- package/dist/node/{command-executor-Aat_q7P2.cjs → command-executor-CqAFpB-X.cjs} +1 -1
- package/dist/node/{command-executor-DV-H2oD6.js → command-executor-d6DdfUTD.js} +2 -2
- package/dist/node/{command-executor-DV-H2oD6.js.map → command-executor-d6DdfUTD.js.map} +1 -1
- package/dist/node/{http-executor-cWzI2svn.js → http-executor-ADn4locH.js} +2 -2
- package/dist/node/{http-executor-cWzI2svn.js.map → http-executor-ADn4locH.js.map} +1 -1
- package/dist/node/{http-executor-71JiIdFP.cjs → http-executor-BFtXs8FP.cjs} +1 -1
- package/dist/node/{index-D1_Mak-n.d.cts → index-CPwJEiFl.d.cts} +1251 -917
- package/dist/node/index-CPwJEiFl.d.cts.map +1 -0
- package/dist/node/{index-D4iJ5IsN.d.ts → index-DQrmrFn9.d.ts} +1251 -917
- package/dist/node/index-DQrmrFn9.d.ts.map +1 -0
- package/dist/node/index.cjs +10 -10
- package/dist/node/index.d.cts +3 -3
- package/dist/node/index.d.ts +3 -3
- package/dist/node/index.js +11 -11
- 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-Ge2XB-y-.d.cts} +4 -5
- package/dist/node/types-Ge2XB-y-.d.cts.map +1 -0
- package/dist/node/{types-gNrckgFE.d.cts → types-Ge2XB-y-.d.ts} +4 -5
- package/dist/node/types-Ge2XB-y-.d.ts.map +1 -0
- package/dist/node/verdict-decoder-DIHay1ul.cjs +1 -0
- package/dist/node/{verdict-decoder-Dk_w2NG9.js → verdict-decoder-Dz_rjoIZ.js} +2 -2
- package/dist/node/verdict-decoder-Dz_rjoIZ.js.map +1 -0
- package/package.json +3 -3
- package/dist/browser/bounded-output-DpjpS98g.js +0 -2
- package/dist/browser/bounded-output-DpjpS98g.js.map +0 -1
- package/dist/browser/verdict-decoder-Dk_w2NG9.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-D1_Mak-n.d.cts.map +0 -1
- package/dist/node/index-D4iJ5IsN.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-Dk_w2NG9.js.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-C0XXfBnt.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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./verdict-decoder-
|
|
2
|
-
//# sourceMappingURL=http-executor-
|
|
1
|
+
import{t as e}from"./verdict-decoder-Dz_rjoIZ.js";function t(e){return e.replace(/\$([A-Za-z_][A-Za-z0-9_]*)/g,(e,t)=>{let n=process.env[t];return n===void 0?e:n})}var n=class{type=`http`;async execute(n,i){let a=(n.timeout??10)*1e3,o={"Content-Type":`application/json`};if(n.headers)for(let[e,r]of Object.entries(n.headers))o[e]=t(r);try{let t=await fetch(n.url,{method:`POST`,headers:o,body:JSON.stringify(i),signal:AbortSignal.timeout(a)});return t.ok?e(await t.text(),`http`,i.hook_event_name):{outcome:`error`,source:`http`,kind:`http-status`,reason:`HTTP ${t.status} ${t.statusText}`}}catch(e){return r(e)}}};function r(e){return{outcome:`error`,source:`http`,kind:e instanceof Error&&e.name===`TimeoutError`?`timeout`:`transport-failure`,reason:e instanceof Error?e.message:String(e)}}export{n as HttpExecutor};
|
|
2
|
+
//# sourceMappingURL=http-executor-B4YgCJg7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-executor-
|
|
1
|
+
{"version":3,"file":"http-executor-B4YgCJg7.js","names":[],"sources":["../../src/hooks/executors/http-executor.ts"],"sourcesContent":["/**\n * HTTP hook executor — POSTs hook input as JSON to a URL.\n *\n * Response format: `{ ok: boolean, reason?: string }`, decoded by `decodeHookVerdict` (SEC-015):\n * - `ok: true` → `allow`\n * - `ok: false` → `deny`, carrying `reason`\n * - anything else, including a non-boolean `ok` → `error` / `malformed-response`\n *\n * Transport conditions are outcomes in their own right rather than a shared failure code:\n * non-2xx → `http-status`, deadline elapsed → `timeout`, unreachable → `transport-failure`,\n * unparseable body → `malformed-response`.\n *\n * Supports env var interpolation in headers: $VAR_NAME\n */\n\nimport { decodeHookVerdict } from '../verdict-decoder.js';\n\nimport type { IHttpHookDefinition, IHookInput, THookOutcome, IHookTypeExecutor } from '../types.js';\n\n/** Default timeout in seconds */\nconst DEFAULT_TIMEOUT_SECONDS = 10;\n\n/** Interpolate $VAR_NAME references in a string with process.env values. */\nfunction interpolateEnvVars(value: string): string {\n return value.replace(/\\$([A-Za-z_][A-Za-z0-9_]*)/g, (_match, varName: string) => {\n const envValue = process.env[varName];\n return envValue !== undefined ? envValue : _match;\n });\n}\n\nexport class HttpExecutor implements IHookTypeExecutor {\n readonly type = 'http' as const;\n\n async execute(definition: IHttpHookDefinition, input: IHookInput): Promise<THookOutcome> {\n const timeoutSeconds = definition.timeout ?? DEFAULT_TIMEOUT_SECONDS;\n const timeoutMs = timeoutSeconds * 1000;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (definition.headers) {\n for (const [key, value] of Object.entries(definition.headers)) {\n headers[key] = interpolateEnvVars(value);\n }\n }\n\n try {\n const response = await fetch(definition.url, {\n method: 'POST',\n headers,\n body: JSON.stringify(input),\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n if (!response.ok) {\n return {\n outcome: 'error',\n source: 'http',\n kind: 'http-status',\n reason: `HTTP ${response.status} ${response.statusText}`,\n };\n }\n\n // Read the body as TEXT first. `response.json()` would collapse \"the endpoint sent HTML\" and\n // \"the endpoint sent a verdict\" into one throw, and the raw text is what the decoder quotes\n // back — so a misconfigured endpoint is identifiable from the reason alone.\n return decodeHookVerdict(await response.text(), 'http', input.hook_event_name);\n } catch (err: unknown) {\n return toTransportOutcome(err);\n }\n }\n}\n\n/**\n * Classify a `fetch` rejection.\n *\n * `AbortSignal.timeout` rejects with a `DOMException` named `TimeoutError`, which is a different\n * fact from a connection refused or dropped: one says the hook was too slow, the other says it was\n * never reached. Both are `error`, and an operator reading the reason needs to know which.\n */\nfunction toTransportOutcome(err: unknown): THookOutcome {\n return {\n outcome: 'error',\n source: 'http',\n kind: err instanceof Error && err.name === 'TimeoutError' ? 'timeout' : 'transport-failure',\n reason: err instanceof Error ? err.message : String(err),\n };\n}\n"],"mappings":"kDAuBA,SAAS,EAAmB,EAAuB,CACjD,OAAO,EAAM,QAAQ,+BAAgC,EAAQ,IAAoB,CAC/E,IAAM,EAAW,QAAQ,IAAI,GAC7B,OAAO,IAAa,IAAA,GAAuB,EAAX,CAClC,CAAC,CACH,CAEA,IAAa,EAAb,KAAuD,CACrD,KAAgB,OAEhB,MAAM,QAAQ,EAAiC,EAA0C,CAEvF,IAAM,GADiB,EAAW,SAAW,IACV,IAE7B,EAAkC,CACtC,eAAgB,kBAClB,EAEA,GAAI,EAAW,QACb,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAW,OAAO,EAC1D,EAAQ,GAAO,EAAmB,CAAK,EAI3C,GAAI,CACF,IAAM,EAAW,MAAM,MAAM,EAAW,IAAK,CAC3C,OAAQ,OACR,UACA,KAAM,KAAK,UAAU,CAAK,EAC1B,OAAQ,YAAY,QAAQ,CAAS,CACvC,CAAC,EAcD,OAZK,EAAS,GAYP,EAAkB,MAAM,EAAS,KAAK,EAAG,OAAQ,EAAM,eAAe,EAXpE,CACL,QAAS,QACT,OAAQ,OACR,KAAM,cACN,OAAQ,QAAQ,EAAS,OAAO,GAAG,EAAS,YAC9C,CAOJ,OAAS,EAAc,CACrB,OAAO,EAAmB,CAAG,CAC/B,CACF,CACF,EASA,SAAS,EAAmB,EAA4B,CACtD,MAAO,CACL,QAAS,QACT,OAAQ,OACR,KAAM,aAAe,OAAS,EAAI,OAAS,eAAiB,UAAY,oBACxE,OAAQ,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CACzD,CACF"}
|