@alpacakit/agents 0.1.0-beta.19 → 0.1.0-beta.21

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.
Files changed (140) hide show
  1. package/README.md +60 -0
  2. package/dist/agents/claude.d.ts.map +1 -1
  3. package/dist/agents/claude.js +3 -0
  4. package/dist/agents/codex.d.ts.map +1 -1
  5. package/dist/agents/codex.js +4 -0
  6. package/dist/agents/openai-compatible/config.d.ts.map +1 -1
  7. package/dist/agents/openai-compatible/config.js +5 -0
  8. package/dist/agents/openai-compatible/fetch-engine.d.ts.map +1 -1
  9. package/dist/agents/openai-compatible/fetch-engine.js +6 -0
  10. package/dist/agents/openai-compatible/pi/module.d.ts.map +1 -1
  11. package/dist/agents/openai-compatible/pi/module.js +1 -0
  12. package/dist/agents/openai-compatible/pi/sandbox.js +2 -0
  13. package/dist/agents/openai-compatible/response.js +1 -0
  14. package/dist/auth/profile-store.d.ts.map +1 -1
  15. package/dist/auth/profile-store.js +1 -0
  16. package/dist/auth/secrets.d.ts.map +1 -1
  17. package/dist/auth/secrets.js +2 -0
  18. package/dist/codex/app-server.js +6 -0
  19. package/dist/core/controlled-process.d.ts +98 -0
  20. package/dist/core/controlled-process.d.ts.map +1 -0
  21. package/dist/core/controlled-process.js +29 -0
  22. package/dist/core/error.d.ts +25 -0
  23. package/dist/core/error.d.ts.map +1 -1
  24. package/dist/core/error.js +32 -0
  25. package/dist/core/node-controlled-exec.d.ts +3 -0
  26. package/dist/core/node-controlled-exec.d.ts.map +1 -0
  27. package/dist/core/node-controlled-exec.js +32 -0
  28. package/dist/core/node-ports.d.ts +1 -0
  29. package/dist/core/node-ports.d.ts.map +1 -1
  30. package/dist/core/node-ports.js +9 -1
  31. package/dist/core/ports.d.ts +5 -0
  32. package/dist/core/ports.d.ts.map +1 -1
  33. package/dist/fleet/fleet.d.ts.map +1 -1
  34. package/dist/fleet/fleet.js +5 -2
  35. package/dist/fleet/store.d.ts.map +1 -1
  36. package/dist/fleet/store.js +3 -0
  37. package/dist/host/github-dir.d.ts.map +1 -1
  38. package/dist/host/github-dir.js +5 -0
  39. package/dist/host/mcp-list.d.ts.map +1 -1
  40. package/dist/host/mcp-list.js +1 -0
  41. package/dist/host/run-command.d.ts.map +1 -1
  42. package/dist/host/run-command.js +2 -0
  43. package/dist/index.d.ts +6 -3
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -1
  46. package/dist/internal/controlled-process/authentication.d.ts +13 -0
  47. package/dist/internal/controlled-process/authentication.d.ts.map +1 -0
  48. package/dist/internal/controlled-process/authentication.js +112 -0
  49. package/dist/internal/controlled-process/child-fd.d.ts +5 -0
  50. package/dist/internal/controlled-process/child-fd.d.ts.map +1 -0
  51. package/dist/internal/controlled-process/child-fd.js +47 -0
  52. package/dist/internal/controlled-process/framed-transport.d.ts +6 -0
  53. package/dist/internal/controlled-process/framed-transport.d.ts.map +1 -0
  54. package/dist/internal/controlled-process/framed-transport.js +117 -0
  55. package/dist/internal/controlled-process/host-controller.d.ts +23 -0
  56. package/dist/internal/controlled-process/host-controller.d.ts.map +1 -0
  57. package/dist/internal/controlled-process/host-controller.js +908 -0
  58. package/dist/internal/controlled-process/lifecycle.d.ts +5 -0
  59. package/dist/internal/controlled-process/lifecycle.d.ts.map +1 -0
  60. package/dist/internal/controlled-process/lifecycle.js +22 -0
  61. package/dist/internal/controlled-process/model.d.ts +99 -0
  62. package/dist/internal/controlled-process/model.d.ts.map +1 -0
  63. package/dist/internal/controlled-process/model.js +1 -0
  64. package/dist/internal/controlled-process/record-store.d.ts +17 -0
  65. package/dist/internal/controlled-process/record-store.d.ts.map +1 -0
  66. package/dist/internal/controlled-process/record-store.js +170 -0
  67. package/dist/internal/controlled-process/record.d.ts +12 -0
  68. package/dist/internal/controlled-process/record.d.ts.map +1 -0
  69. package/dist/internal/controlled-process/record.js +87 -0
  70. package/dist/internal/controlled-process/schema.d.ts +133 -0
  71. package/dist/internal/controlled-process/schema.d.ts.map +1 -0
  72. package/dist/internal/controlled-process/schema.js +99 -0
  73. package/dist/internal/controlled-process/shim-entry.d.ts +2 -0
  74. package/dist/internal/controlled-process/shim-entry.d.ts.map +1 -0
  75. package/dist/internal/controlled-process/shim-entry.js +2 -0
  76. package/dist/internal/controlled-process/shim-runtime.d.ts +2 -0
  77. package/dist/internal/controlled-process/shim-runtime.d.ts.map +1 -0
  78. package/dist/internal/controlled-process/shim-runtime.js +57 -0
  79. package/dist/internal/controlled-process/supervisor-coordinator.d.ts +67 -0
  80. package/dist/internal/controlled-process/supervisor-coordinator.d.ts.map +1 -0
  81. package/dist/internal/controlled-process/supervisor-coordinator.js +325 -0
  82. package/dist/internal/controlled-process/supervisor-entry.d.ts +2 -0
  83. package/dist/internal/controlled-process/supervisor-entry.d.ts.map +1 -0
  84. package/dist/internal/controlled-process/supervisor-entry.js +2 -0
  85. package/dist/internal/controlled-process/supervisor-model.d.ts +92 -0
  86. package/dist/internal/controlled-process/supervisor-model.d.ts.map +1 -0
  87. package/dist/internal/controlled-process/supervisor-model.js +1 -0
  88. package/dist/internal/controlled-process/supervisor-platform.d.ts +16 -0
  89. package/dist/internal/controlled-process/supervisor-platform.d.ts.map +1 -0
  90. package/dist/internal/controlled-process/supervisor-platform.js +104 -0
  91. package/dist/internal/controlled-process/supervisor-runtime.d.ts +11 -0
  92. package/dist/internal/controlled-process/supervisor-runtime.d.ts.map +1 -0
  93. package/dist/internal/controlled-process/supervisor-runtime.js +773 -0
  94. package/dist/internal/controlled-process/supervisor-schema.d.ts +100 -0
  95. package/dist/internal/controlled-process/supervisor-schema.d.ts.map +1 -0
  96. package/dist/internal/controlled-process/supervisor-schema.js +73 -0
  97. package/dist/internal/controlled-process/supervisor-transport.d.ts +46 -0
  98. package/dist/internal/controlled-process/supervisor-transport.d.ts.map +1 -0
  99. package/dist/internal/controlled-process/supervisor-transport.js +368 -0
  100. package/dist/internal/controlled-process/supervisor-values.d.ts +39 -0
  101. package/dist/internal/controlled-process/supervisor-values.d.ts.map +1 -0
  102. package/dist/internal/controlled-process/supervisor-values.js +38 -0
  103. package/dist/internal/controlled-process/token.d.ts +4 -0
  104. package/dist/internal/controlled-process/token.d.ts.map +1 -0
  105. package/dist/internal/controlled-process/token.js +38 -0
  106. package/dist/internal/controlled-process/values.d.ts +39 -0
  107. package/dist/internal/controlled-process/values.d.ts.map +1 -0
  108. package/dist/internal/controlled-process/values.js +38 -0
  109. package/dist/kernel/cli-agent.d.ts.map +1 -1
  110. package/dist/kernel/cli-agent.js +330 -34
  111. package/dist/kernel/cli-login.d.ts.map +1 -1
  112. package/dist/kernel/cli-login.js +5 -0
  113. package/dist/kernel/env-template.js +1 -0
  114. package/dist/kernel/facets.d.ts.map +1 -1
  115. package/dist/kernel/facets.js +1 -0
  116. package/dist/kernel/keyed.d.ts.map +1 -1
  117. package/dist/kernel/keyed.js +1 -0
  118. package/dist/kernel/login.js +2 -0
  119. package/dist/kernel/options.d.ts +14 -0
  120. package/dist/kernel/options.d.ts.map +1 -1
  121. package/dist/kernel/options.js +3 -0
  122. package/dist/kernel/process-lifecycle-failure.d.ts +5 -0
  123. package/dist/kernel/process-lifecycle-failure.d.ts.map +1 -0
  124. package/dist/kernel/process-lifecycle-failure.js +5 -0
  125. package/dist/kernel/run.d.ts.map +1 -1
  126. package/dist/kernel/run.js +11 -0
  127. package/dist/kernel/runtime.d.ts.map +1 -1
  128. package/dist/kernel/runtime.js +2 -0
  129. package/dist/keyring/resolver.d.ts.map +1 -1
  130. package/dist/keyring/resolver.js +2 -0
  131. package/dist/structured/run-structured.js +1 -0
  132. package/dist/testing/fake-controlled-exec.d.ts +21 -0
  133. package/dist/testing/fake-controlled-exec.d.ts.map +1 -0
  134. package/dist/testing/fake-controlled-exec.js +172 -0
  135. package/dist/testing/fake-exec.d.ts.map +1 -1
  136. package/dist/testing/fake-exec.js +64 -54
  137. package/dist/testing/index.d.ts +1 -0
  138. package/dist/testing/index.d.ts.map +1 -1
  139. package/dist/testing/index.js +1 -0
  140. package/package.json +2 -2
@@ -86,6 +86,7 @@ export function bindMcp(capability, binding) {
86
86
  if (issues.length > 0) {
87
87
  throw new AgentError({
88
88
  code: AGENT_ERROR_CODE.invalidInput,
89
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.invalidInput),
89
90
  message: "MCP server spec contains a literal or forbidden secret",
90
91
  data: {
91
92
  reason: issues
@@ -1 +1 @@
1
- {"version":3,"file":"keyed.d.ts","sourceRoot":"","sources":["../../src/kernel/keyed.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAG3E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAEzE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EACtC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,IAAI,CAWN"}
1
+ {"version":3,"file":"keyed.d.ts","sourceRoot":"","sources":["../../src/kernel/keyed.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAG3E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAEzE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EACtC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,IAAI,CAaN"}
@@ -26,6 +26,7 @@ export function requireKeyedHandler(record, key, agentId, what) {
26
26
  if (handler === null) {
27
27
  throw new AgentError({
28
28
  code: AGENT_ERROR_CODE.invalidInput,
29
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.invalidInput),
29
30
  message: `Agent "${agentId}" does not support ${what}`,
30
31
  data: { reason: `unsupported: ${what}` },
31
32
  agentId,
@@ -57,6 +57,7 @@ function toLoginError(agentId, thrown) {
57
57
  const message = thrown instanceof Error ? thrown.message : String(thrown);
58
58
  return new AgentError({
59
59
  code: AGENT_ERROR_CODE.failed,
60
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.failed),
60
61
  message: redactSecrets(message),
61
62
  data: { exitCode: null, stdoutTail: null, stderrTail: null },
62
63
  cause: thrown,
@@ -66,6 +67,7 @@ function toLoginError(agentId, thrown) {
66
67
  function withAgentId(error, agentId) {
67
68
  return new AgentError({
68
69
  code: error.code,
70
+ classification: error.classification,
69
71
  message: error.message,
70
72
  data: error.data,
71
73
  agentId,
@@ -4,6 +4,7 @@
4
4
  * definitions only ever see the resolved types.
5
5
  */
6
6
  import { type EnvPatch } from "../core/env.js";
7
+ import type { ChildProcessLifecycle, ControlledExec } from "../core/controlled-process.js";
7
8
  import type { GuardFactory } from "./guard.js";
8
9
  export declare const GRANT_KIND: {
9
10
  readonly shell: "shell";
@@ -44,6 +45,17 @@ export type ResolvedLimits = {
44
45
  idleMs: number | null;
45
46
  guards: GuardFactory[];
46
47
  };
48
+ /** Optional run-scoped resources supplied by the embedding host. */
49
+ export type ControlledChildProcessResource = {
50
+ readonly exec: ControlledExec;
51
+ readonly lifecycle: ChildProcessLifecycle;
52
+ };
53
+ export type RunResources = {
54
+ childProcess?: ControlledChildProcessResource;
55
+ };
56
+ export type ResolvedRunResources = {
57
+ childProcess: ControlledChildProcessResource | null;
58
+ };
47
59
  type BaseRunOptions = {
48
60
  prompt: string;
49
61
  workspace: string;
@@ -52,6 +64,7 @@ type BaseRunOptions = {
52
64
  sandbox?: Sandbox;
53
65
  env?: EnvPatch;
54
66
  limits?: Limits;
67
+ resources?: RunResources;
55
68
  signal?: AbortSignal;
56
69
  };
57
70
  export type RunOptions = BaseRunOptions & {
@@ -65,6 +78,7 @@ export type ResolvedRunOptions = {
65
78
  sandbox: ResolvedSandbox;
66
79
  env: EnvPatch;
67
80
  limits: ResolvedLimits;
81
+ resources: ResolvedRunResources;
68
82
  };
69
83
  export declare function resolveSandbox(sandbox: Sandbox | undefined): ResolvedSandbox;
70
84
  export declare function resolveLimits(limits: Limits | undefined): ResolvedLimits;
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/kernel/options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,UAAU;;;CAGb,CAAC;AAEX,MAAM,MAAM,KAAK,GACb;IAAE,IAAI,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,OAAO,UAAU,CAAC,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE3E,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,OAAO,YAAY,CAAC,IAAI,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,YAAY,CAAC,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC;AAE7D,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,YAAY,CAAC,IAAI,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,YAAY,CAAC,QAAQ,CAAC;IAAC,MAAM,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,eAAe,CAAC;IACzB,GAAG,EAAE,QAAQ,CAAC;IACd,MAAM,EAAE,cAAc,CAAC;CACxB,CAAC;AAEF,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,eAAe,CAQ5E;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAMxE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,kBAAkB,CAUzE"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/kernel/options.ts"],"names":[],"mappings":"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"}
@@ -37,5 +37,8 @@ export function resolveRunOptions(options) {
37
37
  sandbox: resolveSandbox(options.sandbox),
38
38
  env: options.env ?? EMPTY_ENV_PATCH,
39
39
  limits: resolveLimits(options.limits),
40
+ resources: {
41
+ childProcess: options.resources?.childProcess ?? null,
42
+ },
40
43
  };
41
44
  }
@@ -0,0 +1,5 @@
1
+ import { AGENT_ERROR_CODE, type AgentError } from "../core/error.js";
2
+ type ProcessLifecycleFailure = AgentError<typeof AGENT_ERROR_CODE.failed>;
3
+ export declare function isProcessLifecycleFailure(value: unknown): value is ProcessLifecycleFailure;
4
+ export {};
5
+ //# sourceMappingURL=process-lifecycle-failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-lifecycle-failure.d.ts","sourceRoot":"","sources":["../../src/kernel/process-lifecycle-failure.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEhB,KAAK,UAAU,EAEhB,MAAM,kBAAkB,CAAC;AAE1B,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE1E,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,uBAAuB,CAKlC"}
@@ -0,0 +1,5 @@
1
+ import { AGENT_ERROR_CODE, AGENT_FAILURE_CLASS, isAgentError, } from "../core/error.js";
2
+ export function isProcessLifecycleFailure(value) {
3
+ return (isAgentError(value, AGENT_ERROR_CODE.failed) &&
4
+ value.failureClass === AGENT_FAILURE_CLASS.infrastructure);
5
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/kernel/run.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,KAAK,EAAU,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAIV,SAAS,EAEV,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,eAAe,EAAc,MAAM,iBAAiB,CAAC;AAGnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASvD,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AA4QF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAExD"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/kernel/run.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,KAAK,EAAU,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAIV,SAAS,EAEV,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,eAAe,EAAc,MAAM,iBAAiB,CAAC;AAGnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAUvD,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AA0RF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAExD"}
@@ -10,6 +10,7 @@ import { AGENT_ERROR_CODE, AgentError, isAgentError, TIMEOUT_KIND, withRunIdenti
10
10
  import { redactSecrets } from "../core/redact.js";
11
11
  import { RUN_EVENT_TYPE, RUN_OUTCOME } from "../core/run.js";
12
12
  import { createRunHandle, EventBroadcast } from "./handle.js";
13
+ import { isProcessLifecycleFailure } from "./process-lifecycle-failure.js";
13
14
  const GUARD_POLL_MS = 1_000;
14
15
  const RUN_TRIP_KIND = {
15
16
  timeout: "timeout",
@@ -203,6 +204,7 @@ class RunDriver {
203
204
  if (trip.kind === RUN_TRIP_KIND.timeout) {
204
205
  return new AgentError({
205
206
  code: AGENT_ERROR_CODE.timeout,
207
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.timeout),
206
208
  message: `Run exceeded its ${trip.timeoutKind} timeout of ${trip.limitMs}ms`,
207
209
  data: { kind: trip.timeoutKind, limitMs: trip.limitMs },
208
210
  ...this.identity(),
@@ -211,6 +213,7 @@ class RunDriver {
211
213
  if (trip.kind === RUN_TRIP_KIND.limit) {
212
214
  return new AgentError({
213
215
  code: AGENT_ERROR_CODE.limit,
216
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.limit),
214
217
  message: `Guard "${trip.violation.guardId}" tripped: ${trip.violation.reason}`,
215
218
  data: { violation: trip.violation },
216
219
  ...this.identity(),
@@ -218,12 +221,19 @@ class RunDriver {
218
221
  }
219
222
  return new AgentError({
220
223
  code: AGENT_ERROR_CODE.cancelled,
224
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.cancelled),
221
225
  message: "Run was cancelled",
222
226
  data: { reason: trip.reason },
223
227
  ...this.identity(),
224
228
  });
225
229
  }
226
230
  toAgentError(thrown) {
231
+ // Only branded process/lifecycle cleanup evidence overrides the trip that
232
+ // requested termination. Ordinary adapter failures preserve the existing
233
+ // timeout/cancel precedence.
234
+ if (isProcessLifecycleFailure(thrown)) {
235
+ return withRunIdentity(thrown, this.identity());
236
+ }
227
237
  if (this.tripReason !== null) {
228
238
  return this.errorFromTrip(this.tripReason);
229
239
  }
@@ -233,6 +243,7 @@ class RunDriver {
233
243
  const message = thrown instanceof Error ? thrown.message : String(thrown);
234
244
  return new AgentError({
235
245
  code: AGENT_ERROR_CODE.failed,
246
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.failed),
236
247
  message: redactSecrets(message),
237
248
  data: { exitCode: null, stdoutTail: null, stderrTail: null },
238
249
  cause: thrown,
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/kernel/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAA6B,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAE1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,EAOjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,cAAc,CAAC;AAGlE,MAAM,WAAW,KAAK,CAAC,EAAE,SAAS,MAAM,GAAG,MAAM;IAC/C,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC9D,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,GAAG,CAAC,CAAC,EACH,OAAO,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAAC,CAAC,GAC5C,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,MAAM,GAAG,MAAM;IACtD,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,CAAC,IAAI,SAAS,SAAS,eAAe,EAAE,IAAI;IACzE,MAAM,EAAE,IAAI,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAS1D;AAqED,wBAAgB,kBAAkB,CAChC,KAAK,CAAC,IAAI,SAAS,SAAS,eAAe,EAAE,EAC7C,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CA8BtE"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/kernel/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAA6B,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAE1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,EAOjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,cAAc,CAAC;AAGlE,MAAM,WAAW,KAAK,CAAC,EAAE,SAAS,MAAM,GAAG,MAAM;IAC/C,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC9D,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,GAAG,CAAC,CAAC,EACH,OAAO,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAAC,CAAC,GAC5C,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,MAAM,GAAG,MAAM;IACtD,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,CAAC,IAAI,SAAS,SAAS,eAAe,EAAE,IAAI;IACzE,MAAM,EAAE,IAAI,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAS1D;AAqED,wBAAgB,kBAAkB,CAChC,KAAK,CAAC,IAAI,SAAS,SAAS,eAAe,EAAE,EAC7C,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAoCtE"}
@@ -84,6 +84,7 @@ export function createAgentRuntime(options) {
84
84
  if (bound.has(definition.id)) {
85
85
  throw new AgentError({
86
86
  code: AGENT_ERROR_CODE.invalidInput,
87
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.invalidInput),
87
88
  message: `Duplicate agent id "${definition.id}"`,
88
89
  data: { reason: `agent id "${definition.id}" registered twice` },
89
90
  });
@@ -97,6 +98,7 @@ export function createAgentRuntime(options) {
97
98
  if (agent === undefined) {
98
99
  throw new AgentError({
99
100
  code: AGENT_ERROR_CODE.invalidInput,
101
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.invalidInput),
100
102
  message: `Unknown agent id "${id}"`,
101
103
  data: { reason: `no agent registered with id "${id}"` },
102
104
  });
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/keyring/resolver.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,KAAK,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;AAiBlD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,cAAc,CAEhB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,mBAAmB,GAC1B,cAAc,CA0BhB"}
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/keyring/resolver.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,KAAK,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;AAiBlD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,cAAc,CAEhB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,mBAAmB,GAC1B,cAAc,CA4BhB"}
@@ -27,6 +27,7 @@ export function createKeyringResolver(options, loader) {
27
27
  catch (error) {
28
28
  throw new AgentError({
29
29
  code: AGENT_ERROR_CODE.failed,
30
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.failed),
30
31
  message: `Keyring secret "${id}" could not be read`,
31
32
  data: { exitCode: null, stdoutTail: null, stderrTail: null },
32
33
  cause: error,
@@ -55,6 +56,7 @@ async function loadKeyringModule(loader) {
55
56
  function keyringNotInstalledError(cause) {
56
57
  return new AgentError({
57
58
  code: AGENT_ERROR_CODE.notAvailable,
59
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.notAvailable),
58
60
  message: "Keyring peer is not installed",
59
61
  data: { cause: NOT_AVAILABLE_CAUSE.notInstalled },
60
62
  cause,
@@ -168,6 +168,7 @@ async function driveStructured(input, broadcast) {
168
168
  }
169
169
  const errorOptions = {
170
170
  code: AGENT_ERROR_CODE.outputRejected,
171
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.outputRejected),
171
172
  message: "Structured output contract was not satisfied within the repair budget",
172
173
  data: { issues: lastIssues, attempts: attempts.length },
173
174
  agentId: input.agentId,
@@ -0,0 +1,21 @@
1
+ import type { ChildProcessCompletion, ChildProcessIdentity, ChildProcessTerminationResult, ControlledExec } from "../core/controlled-process.js";
2
+ import type { ExecChunk, ExecSpawnOptions } from "../core/ports.js";
3
+ export type FakeControlledExecScript = {
4
+ readonly chunks?: readonly ExecChunk[];
5
+ readonly completion?: ChildProcessCompletion;
6
+ readonly completionFailure?: unknown;
7
+ readonly requestCompletion?: ChildProcessCompletion;
8
+ readonly waitsForTermination?: boolean;
9
+ readonly closesOutput?: boolean;
10
+ readonly chunkFailure?: unknown;
11
+ };
12
+ export type FakeControlledExec = ControlledExec & {
13
+ readonly spawns: ExecSpawnOptions[];
14
+ readonly identities: ChildProcessIdentity[];
15
+ readonly terminationRequests: number[];
16
+ readonly outputReturns: number[];
17
+ readonly completionSubscriptions: number[];
18
+ readonly recoveryCalls: ChildProcessIdentity[];
19
+ };
20
+ export declare function createFakeControlledExec(scripts?: readonly FakeControlledExecScript[], recoveryResults?: readonly ChildProcessTerminationResult[]): FakeControlledExec;
21
+ //# sourceMappingURL=fake-controlled-exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-controlled-exec.d.ts","sourceRoot":"","sources":["../../src/testing/fake-controlled-exec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,sBAAsB,EACtB,oBAAoB,EAEpB,6BAA6B,EAC7B,cAAc,EACf,MAAM,+BAA+B,CAAC;AAOvC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpE,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,CAAC;IAC7C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IACpD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAAG;IAChD,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,oBAAoB,EAAE,CAAC;IAC5C,QAAQ,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,aAAa,EAAE,oBAAoB,EAAE,CAAC;CAChD,CAAC;AAiBF,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,SAAS,wBAAwB,EAAO,EACjD,eAAe,GAAE,SAAS,6BAA6B,EAAO,GAC7D,kBAAkB,CAkJpB"}
@@ -0,0 +1,172 @@
1
+ import { AsyncQueue } from "../core/async-queue.js";
2
+ import { CHILD_PROCESS_ABSENCE_PROOF, CHILD_PROCESS_TERMINATION_EVIDENCE_KIND, CHILD_PROCESS_TERMINATION_KIND, CHILD_PROCESS_UNKILLABLE_REASON, } from "../core/controlled-process.js";
3
+ const DEFAULT_COMPLETION = {
4
+ kind: CHILD_PROCESS_TERMINATION_KIND.absent,
5
+ proof: CHILD_PROCESS_ABSENCE_PROOF.supervisorProbe,
6
+ workerExit: { code: 0, signal: null },
7
+ };
8
+ const DEFAULT_REQUEST_COMPLETION = {
9
+ kind: CHILD_PROCESS_TERMINATION_KIND.absent,
10
+ proof: CHILD_PROCESS_ABSENCE_PROOF.supervisorProbe,
11
+ workerExit: null,
12
+ };
13
+ const DEFAULT_RECOVERY = {
14
+ kind: CHILD_PROCESS_TERMINATION_KIND.unkillable,
15
+ reason: CHILD_PROCESS_UNKILLABLE_REASON.supervisorUnreachable,
16
+ };
17
+ export function createFakeControlledExec(scripts = [], recoveryResults = []) {
18
+ const remaining = [...scripts];
19
+ const recoveries = [...recoveryResults];
20
+ const spawns = [];
21
+ const identities = [];
22
+ const terminationRequests = [];
23
+ const outputReturns = [];
24
+ const completionSubscriptions = [];
25
+ const recoveryCalls = [];
26
+ let nextPid = 10_000;
27
+ return {
28
+ spawns,
29
+ identities,
30
+ terminationRequests,
31
+ outputReturns,
32
+ completionSubscriptions,
33
+ recoveryCalls,
34
+ spawn: async (options, lifecycle) => {
35
+ const spawnIndex = spawns.length;
36
+ spawns.push(options);
37
+ terminationRequests.push(0);
38
+ outputReturns.push(0);
39
+ completionSubscriptions.push(0);
40
+ const identity = {
41
+ pid: nextPid,
42
+ processStartToken: `fake-process-start-token-${nextPid}`,
43
+ };
44
+ nextPid += 1;
45
+ identities.push(identity);
46
+ await lifecycle.beforeExec(identity);
47
+ const script = remaining.shift() ?? {};
48
+ const chunks = new AsyncQueue();
49
+ for (const chunk of script.chunks ?? []) {
50
+ chunks.push(chunk);
51
+ }
52
+ let resolveCompletion = () => { };
53
+ let rejectCompletion = () => { };
54
+ const completion = new Promise((resolve, reject) => {
55
+ resolveCompletion = resolve;
56
+ rejectCompletion = reject;
57
+ });
58
+ void completion.catch(() => undefined);
59
+ const originalThen = completion.then.bind(completion);
60
+ const thenProperty = ["th", "en"].join("");
61
+ const publicCompletion = new Proxy(completion, {
62
+ get: (target, property) => {
63
+ if (property === thenProperty) {
64
+ return (...args) => {
65
+ completionSubscriptions[spawnIndex] =
66
+ (completionSubscriptions[spawnIndex] ?? 0) + 1;
67
+ return originalThen(...args);
68
+ };
69
+ }
70
+ return Reflect.get(target, property, target);
71
+ },
72
+ });
73
+ let settled = false;
74
+ const settle = async (result) => {
75
+ if (settled) {
76
+ return completion.then(() => undefined);
77
+ }
78
+ settled = true;
79
+ if (result.kind === CHILD_PROCESS_TERMINATION_KIND.absent ||
80
+ script.closesOutput === true) {
81
+ chunks.end();
82
+ }
83
+ try {
84
+ if (result.kind === CHILD_PROCESS_TERMINATION_KIND.absent) {
85
+ await lifecycle.afterTermination(liveOrOfflineEvidence(identity, result));
86
+ }
87
+ resolveCompletion(result);
88
+ }
89
+ catch (error) {
90
+ rejectCompletion(error);
91
+ }
92
+ };
93
+ const failCompletion = () => {
94
+ if (settled)
95
+ return;
96
+ settled = true;
97
+ chunks.end();
98
+ rejectCompletion(script.completionFailure);
99
+ };
100
+ if (script.waitsForTermination !== true) {
101
+ if (script.completionFailure !== undefined) {
102
+ failCompletion();
103
+ }
104
+ else {
105
+ void settle(script.completion ?? DEFAULT_COMPLETION);
106
+ }
107
+ }
108
+ let requested = null;
109
+ const output = {
110
+ [Symbol.asyncIterator]: () => {
111
+ const iterator = chunks[Symbol.asyncIterator]();
112
+ return {
113
+ next: () => script.chunkFailure === undefined
114
+ ? iterator.next()
115
+ : Promise.reject(script.chunkFailure),
116
+ return: async () => {
117
+ outputReturns[spawnIndex] = (outputReturns[spawnIndex] ?? 0) + 1;
118
+ chunks.end();
119
+ return { value: undefined, done: true };
120
+ },
121
+ };
122
+ },
123
+ };
124
+ return {
125
+ chunks: output,
126
+ completion: publicCompletion,
127
+ requestTermination: () => {
128
+ requested ??= (async () => {
129
+ terminationRequests[spawnIndex] =
130
+ (terminationRequests[spawnIndex] ?? 0) + 1;
131
+ await settle(script.requestCompletion ?? DEFAULT_REQUEST_COMPLETION);
132
+ return completion;
133
+ })();
134
+ return requested;
135
+ },
136
+ };
137
+ },
138
+ recovery: {
139
+ recover: async (identity, lifecycle) => {
140
+ recoveryCalls.push(identity);
141
+ const result = recoveries.shift() ?? DEFAULT_RECOVERY;
142
+ if (result.kind === CHILD_PROCESS_TERMINATION_KIND.absent &&
143
+ result.proof !== CHILD_PROCESS_ABSENCE_PROOF.releasedReceipt) {
144
+ await lifecycle.afterTermination(offlineAbsenceEvidence(identity, result.proof));
145
+ }
146
+ return result;
147
+ },
148
+ },
149
+ };
150
+ }
151
+ function liveOrOfflineEvidence(identity, result) {
152
+ if (result.kind === CHILD_PROCESS_TERMINATION_KIND.absent &&
153
+ result.workerExit !== null) {
154
+ return {
155
+ kind: CHILD_PROCESS_TERMINATION_EVIDENCE_KIND.liveChildClose,
156
+ identity,
157
+ proof: result.proof,
158
+ workerExit: result.workerExit,
159
+ };
160
+ }
161
+ if (result.kind !== CHILD_PROCESS_TERMINATION_KIND.absent) {
162
+ throw new Error("Only absent completion may close a child lifecycle.");
163
+ }
164
+ return offlineAbsenceEvidence(identity, result.proof);
165
+ }
166
+ function offlineAbsenceEvidence(identity, proof) {
167
+ return {
168
+ kind: CHILD_PROCESS_TERMINATION_EVIDENCE_KIND.offlineAbsence,
169
+ identity,
170
+ proof,
171
+ };
172
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"fake-exec.d.ts","sourceRoot":"","sources":["../../src/testing/fake-exec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,gBAAgB,EAEhB,2BAA2B,EAC5B,MAAM,kBAAkB,CAAC;AAG1B,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;QACR,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;KAC5B,KACE,IAAI,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,CAAC,gBAAgB,GAAG,2BAA2B,CAAC,EAAE,CAAC;IACpE,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;IACjC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC;AAEF,wBAAgB,QAAQ,CAAC,OAAO,GAAE,cAAc,EAAO,GAAG,QAAQ,CA4EjE"}
1
+ {"version":3,"file":"fake-exec.d.ts","sourceRoot":"","sources":["../../src/testing/fake-exec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,gBAAgB,EAEhB,2BAA2B,EAC5B,MAAM,kBAAkB,CAAC;AAG1B,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;QACR,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;KAC5B,KACE,IAAI,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,CAAC,gBAAgB,GAAG,2BAA2B,CAAC,EAAE,CAAC;IACpE,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;IACjC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC;AAWF,wBAAgB,QAAQ,CAAC,OAAO,GAAE,cAAc,EAAO,GAAG,QAAQ,CAmFjE"}
@@ -1,69 +1,79 @@
1
1
  import { AsyncQueue } from "../core/async-queue.js";
2
2
  import { OUTPUT_CHANNEL, PROCESS_SIGNAL } from "../core/values.js";
3
+ function resolveFakeCommand(missingCommands, command) {
4
+ return Promise.resolve(missingCommands.has(command) ? null : `/fake/bin/${command}`);
5
+ }
3
6
  export function fakeExec(scripts = []) {
4
7
  const remaining = [...scripts];
5
8
  const spawns = [];
6
9
  const stdinWrites = [];
7
10
  const kills = [];
8
11
  const missingCommands = new Set();
12
+ const spawnFake = (options) => {
13
+ spawns.push(options);
14
+ const script = remaining.shift() ?? {};
15
+ const killSignals = [];
16
+ const writes = [];
17
+ kills.push(killSignals);
18
+ stdinWrites.push(writes);
19
+ const chunks = new AsyncQueue();
20
+ let settleExit = () => { };
21
+ const exit = new Promise((resolve) => {
22
+ settleExit = resolve;
23
+ });
24
+ let settleTermination = () => { };
25
+ const termination = new Promise((resolve) => {
26
+ settleTermination = resolve;
27
+ });
28
+ let finished = false;
29
+ const finish = (value) => {
30
+ if (finished) {
31
+ return;
32
+ }
33
+ finished = true;
34
+ chunks.end();
35
+ settleTermination();
36
+ settleExit(value);
37
+ };
38
+ const controls = {
39
+ stdout: (text) => chunks.push({ channel: OUTPUT_CHANNEL.stdout, text }),
40
+ stderr: (text) => chunks.push({ channel: OUTPUT_CHANNEL.stderr, text }),
41
+ exit: finish,
42
+ };
43
+ for (const chunk of script.chunks ?? []) {
44
+ chunks.push(chunk);
45
+ }
46
+ if (script.hang !== true) {
47
+ finish({
48
+ code: script.exitCode ?? 0,
49
+ signal: script.exitSignal ?? null,
50
+ });
51
+ }
52
+ return {
53
+ chunks,
54
+ exit,
55
+ writeStdin: (text) => {
56
+ writes.push(text);
57
+ script.onWrite?.(text, controls);
58
+ },
59
+ endStdin: () => { },
60
+ kill: (signal) => {
61
+ killSignals.push(signal);
62
+ if (signal === PROCESS_SIGNAL.sigterm &&
63
+ script.ignoreSigterm === true) {
64
+ return;
65
+ }
66
+ finish({ code: null, signal });
67
+ },
68
+ awaitTerminationEscalation: () => termination,
69
+ };
70
+ };
9
71
  return {
10
72
  spawns,
11
73
  stdinWrites,
12
74
  kills,
13
75
  missingCommands,
14
- which: (command) => Promise.resolve(missingCommands.has(command) ? null : `/fake/bin/${command}`),
15
- spawn: (options) => {
16
- spawns.push(options);
17
- const script = remaining.shift() ?? {};
18
- const killSignals = [];
19
- const writes = [];
20
- kills.push(killSignals);
21
- stdinWrites.push(writes);
22
- const chunks = new AsyncQueue();
23
- for (const chunk of script.chunks ?? []) {
24
- chunks.push(chunk);
25
- }
26
- let settleExit = () => { };
27
- const exit = new Promise((resolve) => {
28
- settleExit = resolve;
29
- });
30
- let finished = false;
31
- const finish = (value) => {
32
- if (finished) {
33
- return;
34
- }
35
- finished = true;
36
- chunks.end();
37
- settleExit(value);
38
- };
39
- const controls = {
40
- stdout: (text) => chunks.push({ channel: OUTPUT_CHANNEL.stdout, text }),
41
- stderr: (text) => chunks.push({ channel: OUTPUT_CHANNEL.stderr, text }),
42
- exit: finish,
43
- };
44
- if (script.hang !== true) {
45
- finish({
46
- code: script.exitCode ?? 0,
47
- signal: script.exitSignal ?? null,
48
- });
49
- }
50
- return {
51
- chunks,
52
- exit,
53
- writeStdin: (text) => {
54
- writes.push(text);
55
- script.onWrite?.(text, controls);
56
- },
57
- endStdin: () => { },
58
- kill: (signal) => {
59
- killSignals.push(signal);
60
- if (signal === PROCESS_SIGNAL.sigterm &&
61
- script.ignoreSigterm === true) {
62
- return;
63
- }
64
- finish({ code: null, signal });
65
- },
66
- };
67
- },
76
+ which: (command) => resolveFakeCommand(missingCommands, command),
77
+ spawn: spawnFake,
68
78
  };
69
79
  }
@@ -5,6 +5,7 @@
5
5
  */
6
6
  export { FAKE_AGENT_BEHAVIOR_KIND, type FakeAgentBehavior, type FakeAgentCall, type FakeAgentDefinition, fakeAgent, } from "./fake-agent.js";
7
7
  export { type FakeClock, fakeClock } from "./fake-clock.js";
8
+ export { createFakeControlledExec, type FakeControlledExec, type FakeControlledExecScript, } from "./fake-controlled-exec.js";
8
9
  export { type FakeExec, type FakeExecScript, fakeExec } from "./fake-exec.js";
9
10
  export { fakeSecretResolver } from "./fake-secrets.js";
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,wBAAwB,EACxB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,SAAS,GACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,wBAAwB,EACxB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,SAAS,GACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -5,5 +5,6 @@
5
5
  */
6
6
  export { FAKE_AGENT_BEHAVIOR_KIND, fakeAgent, } from "./fake-agent.js";
7
7
  export { fakeClock } from "./fake-clock.js";
8
+ export { createFakeControlledExec, } from "./fake-controlled-exec.js";
8
9
  export { fakeExec } from "./fake-exec.js";
9
10
  export { fakeSecretResolver } from "./fake-secrets.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alpacakit/agents",
3
- "version": "0.1.0-beta.19",
3
+ "version": "0.1.0-beta.21",
4
4
  "description": "Run AI coding agents programmatically: execute, stream, classify failures, fail over.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "zod": "^4.3.6",
52
- "@alpacakit/core": "0.1.0-beta.19"
52
+ "@alpacakit/core": "0.1.0-beta.21"
53
53
  },
54
54
  "devDependencies": {
55
55
  "typescript": "^5.9.3",