@memberjunction/ai-agent-harness 0.0.0 → 6.1.0-edge.1

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 (71) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +192 -27
  3. package/dist/HarnessAgentBase.d.ts +254 -0
  4. package/dist/HarnessAgentBase.d.ts.map +1 -0
  5. package/dist/HarnessAgentBase.js +813 -0
  6. package/dist/HarnessAgentBase.js.map +1 -0
  7. package/dist/HarnessAgentType.d.ts +39 -0
  8. package/dist/HarnessAgentType.d.ts.map +1 -0
  9. package/dist/HarnessAgentType.js +50 -0
  10. package/dist/HarnessAgentType.js.map +1 -0
  11. package/dist/adapters/BaseCliHarnessAdapter.d.ts +93 -0
  12. package/dist/adapters/BaseCliHarnessAdapter.d.ts.map +1 -0
  13. package/dist/adapters/BaseCliHarnessAdapter.js +184 -0
  14. package/dist/adapters/BaseCliHarnessAdapter.js.map +1 -0
  15. package/dist/adapters/BaseHarnessAdapter.d.ts +114 -0
  16. package/dist/adapters/BaseHarnessAdapter.d.ts.map +1 -0
  17. package/dist/adapters/BaseHarnessAdapter.js +86 -0
  18. package/dist/adapters/BaseHarnessAdapter.js.map +1 -0
  19. package/dist/adapters/ClaudeCodeCliAdapter.d.ts +104 -0
  20. package/dist/adapters/ClaudeCodeCliAdapter.d.ts.map +1 -0
  21. package/dist/adapters/ClaudeCodeCliAdapter.js +268 -0
  22. package/dist/adapters/ClaudeCodeCliAdapter.js.map +1 -0
  23. package/dist/adapters/CodexAdapter.d.ts +27 -0
  24. package/dist/adapters/CodexAdapter.d.ts.map +1 -0
  25. package/dist/adapters/CodexAdapter.js +117 -0
  26. package/dist/adapters/CodexAdapter.js.map +1 -0
  27. package/dist/adapters/GeminiCliAdapter.d.ts +25 -0
  28. package/dist/adapters/GeminiCliAdapter.d.ts.map +1 -0
  29. package/dist/adapters/GeminiCliAdapter.js +98 -0
  30. package/dist/adapters/GeminiCliAdapter.js.map +1 -0
  31. package/dist/adapters/OpenCodeAdapter.d.ts +23 -0
  32. package/dist/adapters/OpenCodeAdapter.d.ts.map +1 -0
  33. package/dist/adapters/OpenCodeAdapter.js +104 -0
  34. package/dist/adapters/OpenCodeAdapter.js.map +1 -0
  35. package/dist/adapters/PiAdapter.d.ts +73 -0
  36. package/dist/adapters/PiAdapter.d.ts.map +1 -0
  37. package/dist/adapters/PiAdapter.js +237 -0
  38. package/dist/adapters/PiAdapter.js.map +1 -0
  39. package/dist/adapters/StdioJsonAdapter.d.ts +43 -0
  40. package/dist/adapters/StdioJsonAdapter.d.ts.map +1 -0
  41. package/dist/adapters/StdioJsonAdapter.js +109 -0
  42. package/dist/adapters/StdioJsonAdapter.js.map +1 -0
  43. package/dist/index.d.ts +26 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +28 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/sandbox/ChildProcessExecutor.d.ts +41 -0
  48. package/dist/sandbox/ChildProcessExecutor.d.ts.map +1 -0
  49. package/dist/sandbox/ChildProcessExecutor.js +86 -0
  50. package/dist/sandbox/ChildProcessExecutor.js.map +1 -0
  51. package/dist/sandbox/DockerSandboxProvider.d.ts +64 -0
  52. package/dist/sandbox/DockerSandboxProvider.d.ts.map +1 -0
  53. package/dist/sandbox/DockerSandboxProvider.js +176 -0
  54. package/dist/sandbox/DockerSandboxProvider.js.map +1 -0
  55. package/dist/sandbox/ISandboxProvider.d.ts +71 -0
  56. package/dist/sandbox/ISandboxProvider.d.ts.map +1 -0
  57. package/dist/sandbox/ISandboxProvider.js +2 -0
  58. package/dist/sandbox/ISandboxProvider.js.map +1 -0
  59. package/dist/sandbox/LocalDirectorySandboxProvider.d.ts +37 -0
  60. package/dist/sandbox/LocalDirectorySandboxProvider.d.ts.map +1 -0
  61. package/dist/sandbox/LocalDirectorySandboxProvider.js +75 -0
  62. package/dist/sandbox/LocalDirectorySandboxProvider.js.map +1 -0
  63. package/dist/sandbox/SandboxExecutor.d.ts +47 -0
  64. package/dist/sandbox/SandboxExecutor.d.ts.map +1 -0
  65. package/dist/sandbox/SandboxExecutor.js +2 -0
  66. package/dist/sandbox/SandboxExecutor.js.map +1 -0
  67. package/dist/types.d.ts +180 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +2 -0
  70. package/dist/types.js.map +1 -0
  71. package/package.json +35 -8
@@ -0,0 +1,104 @@
1
+ import { BaseCliHarnessAdapter, HarnessCliRawEvent } from './BaseCliHarnessAdapter.js';
2
+ import { HarnessCapabilities, HarnessPermissionPolicy, HarnessTurnEvent } from '../types.js';
3
+ import { HarnessProcess } from '../sandbox/SandboxExecutor.js';
4
+ /**
5
+ * Drives Claude Code through its headless CLI. This is the ONLY Claude Code adapter.
6
+ *
7
+ * ## Why not the Claude Agent SDK
8
+ *
9
+ * An SDK-based adapter was built and then deliberately removed. The SDK offers a programmatic
10
+ * permission callback (`canUseTool`) and in-process MCP tools, both genuinely useful — but it runs
11
+ * IN-PROCESS in Node, and no sandbox executor can place an in-process library inside a container.
12
+ *
13
+ * That trade does not survive scrutiny: it buys better permission *hooks* at the cost of any
14
+ * process *isolation*, for a feature whose entire purpose is executing an autonomous agent's shell
15
+ * commands. Worse, an SDK-backed agent configured with `provider: 'docker'` would run outside its
16
+ * sandbox while the config claimed otherwise — the same false-containment failure this design
17
+ * refuses elsewhere. And the asymmetry is decisive: the CLI's missing permission hook is fixable
18
+ * (an MCP permission-prompt tool), while the SDK's missing containment is not.
19
+ *
20
+ * Two incidental findings that removed the remaining arguments for it: the SDK's typing advantage
21
+ * largely evaporated in practice (its message union is too broad to narrow against, so the adapter
22
+ * read fields structurally anyway — exactly what the CLI adapter does), and the SDK is not
23
+ * dependency-free — it ships a ~259 MB platform-specific `claude` binary. It wraps the same program
24
+ * this adapter invokes.
25
+ *
26
+ * So there is one Claude path, and it works in all three deployments: local spawn, local container,
27
+ * cloud container.
28
+ */
29
+ export declare class ClaudeCodeCliAdapter extends BaseCliHarnessAdapter {
30
+ private executable;
31
+ private systemPrompt;
32
+ private didResume;
33
+ private permissionArgs;
34
+ /**
35
+ * Maps MJ's posture onto Claude Code's permission vocabulary.
36
+ *
37
+ * Conservative at both ends, deliberately:
38
+ *
39
+ * - `strict` adds NOTHING, leaving Claude Code's default prompting in place. Headless, those
40
+ * prompts have nowhere to go and every call denies — the correct outcome for a posture whose
41
+ * contract is "no mutation without a human" when MJ has no approval channel yet. Observably
42
+ * useless beats quietly permissive.
43
+ * - `auto` uses `acceptEdits`, NOT `bypassPermissions`. Edits inside the workspace proceed while
44
+ * genuinely dangerous operations still gate; using bypass here would make `auto` and
45
+ * `dangerous` the same setting under two names.
46
+ * - `dangerous` passes `--dangerously-skip-permissions`, which Claude Code's own help restricts
47
+ * to sandboxes with no internet access. Pairing it with the LOCAL provider is a
48
+ * misconfiguration — that provider does not contain the process at all.
49
+ *
50
+ * Allow/deny patterns pass through in Claude Code's own syntax, deny applied last so it wins:
51
+ * an overlapping policy must fail closed.
52
+ *
53
+ * ## Bash patterns are PREFIX-LITERAL — they are hygiene, not a boundary
54
+ *
55
+ * `Bash(git commit:*)` matches only commands that *begin* with `git commit`. Proven live: a
56
+ * `Bash(git:*)` allow paired with a `Bash(git commit:*)` deny let `git -C <path> commit` through,
57
+ * because any flag before the subcommand defeats the prefix. The run failed only because nothing
58
+ * happened to be staged.
59
+ *
60
+ * The consequence is a rule, not a caveat: **do not use a broad `Bash(<tool>:*)` allow and try to
61
+ * carve dangerous subcommands back out with denies.** Deny whole tool names (`Bash` — an exact
62
+ * name match, no prefix involved) or allow only fully-specified commands. Real containment comes
63
+ * from the sandbox provider; with the LOCAL provider there is none, so the policy is all there is.
64
+ */
65
+ ApplyPermissionPolicy(policy: HarnessPermissionPolicy): void;
66
+ /** @inheritdoc */
67
+ get DidResumeSession(): boolean;
68
+ /** @inheritdoc */
69
+ SetSystemPrompt(systemPrompt: string): void;
70
+ protected get ExecutablePath(): string;
71
+ /** @inheritdoc */
72
+ get Capabilities(): HarnessCapabilities;
73
+ protected BuildTurnArgs(input: string, isFirstTurn: boolean): string[];
74
+ protected MapEvent(raw: HarnessCliRawEvent): HarnessTurnEvent | null;
75
+ /**
76
+ * Handles a `result` line, which carries BOTH the turn's usage and its outcome.
77
+ *
78
+ * MapEvent is one-in-one-out, so usage is returned now and the outcome is parked in
79
+ * {@link pendingTerminal} for {@link readEvents} to flush immediately after. Emitting usage
80
+ * first matters: a turn that failed still spent tokens getting there, and the run's cost
81
+ * accounting should see them either way.
82
+ */
83
+ private buildResultEvents;
84
+ /** Turns a `result` message into either a completed turn or a failed one. */
85
+ private buildTerminalEvent;
86
+ /** Concatenates the text blocks of an assistant message. */
87
+ private extractAssistantText;
88
+ /** Terminal event held back while its usage event is emitted first. */
89
+ private pendingTerminal;
90
+ /** The model Claude reported using on this turn. */
91
+ private reportedModel;
92
+ /** @inheritdoc */
93
+ get ReportedModel(): string | undefined;
94
+ /**
95
+ * Flushes the terminal event held back by {@link buildResultEvents}.
96
+ *
97
+ * Overridden so a single `result` line can yield both usage and outcome while MapEvent keeps
98
+ * its simple one-in-one-out shape.
99
+ */
100
+ protected readEvents(proc: HarnessProcess): AsyncIterable<HarnessTurnEvent>;
101
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
102
+ SetExecutable(path: string): void;
103
+ }
104
+ //# sourceMappingURL=ClaudeCodeCliAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClaudeCodeCliAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/ClaudeCodeCliAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,oBAAqB,SAAQ,qBAAqB;IAC3D,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAgB;IAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACa,qBAAqB,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI;IAsB5E,kBAAkB;IAClB,IAAoB,gBAAgB,IAAI,OAAO,CAE9C;IAED,kBAAkB;IACF,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAI3D,SAAS,KAAK,cAAc,IAAI,MAAM,CAErC;IAED,kBAAkB;IAClB,IAAW,YAAY,IAAI,mBAAmB,CAwB7C;IAED,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,EAAE;IAkCtE,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,IAAI;IAiCpE;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IAUzB,6EAA6E;IAC7E,OAAO,CAAC,kBAAkB;IAQ1B,4DAA4D;IAC5D,OAAO,CAAC,oBAAoB;IAiB5B,uEAAuE;IACvE,OAAO,CAAC,eAAe,CAAiC;IAExD,oDAAoD;IACpD,OAAO,CAAC,aAAa,CAAqB;IAE1C,kBAAkB;IAClB,IAAoB,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtD;IAED;;;;;OAKG;cACuB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CAAC,gBAAgB,CAAC;IAW3F,qFAAqF;IAC9E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG3C"}
@@ -0,0 +1,268 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { RegisterClass } from '@memberjunction/global';
8
+ import { BaseCliHarnessAdapter } from './BaseCliHarnessAdapter.js';
9
+ import { BaseHarnessAdapter } from './BaseHarnessAdapter.js';
10
+ /**
11
+ * Drives Claude Code through its headless CLI. This is the ONLY Claude Code adapter.
12
+ *
13
+ * ## Why not the Claude Agent SDK
14
+ *
15
+ * An SDK-based adapter was built and then deliberately removed. The SDK offers a programmatic
16
+ * permission callback (`canUseTool`) and in-process MCP tools, both genuinely useful — but it runs
17
+ * IN-PROCESS in Node, and no sandbox executor can place an in-process library inside a container.
18
+ *
19
+ * That trade does not survive scrutiny: it buys better permission *hooks* at the cost of any
20
+ * process *isolation*, for a feature whose entire purpose is executing an autonomous agent's shell
21
+ * commands. Worse, an SDK-backed agent configured with `provider: 'docker'` would run outside its
22
+ * sandbox while the config claimed otherwise — the same false-containment failure this design
23
+ * refuses elsewhere. And the asymmetry is decisive: the CLI's missing permission hook is fixable
24
+ * (an MCP permission-prompt tool), while the SDK's missing containment is not.
25
+ *
26
+ * Two incidental findings that removed the remaining arguments for it: the SDK's typing advantage
27
+ * largely evaporated in practice (its message union is too broad to narrow against, so the adapter
28
+ * read fields structurally anyway — exactly what the CLI adapter does), and the SDK is not
29
+ * dependency-free — it ships a ~259 MB platform-specific `claude` binary. It wraps the same program
30
+ * this adapter invokes.
31
+ *
32
+ * So there is one Claude path, and it works in all three deployments: local spawn, local container,
33
+ * cloud container.
34
+ */
35
+ let ClaudeCodeCliAdapter = class ClaudeCodeCliAdapter extends BaseCliHarnessAdapter {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.executable = 'claude';
39
+ this.didResume = false;
40
+ this.permissionArgs = [];
41
+ /** Terminal event held back while its usage event is emitted first. */
42
+ this.pendingTerminal = null;
43
+ }
44
+ /**
45
+ * Maps MJ's posture onto Claude Code's permission vocabulary.
46
+ *
47
+ * Conservative at both ends, deliberately:
48
+ *
49
+ * - `strict` adds NOTHING, leaving Claude Code's default prompting in place. Headless, those
50
+ * prompts have nowhere to go and every call denies — the correct outcome for a posture whose
51
+ * contract is "no mutation without a human" when MJ has no approval channel yet. Observably
52
+ * useless beats quietly permissive.
53
+ * - `auto` uses `acceptEdits`, NOT `bypassPermissions`. Edits inside the workspace proceed while
54
+ * genuinely dangerous operations still gate; using bypass here would make `auto` and
55
+ * `dangerous` the same setting under two names.
56
+ * - `dangerous` passes `--dangerously-skip-permissions`, which Claude Code's own help restricts
57
+ * to sandboxes with no internet access. Pairing it with the LOCAL provider is a
58
+ * misconfiguration — that provider does not contain the process at all.
59
+ *
60
+ * Allow/deny patterns pass through in Claude Code's own syntax, deny applied last so it wins:
61
+ * an overlapping policy must fail closed.
62
+ *
63
+ * ## Bash patterns are PREFIX-LITERAL — they are hygiene, not a boundary
64
+ *
65
+ * `Bash(git commit:*)` matches only commands that *begin* with `git commit`. Proven live: a
66
+ * `Bash(git:*)` allow paired with a `Bash(git commit:*)` deny let `git -C <path> commit` through,
67
+ * because any flag before the subcommand defeats the prefix. The run failed only because nothing
68
+ * happened to be staged.
69
+ *
70
+ * The consequence is a rule, not a caveat: **do not use a broad `Bash(<tool>:*)` allow and try to
71
+ * carve dangerous subcommands back out with denies.** Deny whole tool names (`Bash` — an exact
72
+ * name match, no prefix involved) or allow only fully-specified commands. Real containment comes
73
+ * from the sandbox provider; with the LOCAL provider there is none, so the policy is all there is.
74
+ */
75
+ ApplyPermissionPolicy(policy) {
76
+ const args = [];
77
+ switch (policy.Posture) {
78
+ case 'auto':
79
+ args.push('--permission-mode', 'acceptEdits');
80
+ break;
81
+ case 'dangerous':
82
+ args.push('--dangerously-skip-permissions');
83
+ break;
84
+ case 'strict':
85
+ default:
86
+ break;
87
+ }
88
+ if (policy.AllowedTools?.length) {
89
+ args.push('--allowedTools', ...policy.AllowedTools);
90
+ }
91
+ if (policy.DisallowedTools?.length) {
92
+ args.push('--disallowedTools', ...policy.DisallowedTools);
93
+ }
94
+ this.permissionArgs = args;
95
+ }
96
+ /** @inheritdoc */
97
+ get DidResumeSession() {
98
+ return this.didResume;
99
+ }
100
+ /** @inheritdoc */
101
+ SetSystemPrompt(systemPrompt) {
102
+ this.systemPrompt = systemPrompt;
103
+ }
104
+ get ExecutablePath() {
105
+ return this.executable;
106
+ }
107
+ /** @inheritdoc */
108
+ get Capabilities() {
109
+ return {
110
+ SessionResume: true,
111
+ // Killing the process ends the turn immediately — the executor owns the process handle.
112
+ MidTurnCancellation: true,
113
+ // FALSE, deliberately. `--output-format stream-json` structures the TRANSPORT, not the
114
+ // model's content — nothing constrains what Claude actually writes inside a turn. Claiming
115
+ // true here told the runtime it need not compensate, and the harness spent five turns
116
+ // inventing step names (`complete`, `respond`, `undefined`) before BaseAgent's retry
117
+ // feedback taught it the Loop vocabulary. Same distinction PiAdapter already documents.
118
+ StructuredOutput: false,
119
+ UsageReporting: true,
120
+ // ApplyPermissionPolicy below translates posture + allow/deny into real launch flags.
121
+ PermissionPolicy: true,
122
+ // Claude Code CAN intercept permissions, but only through an MCP permission-prompt tool
123
+ // that MJ has not stood up yet. Reported false until that exists: claiming interception
124
+ // the adapter does not implement would let mutating operations through unreviewed while
125
+ // the strict posture believed it was gating them. This is the one capability the removed
126
+ // SDK adapter had and this one does not, and it is a prerequisite for `strict`.
127
+ PermissionHooks: false,
128
+ McpClient: true,
129
+ WorkspaceScoping: true,
130
+ ModelSelection: true,
131
+ };
132
+ }
133
+ BuildTurnArgs(input, isFirstTurn) {
134
+ const args = ['-p', input, '--output-format', 'stream-json', '--verbose'];
135
+ // Claude Code persists sessions to its own on-disk store, so resuming needs no live process
136
+ // — which is why this works at all despite the process dying after every turn. If the store
137
+ // has pruned the session the CLI starts fresh rather than failing, so an optimistic resume
138
+ // degrades to a cold session instead of breaking the run.
139
+ if (isFirstTurn && this.config?.ResumeSessionId) {
140
+ this.sessionId = this.config.ResumeSessionId;
141
+ this.didResume = true;
142
+ }
143
+ // APPEND rather than replace: Claude Code's own system prompt carries its tool definitions
144
+ // and sandbox conventions, and replacing it would break the harness to enforce our envelope.
145
+ // Appending puts MJ's contract at system level, where it outranks the conversational habit
146
+ // that was costing a retry on turn one.
147
+ if (isFirstTurn && this.systemPrompt) {
148
+ args.push('--append-system-prompt', this.systemPrompt);
149
+ }
150
+ // Pass --resume when continuing WITHIN a run (turn 2+) OR when continuing a PRIOR run's
151
+ // session on turn 1. Gating on `!isFirstTurn` alone silently defeated cross-run resume: the
152
+ // session id was looked up and assigned, the log said "Resuming...", and the flag was never
153
+ // actually passed — so Claude started cold and MapEvent overwrote the id with the new one.
154
+ // The run then recorded a different session than the one it claimed to resume.
155
+ if (this.sessionId && (!isFirstTurn || this.didResume)) {
156
+ args.push('--resume', this.sessionId);
157
+ }
158
+ if (this.config?.Model) {
159
+ args.push('--model', this.config.Model);
160
+ }
161
+ // Per-invocation, not per-session: the process is new every turn, so a policy applied only
162
+ // at session start would silently lapse from turn 2 onward.
163
+ args.push(...this.permissionArgs);
164
+ return args;
165
+ }
166
+ MapEvent(raw) {
167
+ const session = this.readString(raw, 'session_id');
168
+ if (session) {
169
+ this.sessionId = session;
170
+ }
171
+ switch (this.readString(raw, 'type')) {
172
+ case 'assistant': {
173
+ // Claude reports the model it actually used on each assistant message. Capture it so
174
+ // accounting reflects reality rather than the model we assumed.
175
+ const message = this.readObject(raw, 'message');
176
+ const model = message ? this.readString(message, 'model') : undefined;
177
+ if (model) {
178
+ this.reportedModel = model;
179
+ }
180
+ const text = this.extractAssistantText(raw);
181
+ return text ? { Type: 'assistant-text', Text: text } : null;
182
+ }
183
+ case 'result': {
184
+ const usage = this.readObject(raw, 'usage');
185
+ if (usage) {
186
+ // Usage arrives on the same message as the result. It is emitted as its own
187
+ // event so the accumulation loop stays uniform across every adapter, and so a
188
+ // turn that errors still reports what it spent getting there.
189
+ return this.buildResultEvents(raw, usage);
190
+ }
191
+ return this.buildTerminalEvent(raw);
192
+ }
193
+ default:
194
+ return null;
195
+ }
196
+ }
197
+ /**
198
+ * Handles a `result` line, which carries BOTH the turn's usage and its outcome.
199
+ *
200
+ * MapEvent is one-in-one-out, so usage is returned now and the outcome is parked in
201
+ * {@link pendingTerminal} for {@link readEvents} to flush immediately after. Emitting usage
202
+ * first matters: a turn that failed still spent tokens getting there, and the run's cost
203
+ * accounting should see them either way.
204
+ */
205
+ buildResultEvents(raw, usage) {
206
+ this.pendingTerminal = this.buildTerminalEvent(raw);
207
+ return {
208
+ Type: 'usage',
209
+ InputTokens: this.readNumber(usage, 'input_tokens') ?? 0,
210
+ OutputTokens: this.readNumber(usage, 'output_tokens') ?? 0,
211
+ CostUsd: this.readNumber(raw, 'total_cost_usd'),
212
+ };
213
+ }
214
+ /** Turns a `result` message into either a completed turn or a failed one. */
215
+ buildTerminalEvent(raw) {
216
+ const text = this.readString(raw, 'result') ?? '';
217
+ const isError = raw['is_error'] === true;
218
+ return isError
219
+ ? { Type: 'session-error', Error: text || 'Claude Code reported an error' }
220
+ : { Type: 'turn-complete', RawText: text };
221
+ }
222
+ /** Concatenates the text blocks of an assistant message. */
223
+ extractAssistantText(raw) {
224
+ const message = this.readObject(raw, 'message');
225
+ const content = message?.['content'];
226
+ if (!Array.isArray(content)) {
227
+ return '';
228
+ }
229
+ return content
230
+ .map((block) => {
231
+ if (block === null || typeof block !== 'object') {
232
+ return '';
233
+ }
234
+ const asRecord = block;
235
+ return asRecord['type'] === 'text' ? (this.readString(asRecord, 'text') ?? '') : '';
236
+ })
237
+ .join('');
238
+ }
239
+ /** @inheritdoc */
240
+ get ReportedModel() {
241
+ return this.reportedModel;
242
+ }
243
+ /**
244
+ * Flushes the terminal event held back by {@link buildResultEvents}.
245
+ *
246
+ * Overridden so a single `result` line can yield both usage and outcome while MapEvent keeps
247
+ * its simple one-in-one-out shape.
248
+ */
249
+ async *readEvents(proc) {
250
+ for await (const event of super.readEvents(proc)) {
251
+ yield event;
252
+ if (this.pendingTerminal) {
253
+ const terminal = this.pendingTerminal;
254
+ this.pendingTerminal = null;
255
+ yield terminal;
256
+ }
257
+ }
258
+ }
259
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
260
+ SetExecutable(path) {
261
+ this.executable = path;
262
+ }
263
+ };
264
+ ClaudeCodeCliAdapter = __decorate([
265
+ RegisterClass(BaseHarnessAdapter, 'ClaudeCodeCliAdapter')
266
+ ], ClaudeCodeCliAdapter);
267
+ export { ClaudeCodeCliAdapter };
268
+ //# sourceMappingURL=ClaudeCodeCliAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClaudeCodeCliAdapter.js","sourceRoot":"","sources":["../../src/adapters/ClaudeCodeCliAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { BaseCliHarnessAdapter, HarnessCliRawEvent } from './BaseCliHarnessAdapter.js';
2
+ import { HarnessCapabilities, HarnessTurnEvent } from '../types.js';
3
+ /**
4
+ * Drives OpenAI's Codex CLI (`@openai/codex`).
5
+ *
6
+ * Codex ships as a CLI only — the npm package exposes a `bin` and no library entry point — so this
7
+ * goes through {@link BaseCliHarnessAdapter} rather than an SDK.
8
+ *
9
+ * ## About the argv defaults
10
+ *
11
+ * `codex exec --json` is the documented headless form, but coding-agent CLIs move fast and flag
12
+ * names drift between minor versions. Everything version-sensitive is confined to
13
+ * {@link BuildTurnArgs} and the event names in {@link MapEvent}, so adapting to a new Codex release
14
+ * is a change in one small place rather than a redesign — and `AIAgentHarness.ExecutablePath` lets a
15
+ * deployment pin a specific binary without touching code at all.
16
+ */
17
+ export declare class CodexAdapter extends BaseCliHarnessAdapter {
18
+ protected get ExecutablePath(): string;
19
+ private executable;
20
+ /** @inheritdoc */
21
+ get Capabilities(): HarnessCapabilities;
22
+ protected BuildTurnArgs(input: string, isFirstTurn: boolean): string[];
23
+ protected MapEvent(raw: HarnessCliRawEvent): HarnessTurnEvent | null;
24
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
25
+ SetExecutable(path: string): void;
26
+ }
27
+ //# sourceMappingURL=CodexAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodexAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/CodexAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;;;;;GAaG;AACH,qBACa,YAAa,SAAQ,qBAAqB;IACnD,SAAS,KAAK,cAAc,IAAI,MAAM,CAErC;IAED,OAAO,CAAC,UAAU,CAAW;IAE7B,kBAAkB;IAClB,IAAW,YAAY,IAAI,mBAAmB,CAoB7C;IAED,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,EAAE;IAYtE,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,IAAI;IA8CpE,qFAAqF;IAC9E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG3C"}
@@ -0,0 +1,117 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { RegisterClass } from '@memberjunction/global';
8
+ import { BaseCliHarnessAdapter } from './BaseCliHarnessAdapter.js';
9
+ import { BaseHarnessAdapter } from './BaseHarnessAdapter.js';
10
+ /**
11
+ * Drives OpenAI's Codex CLI (`@openai/codex`).
12
+ *
13
+ * Codex ships as a CLI only — the npm package exposes a `bin` and no library entry point — so this
14
+ * goes through {@link BaseCliHarnessAdapter} rather than an SDK.
15
+ *
16
+ * ## About the argv defaults
17
+ *
18
+ * `codex exec --json` is the documented headless form, but coding-agent CLIs move fast and flag
19
+ * names drift between minor versions. Everything version-sensitive is confined to
20
+ * {@link BuildTurnArgs} and the event names in {@link MapEvent}, so adapting to a new Codex release
21
+ * is a change in one small place rather than a redesign — and `AIAgentHarness.ExecutablePath` lets a
22
+ * deployment pin a specific binary without touching code at all.
23
+ */
24
+ let CodexAdapter = class CodexAdapter extends BaseCliHarnessAdapter {
25
+ constructor() {
26
+ super(...arguments);
27
+ this.executable = 'codex';
28
+ }
29
+ get ExecutablePath() {
30
+ return this.executable;
31
+ }
32
+ /** @inheritdoc */
33
+ get Capabilities() {
34
+ return {
35
+ // Codex resumes by threading its session id back on the next invocation.
36
+ SessionResume: true,
37
+ // No constrained-output mode: the turn-end JSON envelope is coaxed by prompt and
38
+ // recovered by BaseAgent's malformed-response retry when the model drifts into prose.
39
+ StructuredOutput: false,
40
+ UsageReporting: true,
41
+ // FALSE: this adapter does not translate MJ's permission policy into harness flags, so a
42
+ // configured posture is INERT here and the runtime warns about it. Not an oversight —
43
+ // Codex CLI's permission flags could not be verified against a real install, and
44
+ // guessing them produces the exact failure this flag exists to surface: a policy that
45
+ // looks applied and is not. Verify against the CLI, then implement
46
+ // ApplyPermissionPolicy and flip this to true.
47
+ PermissionPolicy: false,
48
+ PermissionHooks: false,
49
+ McpClient: true,
50
+ WorkspaceScoping: true,
51
+ ModelSelection: true,
52
+ };
53
+ }
54
+ BuildTurnArgs(input, isFirstTurn) {
55
+ const args = ['exec', '--json'];
56
+ if (!isFirstTurn && this.sessionId) {
57
+ args.push('--resume', this.sessionId);
58
+ }
59
+ if (this.config?.Model) {
60
+ args.push('--model', this.config.Model);
61
+ }
62
+ args.push(input);
63
+ return args;
64
+ }
65
+ MapEvent(raw) {
66
+ // Capture the session id wherever it first appears so the next turn can resume, and so the
67
+ // run can persist it to AIAgentRun.ExternalSessionID for vendor-side log correlation.
68
+ const session = this.readString(raw, 'session_id') ?? this.readString(raw, 'sessionId');
69
+ if (session) {
70
+ this.sessionId = session;
71
+ }
72
+ switch (this.readString(raw, 'type')) {
73
+ case 'assistant_message':
74
+ case 'agent_message': {
75
+ const text = this.readString(raw, 'message') ?? this.readString(raw, 'text');
76
+ return text ? { Type: 'assistant-text', Text: text } : null;
77
+ }
78
+ case 'tool_call':
79
+ case 'exec_command': {
80
+ const description = this.readString(raw, 'command') ?? this.readString(raw, 'name') ?? 'sandbox activity';
81
+ return { Type: 'sandbox-activity', Description: description };
82
+ }
83
+ case 'token_count':
84
+ case 'usage': {
85
+ const usage = this.readObject(raw, 'usage') ?? raw;
86
+ return {
87
+ Type: 'usage',
88
+ InputTokens: this.readNumber(usage, 'input_tokens') ?? 0,
89
+ OutputTokens: this.readNumber(usage, 'output_tokens') ?? 0,
90
+ CostUsd: this.readNumber(usage, 'cost_usd'),
91
+ };
92
+ }
93
+ case 'task_complete':
94
+ case 'turn_complete': {
95
+ const text = this.readString(raw, 'last_agent_message') ??
96
+ this.readString(raw, 'message') ??
97
+ this.readString(raw, 'text') ??
98
+ '';
99
+ return { Type: 'turn-complete', RawText: text };
100
+ }
101
+ case 'error': {
102
+ return { Type: 'session-error', Error: this.readString(raw, 'message') ?? 'Codex reported an error' };
103
+ }
104
+ default:
105
+ return null;
106
+ }
107
+ }
108
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
109
+ SetExecutable(path) {
110
+ this.executable = path;
111
+ }
112
+ };
113
+ CodexAdapter = __decorate([
114
+ RegisterClass(BaseHarnessAdapter, 'CodexAdapter')
115
+ ], CodexAdapter);
116
+ export { CodexAdapter };
117
+ //# sourceMappingURL=CodexAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodexAdapter.js","sourceRoot":"","sources":["../../src/adapters/CodexAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { BaseCliHarnessAdapter, HarnessCliRawEvent } from './BaseCliHarnessAdapter.js';
2
+ import { HarnessCapabilities, HarnessTurnEvent } from '../types.js';
3
+ /**
4
+ * Drives Google's Gemini CLI (`@google/gemini-cli`).
5
+ *
6
+ * `@google/gemini-cli-core` does expose a compilable entry point, but it is the CLI's internals
7
+ * rather than a supported embedding API — depending on it would couple MJ to a package with no
8
+ * stability contract. The CLI surface is the supported one, so this adapter uses it.
9
+ *
10
+ * Gemini CLI is the weakest of the five on session continuity: it is built around one-shot
11
+ * invocations. {@link Capabilities} reports `SessionResume: false` accordingly, which makes the
12
+ * runtime replay accumulated context into each turn — correct, but the token cost grows with turn
13
+ * count, and reporting it honestly here is what lets the run's cost guardrail see that.
14
+ */
15
+ export declare class GeminiCliAdapter extends BaseCliHarnessAdapter {
16
+ private executable;
17
+ protected get ExecutablePath(): string;
18
+ /** @inheritdoc */
19
+ get Capabilities(): HarnessCapabilities;
20
+ protected BuildTurnArgs(input: string, _isFirstTurn: boolean): string[];
21
+ protected MapEvent(raw: HarnessCliRawEvent): HarnessTurnEvent | null;
22
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
23
+ SetExecutable(path: string): void;
24
+ }
25
+ //# sourceMappingURL=GeminiCliAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiCliAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/GeminiCliAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,qBACa,gBAAiB,SAAQ,qBAAqB;IACvD,OAAO,CAAC,UAAU,CAAY;IAE9B,SAAS,KAAK,cAAc,IAAI,MAAM,CAErC;IAED,kBAAkB;IAClB,IAAW,YAAY,IAAI,mBAAmB,CAkB7C;IAED,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,MAAM,EAAE;IAUvE,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,IAAI;IAgCpE,qFAAqF;IAC9E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG3C"}