@memberjunction/ai-agent-harness 0.0.0 → 6.1.0-edge.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +192 -27
- package/dist/HarnessAgentBase.d.ts +261 -0
- package/dist/HarnessAgentBase.d.ts.map +1 -0
- package/dist/HarnessAgentBase.js +822 -0
- package/dist/HarnessAgentBase.js.map +1 -0
- package/dist/HarnessAgentType.d.ts +39 -0
- package/dist/HarnessAgentType.d.ts.map +1 -0
- package/dist/HarnessAgentType.js +50 -0
- package/dist/HarnessAgentType.js.map +1 -0
- package/dist/adapters/BaseCliHarnessAdapter.d.ts +93 -0
- package/dist/adapters/BaseCliHarnessAdapter.d.ts.map +1 -0
- package/dist/adapters/BaseCliHarnessAdapter.js +184 -0
- package/dist/adapters/BaseCliHarnessAdapter.js.map +1 -0
- package/dist/adapters/BaseHarnessAdapter.d.ts +114 -0
- package/dist/adapters/BaseHarnessAdapter.d.ts.map +1 -0
- package/dist/adapters/BaseHarnessAdapter.js +86 -0
- package/dist/adapters/BaseHarnessAdapter.js.map +1 -0
- package/dist/adapters/ClaudeCodeCliAdapter.d.ts +104 -0
- package/dist/adapters/ClaudeCodeCliAdapter.d.ts.map +1 -0
- package/dist/adapters/ClaudeCodeCliAdapter.js +268 -0
- package/dist/adapters/ClaudeCodeCliAdapter.js.map +1 -0
- package/dist/adapters/CodexAdapter.d.ts +27 -0
- package/dist/adapters/CodexAdapter.d.ts.map +1 -0
- package/dist/adapters/CodexAdapter.js +117 -0
- package/dist/adapters/CodexAdapter.js.map +1 -0
- package/dist/adapters/GeminiCliAdapter.d.ts +25 -0
- package/dist/adapters/GeminiCliAdapter.d.ts.map +1 -0
- package/dist/adapters/GeminiCliAdapter.js +98 -0
- package/dist/adapters/GeminiCliAdapter.js.map +1 -0
- package/dist/adapters/OpenCodeAdapter.d.ts +23 -0
- package/dist/adapters/OpenCodeAdapter.d.ts.map +1 -0
- package/dist/adapters/OpenCodeAdapter.js +104 -0
- package/dist/adapters/OpenCodeAdapter.js.map +1 -0
- package/dist/adapters/PiAdapter.d.ts +73 -0
- package/dist/adapters/PiAdapter.d.ts.map +1 -0
- package/dist/adapters/PiAdapter.js +237 -0
- package/dist/adapters/PiAdapter.js.map +1 -0
- package/dist/adapters/StdioJsonAdapter.d.ts +43 -0
- package/dist/adapters/StdioJsonAdapter.d.ts.map +1 -0
- package/dist/adapters/StdioJsonAdapter.js +109 -0
- package/dist/adapters/StdioJsonAdapter.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox/ChildProcessExecutor.d.ts +41 -0
- package/dist/sandbox/ChildProcessExecutor.d.ts.map +1 -0
- package/dist/sandbox/ChildProcessExecutor.js +86 -0
- package/dist/sandbox/ChildProcessExecutor.js.map +1 -0
- package/dist/sandbox/DockerSandboxProvider.d.ts +64 -0
- package/dist/sandbox/DockerSandboxProvider.d.ts.map +1 -0
- package/dist/sandbox/DockerSandboxProvider.js +176 -0
- package/dist/sandbox/DockerSandboxProvider.js.map +1 -0
- package/dist/sandbox/ISandboxProvider.d.ts +71 -0
- package/dist/sandbox/ISandboxProvider.d.ts.map +1 -0
- package/dist/sandbox/ISandboxProvider.js +2 -0
- package/dist/sandbox/ISandboxProvider.js.map +1 -0
- package/dist/sandbox/LocalDirectorySandboxProvider.d.ts +37 -0
- package/dist/sandbox/LocalDirectorySandboxProvider.d.ts.map +1 -0
- package/dist/sandbox/LocalDirectorySandboxProvider.js +75 -0
- package/dist/sandbox/LocalDirectorySandboxProvider.js.map +1 -0
- package/dist/sandbox/SandboxExecutor.d.ts +47 -0
- package/dist/sandbox/SandboxExecutor.d.ts.map +1 -0
- package/dist/sandbox/SandboxExecutor.js +2 -0
- package/dist/sandbox/SandboxExecutor.js.map +1 -0
- package/dist/types.d.ts +180 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- 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"}
|