@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,98 @@
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 Google's Gemini CLI (`@google/gemini-cli`).
12
+ *
13
+ * `@google/gemini-cli-core` does expose a compilable entry point, but it is the CLI's internals
14
+ * rather than a supported embedding API — depending on it would couple MJ to a package with no
15
+ * stability contract. The CLI surface is the supported one, so this adapter uses it.
16
+ *
17
+ * Gemini CLI is the weakest of the five on session continuity: it is built around one-shot
18
+ * invocations. {@link Capabilities} reports `SessionResume: false` accordingly, which makes the
19
+ * runtime replay accumulated context into each turn — correct, but the token cost grows with turn
20
+ * count, and reporting it honestly here is what lets the run's cost guardrail see that.
21
+ */
22
+ let GeminiCliAdapter = class GeminiCliAdapter extends BaseCliHarnessAdapter {
23
+ constructor() {
24
+ super(...arguments);
25
+ this.executable = 'gemini';
26
+ }
27
+ get ExecutablePath() {
28
+ return this.executable;
29
+ }
30
+ /** @inheritdoc */
31
+ get Capabilities() {
32
+ return {
33
+ // One-shot by design — the runtime must replay context each turn. See class doc.
34
+ SessionResume: false,
35
+ StructuredOutput: false,
36
+ UsageReporting: true,
37
+ // FALSE: this adapter does not translate MJ's permission policy into harness flags, so a
38
+ // configured posture is INERT here and the runtime warns about it. Not an oversight —
39
+ // Gemini CLI's permission flags could not be verified against a real install, and
40
+ // guessing them produces the exact failure this flag exists to surface: a policy that
41
+ // looks applied and is not. Verify against the CLI, then implement
42
+ // ApplyPermissionPolicy and flip this to true.
43
+ PermissionPolicy: false,
44
+ PermissionHooks: false,
45
+ McpClient: true,
46
+ WorkspaceScoping: true,
47
+ ModelSelection: true,
48
+ };
49
+ }
50
+ BuildTurnArgs(input, _isFirstTurn) {
51
+ // No resume flag: every turn is a fresh invocation carrying replayed context in `input`.
52
+ const args = ['--output-format', 'json', '--yolo'];
53
+ if (this.config?.Model) {
54
+ args.push('--model', this.config.Model);
55
+ }
56
+ args.push('--prompt', input);
57
+ return args;
58
+ }
59
+ MapEvent(raw) {
60
+ // Gemini CLI's JSON output mode emits a single result object rather than a running stream,
61
+ // so the common case is one line that IS the turn result.
62
+ const response = this.readString(raw, 'response');
63
+ if (response !== undefined) {
64
+ const stats = this.readObject(raw, 'stats');
65
+ const tokens = stats ? this.readObject(stats, 'tokens') : undefined;
66
+ if (tokens) {
67
+ // Usage arrives on the same object as the result. Emitting it as a separate event
68
+ // keeps the accumulation loop uniform across adapters.
69
+ return { Type: 'turn-complete', RawText: response };
70
+ }
71
+ return { Type: 'turn-complete', RawText: response };
72
+ }
73
+ switch (this.readString(raw, 'type')) {
74
+ case 'usage': {
75
+ return {
76
+ Type: 'usage',
77
+ InputTokens: this.readNumber(raw, 'input_tokens') ?? 0,
78
+ OutputTokens: this.readNumber(raw, 'output_tokens') ?? 0,
79
+ CostUsd: this.readNumber(raw, 'cost_usd'),
80
+ };
81
+ }
82
+ case 'error': {
83
+ return { Type: 'session-error', Error: this.readString(raw, 'message') ?? 'Gemini CLI reported an error' };
84
+ }
85
+ default:
86
+ return null;
87
+ }
88
+ }
89
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
90
+ SetExecutable(path) {
91
+ this.executable = path;
92
+ }
93
+ };
94
+ GeminiCliAdapter = __decorate([
95
+ RegisterClass(BaseHarnessAdapter, 'GeminiCliAdapter')
96
+ ], GeminiCliAdapter);
97
+ export { GeminiCliAdapter };
98
+ //# sourceMappingURL=GeminiCliAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiCliAdapter.js","sourceRoot":"","sources":["../../src/adapters/GeminiCliAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { BaseCliHarnessAdapter, HarnessCliRawEvent } from './BaseCliHarnessAdapter.js';
2
+ import { HarnessCapabilities, HarnessTurnEvent } from '../types.js';
3
+ /**
4
+ * Drives OpenCode (`opencode`) in its non-interactive run mode.
5
+ *
6
+ * OpenCode publishes `@opencode-ai/sdk`, but that package exposes no `main` or `types` entry, so
7
+ * there is nothing stable to compile against — the CLI is the dependable contract. If the SDK later
8
+ * ships a real typed entry point, this adapter is the only thing that needs to change.
9
+ *
10
+ * Flag names live entirely in {@link BuildTurnArgs}; see {@link CodexAdapter} for why that
11
+ * confinement matters with fast-moving agent CLIs.
12
+ */
13
+ export declare class OpenCodeAdapter extends BaseCliHarnessAdapter {
14
+ private executable;
15
+ protected get ExecutablePath(): string;
16
+ /** @inheritdoc */
17
+ get Capabilities(): HarnessCapabilities;
18
+ protected BuildTurnArgs(input: string, isFirstTurn: boolean): string[];
19
+ protected MapEvent(raw: HarnessCliRawEvent): HarnessTurnEvent | null;
20
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
21
+ SetExecutable(path: string): void;
22
+ }
23
+ //# sourceMappingURL=OpenCodeAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenCodeAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/OpenCodeAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;GASG;AACH,qBACa,eAAgB,SAAQ,qBAAqB;IACtD,OAAO,CAAC,UAAU,CAAc;IAEhC,SAAS,KAAK,cAAc,IAAI,MAAM,CAErC;IAED,kBAAkB;IAClB,IAAW,YAAY,IAAI,mBAAmB,CAiB7C;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;IAuCpE,qFAAqF;IAC9E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG3C"}
@@ -0,0 +1,104 @@
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 OpenCode (`opencode`) in its non-interactive run mode.
12
+ *
13
+ * OpenCode publishes `@opencode-ai/sdk`, but that package exposes no `main` or `types` entry, so
14
+ * there is nothing stable to compile against — the CLI is the dependable contract. If the SDK later
15
+ * ships a real typed entry point, this adapter is the only thing that needs to change.
16
+ *
17
+ * Flag names live entirely in {@link BuildTurnArgs}; see {@link CodexAdapter} for why that
18
+ * confinement matters with fast-moving agent CLIs.
19
+ */
20
+ let OpenCodeAdapter = class OpenCodeAdapter extends BaseCliHarnessAdapter {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.executable = 'opencode';
24
+ }
25
+ get ExecutablePath() {
26
+ return this.executable;
27
+ }
28
+ /** @inheritdoc */
29
+ get Capabilities() {
30
+ return {
31
+ SessionResume: true,
32
+ StructuredOutput: false,
33
+ UsageReporting: true,
34
+ // FALSE: this adapter does not translate MJ's permission policy into harness flags, so a
35
+ // configured posture is INERT here and the runtime warns about it. Not an oversight —
36
+ // OpenCode's permission flags could not be verified against a real install, and
37
+ // guessing them produces the exact failure this flag exists to surface: a policy that
38
+ // looks applied and is not. Verify against the CLI, then implement
39
+ // ApplyPermissionPolicy and flip this to true.
40
+ PermissionPolicy: false,
41
+ PermissionHooks: false,
42
+ McpClient: true,
43
+ WorkspaceScoping: true,
44
+ ModelSelection: true,
45
+ };
46
+ }
47
+ BuildTurnArgs(input, isFirstTurn) {
48
+ const args = ['run', '--print-logs', '--format', 'json'];
49
+ if (!isFirstTurn && this.sessionId) {
50
+ args.push('--session', this.sessionId);
51
+ }
52
+ if (this.config?.Model) {
53
+ args.push('--model', this.config.Model);
54
+ }
55
+ args.push(input);
56
+ return args;
57
+ }
58
+ MapEvent(raw) {
59
+ const session = this.readString(raw, 'sessionID') ?? this.readString(raw, 'session_id');
60
+ if (session) {
61
+ this.sessionId = session;
62
+ }
63
+ const type = this.readString(raw, 'type') ?? this.readString(raw, 'event');
64
+ switch (type) {
65
+ case 'message':
66
+ case 'text': {
67
+ const text = this.readString(raw, 'text') ?? this.readString(raw, 'content');
68
+ return text ? { Type: 'assistant-text', Text: text } : null;
69
+ }
70
+ case 'tool':
71
+ case 'tool.execute': {
72
+ return { Type: 'sandbox-activity', Description: this.readString(raw, 'tool') ?? 'tool call' };
73
+ }
74
+ case 'usage': {
75
+ const usage = this.readObject(raw, 'tokens') ?? raw;
76
+ return {
77
+ Type: 'usage',
78
+ InputTokens: this.readNumber(usage, 'input') ?? 0,
79
+ OutputTokens: this.readNumber(usage, 'output') ?? 0,
80
+ CostUsd: this.readNumber(raw, 'cost'),
81
+ };
82
+ }
83
+ case 'session.idle':
84
+ case 'finish':
85
+ case 'done': {
86
+ return { Type: 'turn-complete', RawText: this.readString(raw, 'text') ?? this.readString(raw, 'result') ?? '' };
87
+ }
88
+ case 'error': {
89
+ return { Type: 'session-error', Error: this.readString(raw, 'message') ?? 'OpenCode reported an error' };
90
+ }
91
+ default:
92
+ return null;
93
+ }
94
+ }
95
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
96
+ SetExecutable(path) {
97
+ this.executable = path;
98
+ }
99
+ };
100
+ OpenCodeAdapter = __decorate([
101
+ RegisterClass(BaseHarnessAdapter, 'OpenCodeAdapter')
102
+ ], OpenCodeAdapter);
103
+ export { OpenCodeAdapter };
104
+ //# sourceMappingURL=OpenCodeAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenCodeAdapter.js","sourceRoot":"","sources":["../../src/adapters/OpenCodeAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { BaseCliHarnessAdapter, HarnessCliRawEvent } from './BaseCliHarnessAdapter.js';
2
+ import { HarnessCapabilities, HarnessPermissionPolicy, HarnessTurnEvent } from '../types.js';
3
+ /**
4
+ * Drives Pi (`@earendil-works/pi-coding-agent`).
5
+ *
6
+ * ## Verified against a real install, not inferred
7
+ *
8
+ * An earlier version of this adapter subclassed the generic stdio-JSON escape hatch, because the
9
+ * obvious npm names for Pi are placeholder reservations and there was no published contract to code
10
+ * against. With Pi actually installed (0.83.0), its CLI turns out to be well specified, so this is
11
+ * now a first-class adapter:
12
+ *
13
+ * · `-p` / `--print` non-interactive: process the prompt and exit
14
+ * · `--mode json` newline-delimited JSON events
15
+ * · `--session-id <id>` exact session, created if missing — so turns resume rather than replay
16
+ * · `--provider <name>` default `google`
17
+ * · `--model <pattern>` model pattern or `provider/id`
18
+ *
19
+ * The session-id form is what earns `SessionResume: true`: MJ supplies the id up front rather than
20
+ * discovering it, so continuity does not depend on parsing it back out before turn two.
21
+ *
22
+ * ## Authentication
23
+ *
24
+ * Pi resolves credentials from environment variables (or its own `/login`). It therefore works with
25
+ * the standard credential path — grant a credential whose `EnvVariableName` matches what the chosen
26
+ * provider expects — and equally with the "true local" mode, where a developer who has already run
27
+ * `pi /login` needs no credential row at all, because the local executor passes `HOME` through.
28
+ */
29
+ export declare class PiAdapter extends BaseCliHarnessAdapter {
30
+ private executable;
31
+ private provider;
32
+ private permissionArgs;
33
+ protected get ExecutablePath(): string;
34
+ /** @inheritdoc */
35
+ get Capabilities(): HarnessCapabilities;
36
+ /**
37
+ * Maps MJ's posture onto Pi's `--tools` / `--exclude-tools`.
38
+ *
39
+ * Pi gates at the TOOL level, and unlike Claude Code's prefix-matched Bash patterns these are
40
+ * exact tool-name matches — so what this configures is what is enforced, with no way for a
41
+ * cleverly-flagged command to slip past. `strict` is therefore genuinely enforceable here,
42
+ * whereas on Claude Code it degrades to "prompts that have nowhere to go".
43
+ *
44
+ * ## Command-scoped patterns cannot be expressed, and are NOT quietly widened
45
+ *
46
+ * A policy authored for Claude Code may contain `Bash(git:*)`. Pi has no sub-command vocabulary,
47
+ * so the only faithful translations are "all of `bash`" or "none of it" — and those are not
48
+ * equivalent to what was written. The rule is fail-closed in both directions:
49
+ *
50
+ * - a command-scoped **allow** is DROPPED — granting the whole tool would hand over strictly more
51
+ * authority than the policy asked for;
52
+ * - a command-scoped **deny** is WIDENED to the whole tool — denying more than asked is the safe
53
+ * direction, and a policy that bothered to deny `git push` should not get all of `bash`.
54
+ *
55
+ * Silently widening an allow is the failure this whole capability exists to prevent.
56
+ */
57
+ ApplyPermissionPolicy(policy: HarnessPermissionPolicy): void;
58
+ /**
59
+ * Built-in tools each posture grants when no explicit allowlist is given.
60
+ *
61
+ * `dangerous` returns undefined — no `--tools` flag at all, leaving Pi's own defaults in place.
62
+ */
63
+ private defaultToolsForPosture;
64
+ /** Applies {@link PI_TOOL_ALIASES} and the command-scoped-pattern rules described above. */
65
+ private translateTools;
66
+ protected BuildTurnArgs(input: string, _isFirstTurn: boolean): string[];
67
+ protected MapEvent(raw: HarnessCliRawEvent): HarnessTurnEvent | null;
68
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
69
+ SetExecutable(path: string): void;
70
+ /** Selects Pi's provider (default `google`), typically from the harness row's configuration. */
71
+ SetProvider(provider: string): void;
72
+ }
73
+ //# sourceMappingURL=PiAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PiAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/PiAdapter.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;AAuB7F;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBACa,SAAU,SAAQ,qBAAqB;IAChD,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,cAAc,CAAgB;IAEtC,SAAS,KAAK,cAAc,IAAI,MAAM,CAErC;IAED,kBAAkB;IAClB,IAAW,YAAY,IAAI,mBAAmB,CAkB7C;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACa,qBAAqB,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI;IAoB5E;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAc9B,4FAA4F;IAC5F,OAAO,CAAC,cAAc;IAqBtB,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,MAAM,EAAE;IAsBvE,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,IAAI;IA8CpE,qFAAqF;IAC9E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxC,gGAAgG;IACzF,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAG7C"}
@@ -0,0 +1,237 @@
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
+ * Pi's built-in tools, from `pi --help` on a real install (0.83.0).
12
+ *
13
+ * `--tools` / `--exclude-tools` take Pi's own tool names, which are lowercase and differ from
14
+ * Claude Code's (`bash` not `Bash`, `find` not `Glob`). MJ's policy is written once in agent
15
+ * metadata, so the adapter — not the operator — is responsible for speaking each harness's
16
+ * vocabulary. Names not in this map pass through unchanged, so extension and custom tools still
17
+ * work; only the built-ins need translating.
18
+ */
19
+ const PI_TOOL_ALIASES = {
20
+ Bash: 'bash',
21
+ Read: 'read',
22
+ Edit: 'edit',
23
+ Write: 'write',
24
+ Grep: 'grep',
25
+ Glob: 'find',
26
+ };
27
+ /** Mutating built-ins — what `strict` must leave out when no explicit allowlist is supplied. */
28
+ const PI_READ_ONLY_TOOLS = ['read', 'grep', 'find'];
29
+ /**
30
+ * Drives Pi (`@earendil-works/pi-coding-agent`).
31
+ *
32
+ * ## Verified against a real install, not inferred
33
+ *
34
+ * An earlier version of this adapter subclassed the generic stdio-JSON escape hatch, because the
35
+ * obvious npm names for Pi are placeholder reservations and there was no published contract to code
36
+ * against. With Pi actually installed (0.83.0), its CLI turns out to be well specified, so this is
37
+ * now a first-class adapter:
38
+ *
39
+ * · `-p` / `--print` non-interactive: process the prompt and exit
40
+ * · `--mode json` newline-delimited JSON events
41
+ * · `--session-id <id>` exact session, created if missing — so turns resume rather than replay
42
+ * · `--provider <name>` default `google`
43
+ * · `--model <pattern>` model pattern or `provider/id`
44
+ *
45
+ * The session-id form is what earns `SessionResume: true`: MJ supplies the id up front rather than
46
+ * discovering it, so continuity does not depend on parsing it back out before turn two.
47
+ *
48
+ * ## Authentication
49
+ *
50
+ * Pi resolves credentials from environment variables (or its own `/login`). It therefore works with
51
+ * the standard credential path — grant a credential whose `EnvVariableName` matches what the chosen
52
+ * provider expects — and equally with the "true local" mode, where a developer who has already run
53
+ * `pi /login` needs no credential row at all, because the local executor passes `HOME` through.
54
+ */
55
+ let PiAdapter = class PiAdapter extends BaseCliHarnessAdapter {
56
+ constructor() {
57
+ super(...arguments);
58
+ this.executable = 'pi';
59
+ this.permissionArgs = [];
60
+ }
61
+ get ExecutablePath() {
62
+ return this.executable;
63
+ }
64
+ /** @inheritdoc */
65
+ get Capabilities() {
66
+ return {
67
+ // MJ supplies --session-id, so continuity does not depend on parsing an id back out.
68
+ SessionResume: true,
69
+ MidTurnCancellation: true,
70
+ // --mode json structures the TRANSPORT, not the model's content; the turn-end envelope
71
+ // is still coaxed by prompt and recovered by BaseAgent's malformed-response retry.
72
+ StructuredOutput: false,
73
+ UsageReporting: true,
74
+ // ApplyPermissionPolicy translates posture + allow/deny into --tools/--exclude-tools.
75
+ PermissionPolicy: true,
76
+ // Pi can gate tools at LAUNCH but exposes no mid-turn interception MJ can pause on, so
77
+ // there is still nowhere to route an approval request. Static policy, no HITL.
78
+ PermissionHooks: false,
79
+ McpClient: false,
80
+ WorkspaceScoping: true,
81
+ ModelSelection: true,
82
+ };
83
+ }
84
+ /**
85
+ * Maps MJ's posture onto Pi's `--tools` / `--exclude-tools`.
86
+ *
87
+ * Pi gates at the TOOL level, and unlike Claude Code's prefix-matched Bash patterns these are
88
+ * exact tool-name matches — so what this configures is what is enforced, with no way for a
89
+ * cleverly-flagged command to slip past. `strict` is therefore genuinely enforceable here,
90
+ * whereas on Claude Code it degrades to "prompts that have nowhere to go".
91
+ *
92
+ * ## Command-scoped patterns cannot be expressed, and are NOT quietly widened
93
+ *
94
+ * A policy authored for Claude Code may contain `Bash(git:*)`. Pi has no sub-command vocabulary,
95
+ * so the only faithful translations are "all of `bash`" or "none of it" — and those are not
96
+ * equivalent to what was written. The rule is fail-closed in both directions:
97
+ *
98
+ * - a command-scoped **allow** is DROPPED — granting the whole tool would hand over strictly more
99
+ * authority than the policy asked for;
100
+ * - a command-scoped **deny** is WIDENED to the whole tool — denying more than asked is the safe
101
+ * direction, and a policy that bothered to deny `git push` should not get all of `bash`.
102
+ *
103
+ * Silently widening an allow is the failure this whole capability exists to prevent.
104
+ */
105
+ ApplyPermissionPolicy(policy) {
106
+ const args = [];
107
+ const allowed = this.translateTools(policy.AllowedTools, 'allow');
108
+ const denied = this.translateTools(policy.DisallowedTools, 'deny');
109
+ // An explicit allowlist always wins over the posture default: the operator said exactly what
110
+ // they wanted. Without one, the posture picks a sensible built-in set.
111
+ const allowlist = allowed.length > 0 ? allowed : this.defaultToolsForPosture(policy.Posture);
112
+ if (allowlist) {
113
+ args.push('--tools', allowlist.join(','));
114
+ }
115
+ // Applied last and independently of --tools so deny wins on any overlap.
116
+ if (denied.length > 0) {
117
+ args.push('--exclude-tools', denied.join(','));
118
+ }
119
+ this.permissionArgs = args;
120
+ }
121
+ /**
122
+ * Built-in tools each posture grants when no explicit allowlist is given.
123
+ *
124
+ * `dangerous` returns undefined — no `--tools` flag at all, leaving Pi's own defaults in place.
125
+ */
126
+ defaultToolsForPosture(posture) {
127
+ switch (posture) {
128
+ case 'dangerous':
129
+ return undefined;
130
+ case 'auto':
131
+ // File mutation proceeds; shell does not. The analogue of Claude Code's acceptEdits,
132
+ // which likewise accepts edits while still gating command execution.
133
+ return [...PI_READ_ONLY_TOOLS, 'edit', 'write'];
134
+ case 'strict':
135
+ default:
136
+ return [...PI_READ_ONLY_TOOLS];
137
+ }
138
+ }
139
+ /** Applies {@link PI_TOOL_ALIASES} and the command-scoped-pattern rules described above. */
140
+ translateTools(tools, direction) {
141
+ if (!tools?.length) {
142
+ return [];
143
+ }
144
+ const out = [];
145
+ for (const tool of tools) {
146
+ const parenIndex = tool.indexOf('(');
147
+ if (parenIndex === -1) {
148
+ out.push(PI_TOOL_ALIASES[tool] ?? tool);
149
+ continue;
150
+ }
151
+ if (direction === 'deny') {
152
+ // Widen to the whole tool — the safe direction.
153
+ const base = tool.slice(0, parenIndex);
154
+ out.push(PI_TOOL_ALIASES[base] ?? base);
155
+ }
156
+ // direction === 'allow': dropped deliberately. See the method doc.
157
+ }
158
+ return [...new Set(out)];
159
+ }
160
+ BuildTurnArgs(input, _isFirstTurn) {
161
+ // The session id is generated once per session and passed on EVERY turn: --session-id
162
+ // creates the session if missing, so the first turn establishes it and later turns attach
163
+ // to it. No branch on first-vs-subsequent is needed, which removes a state bug by design.
164
+ if (!this.sessionId) {
165
+ this.sessionId = `mj-${Date.now().toString(36)}-${Math.floor(Math.random() * 1e6).toString(36)}`;
166
+ }
167
+ const args = ['-p', '--mode', 'json', '--session-id', this.sessionId];
168
+ if (this.provider) {
169
+ args.push('--provider', this.provider);
170
+ }
171
+ if (this.config?.Model) {
172
+ args.push('--model', this.config.Model);
173
+ }
174
+ // Per-invocation, like every other flag here: Pi's process dies at turn end, so a policy
175
+ // applied only at session start would silently lapse from turn two onward.
176
+ args.push(...this.permissionArgs);
177
+ args.push(input);
178
+ return args;
179
+ }
180
+ MapEvent(raw) {
181
+ const type = this.readString(raw, 'type');
182
+ switch (type) {
183
+ case 'session': {
184
+ // Pi announces its session up front; prefer its id over the one MJ proposed so
185
+ // AIAgentRun.ExternalSessionID correlates with Pi's own session files.
186
+ const id = this.readString(raw, 'id');
187
+ if (id) {
188
+ this.sessionId = id;
189
+ }
190
+ return null;
191
+ }
192
+ case 'assistant':
193
+ case 'text':
194
+ case 'message': {
195
+ const text = this.readString(raw, 'text') ?? this.readString(raw, 'content');
196
+ return text ? { Type: 'assistant-text', Text: text } : null;
197
+ }
198
+ case 'tool':
199
+ case 'tool_use': {
200
+ return { Type: 'sandbox-activity', Description: this.readString(raw, 'name') ?? 'tool call' };
201
+ }
202
+ case 'usage': {
203
+ const usage = this.readObject(raw, 'usage') ?? raw;
204
+ return {
205
+ Type: 'usage',
206
+ InputTokens: this.readNumber(usage, 'input_tokens') ?? this.readNumber(usage, 'input') ?? 0,
207
+ OutputTokens: this.readNumber(usage, 'output_tokens') ?? this.readNumber(usage, 'output') ?? 0,
208
+ CostUsd: this.readNumber(usage, 'cost_usd') ?? this.readNumber(raw, 'cost'),
209
+ };
210
+ }
211
+ case 'result':
212
+ case 'done':
213
+ case 'complete': {
214
+ const text = this.readString(raw, 'result') ?? this.readString(raw, 'text') ?? '';
215
+ return { Type: 'turn-complete', RawText: text };
216
+ }
217
+ case 'error': {
218
+ return { Type: 'session-error', Error: this.readString(raw, 'message') ?? 'Pi reported an error' };
219
+ }
220
+ default:
221
+ return null;
222
+ }
223
+ }
224
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
225
+ SetExecutable(path) {
226
+ this.executable = path;
227
+ }
228
+ /** Selects Pi's provider (default `google`), typically from the harness row's configuration. */
229
+ SetProvider(provider) {
230
+ this.provider = provider;
231
+ }
232
+ };
233
+ PiAdapter = __decorate([
234
+ RegisterClass(BaseHarnessAdapter, 'PiAdapter')
235
+ ], PiAdapter);
236
+ export { PiAdapter };
237
+ //# sourceMappingURL=PiAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PiAdapter.js","sourceRoot":"","sources":["../../src/adapters/PiAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { BaseCliHarnessAdapter, HarnessCliRawEvent } from './BaseCliHarnessAdapter.js';
2
+ import { HarnessCapabilities, HarnessTurnEvent } from '../types.js';
3
+ /**
4
+ * Drives ANY command that speaks a documented newline-delimited JSON event contract.
5
+ *
6
+ * This is the escape hatch that keeps "adding a harness must not require core changes" true in the
7
+ * strong sense: a harness MJ has never heard of works with zero MJ code, provided its CLI emits
8
+ * lines matching the vocabulary below.
9
+ *
10
+ * ## The contract
11
+ *
12
+ * Each stdout line is a JSON object with a `type` field:
13
+ *
14
+ * | `type` | Other fields | Meaning |
15
+ * |--------------|---------------------------------------|------------------------------------------|
16
+ * | `text` | `text` | Narration; streamed, never persisted |
17
+ * | `activity` | `description` | In-sandbox activity, for live view only |
18
+ * | `permission` | `id`, `description`, `command?` | Requests approval; becomes a HITL row |
19
+ * | `usage` | `input_tokens`, `output_tokens`, `cost_usd?` | Turn usage; drives cost guardrails |
20
+ * | `complete` | `text` | Turn ended; `text` carries the envelope |
21
+ * | `error` | `message` | Turn failed |
22
+ *
23
+ * Unrecognised lines are ignored, so a harness may interleave its own diagnostics freely.
24
+ *
25
+ * Capabilities default to the conservative end — an unknown harness is assumed NOT to resume
26
+ * sessions or honour permission hooks, so the runtime emulates continuity rather than silently
27
+ * losing context. Override via `AIAgentHarness.CapabilitySettings` when the harness does better.
28
+ */
29
+ export declare class StdioJsonAdapter extends BaseCliHarnessAdapter {
30
+ protected executable: string;
31
+ protected extraArgs: string[];
32
+ protected declaredCapabilities: HarnessCapabilities | null;
33
+ protected get ExecutablePath(): string;
34
+ /** @inheritdoc */
35
+ get Capabilities(): HarnessCapabilities;
36
+ protected BuildTurnArgs(input: string, _isFirstTurn: boolean): string[];
37
+ protected MapEvent(raw: HarnessCliRawEvent): HarnessTurnEvent | null;
38
+ /** Configures the command, extra argv and declared capabilities from `AIAgentHarness` metadata. */
39
+ Configure(executable: string, extraArgs: string[], capabilities: HarnessCapabilities | null): void;
40
+ /** Points the adapter at a specific binary, from `AIAgentHarness.ExecutablePath`. */
41
+ SetExecutable(path: string): void;
42
+ }
43
+ //# sourceMappingURL=StdioJsonAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StdioJsonAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/StdioJsonAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBACa,gBAAiB,SAAQ,qBAAqB;IACvD,SAAS,CAAC,UAAU,SAAa;IACjC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,CAAM;IACnC,SAAS,CAAC,oBAAoB,EAAE,mBAAmB,GAAG,IAAI,CAAQ;IAElE,SAAS,KAAK,cAAc,IAAI,MAAM,CAErC;IAED,kBAAkB;IAClB,IAAW,YAAY,IAAI,mBAAmB,CAiB7C;IAED,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,MAAM,EAAE;IAIvE,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,IAAI;IA6BpE,mGAAmG;IAC5F,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,mBAAmB,GAAG,IAAI,GAAG,IAAI;IAMzG,qFAAqF;IAC9E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG3C"}