genaicode 2.3.0 → 2.4.0

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 (79) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +59 -11
  3. package/dist/agents/cli-agent.d.ts +28 -0
  4. package/dist/agents/cli-agent.js +57 -0
  5. package/dist/agents/cli-agent.js.map +1 -0
  6. package/dist/agents/discovery.d.ts +10 -0
  7. package/dist/agents/discovery.js +31 -0
  8. package/dist/agents/discovery.js.map +1 -0
  9. package/dist/agents/drivers/claude.d.ts +25 -0
  10. package/dist/agents/drivers/claude.js +184 -0
  11. package/dist/agents/drivers/claude.js.map +1 -0
  12. package/dist/agents/drivers/codex-live.d.ts +17 -0
  13. package/dist/agents/drivers/codex-live.js +182 -0
  14. package/dist/agents/drivers/codex-live.js.map +1 -0
  15. package/dist/agents/drivers/codex.d.ts +27 -0
  16. package/dist/agents/drivers/codex.js +176 -0
  17. package/dist/agents/drivers/codex.js.map +1 -0
  18. package/dist/agents/drivers/copilot.d.ts +27 -0
  19. package/dist/agents/drivers/copilot.js +199 -0
  20. package/dist/agents/drivers/copilot.js.map +1 -0
  21. package/dist/agents/drivers/cursor.d.ts +23 -0
  22. package/dist/agents/drivers/cursor.js +174 -0
  23. package/dist/agents/drivers/cursor.js.map +1 -0
  24. package/dist/agents/drivers/gemini.d.ts +18 -0
  25. package/dist/agents/drivers/gemini.js +118 -0
  26. package/dist/agents/drivers/gemini.js.map +1 -0
  27. package/dist/agents/drivers/json.d.ts +6 -0
  28. package/dist/agents/drivers/json.js +20 -0
  29. package/dist/agents/drivers/json.js.map +1 -0
  30. package/dist/agents/drivers/muse-live.d.ts +17 -0
  31. package/dist/agents/drivers/muse-live.js +112 -0
  32. package/dist/agents/drivers/muse-live.js.map +1 -0
  33. package/dist/agents/drivers/muse.d.ts +12 -0
  34. package/dist/agents/drivers/muse.js +87 -0
  35. package/dist/agents/drivers/muse.js.map +1 -0
  36. package/dist/agents/drivers/opencode.d.ts +17 -0
  37. package/dist/agents/drivers/opencode.js +103 -0
  38. package/dist/agents/drivers/opencode.js.map +1 -0
  39. package/dist/agents/env.d.ts +16 -0
  40. package/dist/agents/env.js +46 -0
  41. package/dist/agents/env.js.map +1 -0
  42. package/dist/agents/event-queue.d.ts +44 -0
  43. package/dist/agents/event-queue.js +123 -0
  44. package/dist/agents/event-queue.js.map +1 -0
  45. package/dist/agents/hosted.d.ts +33 -0
  46. package/dist/agents/hosted.js +129 -0
  47. package/dist/agents/hosted.js.map +1 -0
  48. package/dist/agents/live-agent.d.ts +37 -0
  49. package/dist/agents/live-agent.js +142 -0
  50. package/dist/agents/live-agent.js.map +1 -0
  51. package/dist/agents/prepare.d.ts +33 -0
  52. package/dist/agents/prepare.js +52 -0
  53. package/dist/agents/prepare.js.map +1 -0
  54. package/dist/agents/process.d.ts +39 -0
  55. package/dist/agents/process.js +140 -0
  56. package/dist/agents/process.js.map +1 -0
  57. package/dist/agents/rpc.d.ts +29 -0
  58. package/dist/agents/rpc.js +101 -0
  59. package/dist/agents/rpc.js.map +1 -0
  60. package/dist/agents/runtime.d.ts +26 -0
  61. package/dist/agents/runtime.js +97 -0
  62. package/dist/agents/runtime.js.map +1 -0
  63. package/dist/agents/types.d.ts +158 -0
  64. package/dist/agents/types.js +2 -0
  65. package/dist/agents/types.js.map +1 -0
  66. package/dist/agents/verify.d.ts +36 -0
  67. package/dist/agents/verify.js +43 -0
  68. package/dist/agents/verify.js.map +1 -0
  69. package/dist/agents.d.ts +36 -0
  70. package/dist/agents.js +19 -0
  71. package/dist/agents.js.map +1 -0
  72. package/dist/providers/google-converter.js +30 -14
  73. package/dist/providers/google-converter.js.map +1 -1
  74. package/dist/providers/google.d.ts +8 -0
  75. package/dist/providers/google.js.map +1 -1
  76. package/docs/agents.md +269 -0
  77. package/docs/pivot.md +4 -0
  78. package/docs/semver.md +5 -0
  79. package/package.json +5 -1
@@ -0,0 +1,87 @@
1
+ import { cliAgent } from '../cli-agent.js';
2
+ import { isObject, stringField } from './json.js';
3
+ /** Muse in exec mode (`muse exec --json`). */
4
+ export function muse(options = {}) {
5
+ return cliAgent({
6
+ name: 'muse',
7
+ command: options.command ?? 'muse',
8
+ capabilities: { effort: ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'], maxTurns: true },
9
+ args: (task) => museArgs(task, options),
10
+ createParser: createMuseParser,
11
+ });
12
+ }
13
+ export function museArgs(task, options = {}) {
14
+ const args = ['exec', '--json'];
15
+ if (options.trustWorkspace ?? true)
16
+ args.push('--trust-workspace');
17
+ if (task.model)
18
+ args.push('--model', task.model);
19
+ if (task.effort)
20
+ args.push('--reasoning-effort', task.effort);
21
+ if (task.maxTurns !== undefined)
22
+ args.push('--max-model-steps', String(task.maxTurns));
23
+ if (task.extraArgs)
24
+ args.push(...task.extraArgs);
25
+ return [...args, task.prompt];
26
+ }
27
+ const TERMINAL = 'run.terminal.';
28
+ export function createMuseParser() {
29
+ let outcome;
30
+ let sessionSent = false;
31
+ let streamed = '';
32
+ return {
33
+ outcome: () => outcome,
34
+ event(value) {
35
+ if (!isObject(value))
36
+ return [];
37
+ const events = [];
38
+ const stream = isObject(value.stream) ? value.stream : undefined;
39
+ const sessionId = stringField(stream, 'id');
40
+ if (!sessionSent && stream?.kind === 'session' && sessionId) {
41
+ sessionSent = true;
42
+ events.push({ type: 'session', sessionId });
43
+ }
44
+ const type = stringField(value, 'payload_type');
45
+ const payload = isObject(value.payload) ? value.payload : undefined;
46
+ const text = stringField(payload, 'text');
47
+ if (!type)
48
+ return events;
49
+ if (type === 'run.output.delta' && text) {
50
+ streamed += text;
51
+ events.push({ type: 'text-delta', text });
52
+ }
53
+ else if (type === 'task.lifecycle.side_effect_intent') {
54
+ const operation = stringField(payload?.event, 'operation');
55
+ if (operation && !operation.startsWith('model.'))
56
+ events.push({ type: 'tool-start', name: operation });
57
+ }
58
+ else if (type === 'approval_wait.effect.started' ||
59
+ (type === 'runtime.session' &&
60
+ payload?.kind === 'approval' &&
61
+ stringField(payload.event, 'kind') === 'requested')) {
62
+ // Headless exec cannot answer; museLive() can.
63
+ events.push({ type: 'approval-request', request: { id: approvalId(payload), kind: 'other', detail: payload } });
64
+ }
65
+ else if (type.startsWith(TERMINAL)) {
66
+ const verdict = type.slice(TERMINAL.length);
67
+ if (verdict === 'completed') {
68
+ outcome = { ok: true };
69
+ const final = (text ?? streamed).trim();
70
+ if (final)
71
+ events.push({ type: 'message', text: final });
72
+ }
73
+ else {
74
+ const reason = stringField(payload, 'reason') ?? text;
75
+ const message = `Muse run ${verdict}${reason ? `: ${reason}` : ''}`;
76
+ outcome = { ok: false, error: message };
77
+ events.push({ type: 'error', message });
78
+ }
79
+ }
80
+ return events;
81
+ },
82
+ };
83
+ }
84
+ function approvalId(payload) {
85
+ return stringField(payload, 'id') ?? stringField(payload, 'approvalId') ?? 'approval';
86
+ }
87
+ //# sourceMappingURL=muse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muse.js","sourceRoot":"","sources":["../../../src/agents/drivers/muse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type AgentOutputParser } from '../cli-agent.js';
2
+ import type { AgentTask, CodingAgent } from '../types.js';
3
+ export interface OpencodeAgentOptions {
4
+ /** Executable name or path. Default `opencode`. */
5
+ command?: string;
6
+ /** opencode agent to use (`--agent`). */
7
+ agent?: string;
8
+ /** Pass `--auto`: approve every permission that is not explicitly denied. Default false. */
9
+ autoApprove?: boolean;
10
+ }
11
+ /**
12
+ * opencode in run mode (`opencode run --format json`). `task.model` is `provider/model`;
13
+ * `task.effort` maps to `--variant`.
14
+ */
15
+ export declare function opencode(options?: OpencodeAgentOptions): CodingAgent;
16
+ export declare function opencodeArgs(task: AgentTask, options?: OpencodeAgentOptions): string[];
17
+ export declare function createOpencodeParser(): AgentOutputParser;
@@ -0,0 +1,103 @@
1
+ import { cliAgent } from '../cli-agent.js';
2
+ import { isObject, numberField, stringField } from './json.js';
3
+ const EDIT_TOOLS = new Set(['edit', 'write', 'patch', 'multiedit']);
4
+ /**
5
+ * opencode in run mode (`opencode run --format json`). `task.model` is `provider/model`;
6
+ * `task.effort` maps to `--variant`.
7
+ */
8
+ export function opencode(options = {}) {
9
+ return cliAgent({
10
+ name: 'opencode',
11
+ command: options.command ?? 'opencode',
12
+ capabilities: { effort: ['minimal', 'low', 'medium', 'high', 'max'], usage: true },
13
+ args: (task) => opencodeArgs(task, options),
14
+ createParser: createOpencodeParser,
15
+ });
16
+ }
17
+ export function opencodeArgs(task, options = {}) {
18
+ const args = ['run', '--format', 'json'];
19
+ if (options.agent)
20
+ args.push('--agent', options.agent);
21
+ if (options.autoApprove)
22
+ args.push('--auto');
23
+ if (task.model)
24
+ args.push('--model', task.model);
25
+ if (task.effort)
26
+ args.push('--variant', task.effort);
27
+ if (task.extraArgs)
28
+ args.push(...task.extraArgs);
29
+ return [...args, '--', task.prompt];
30
+ }
31
+ export function createOpencodeParser() {
32
+ let outcome;
33
+ let sessionSent = false;
34
+ const totals = { inputTokens: 0, outputTokens: 0, cachedInputTokens: 0 };
35
+ let costUsd = 0;
36
+ let steps = 0;
37
+ return {
38
+ outcome: () => outcome ?? (steps > 0 ? { ok: true } : undefined),
39
+ event(value) {
40
+ if (!isObject(value))
41
+ return [];
42
+ const events = [];
43
+ const sessionId = stringField(value, 'sessionID');
44
+ if (sessionId && !sessionSent) {
45
+ sessionSent = true;
46
+ events.push({ type: 'session', sessionId });
47
+ }
48
+ const part = isObject(value.part) ? value.part : undefined;
49
+ switch (value.type) {
50
+ case 'text': {
51
+ const text = stringField(part, 'text')?.trim();
52
+ if (text)
53
+ events.push({ type: 'message', text });
54
+ break;
55
+ }
56
+ case 'tool_use': {
57
+ const name = stringField(part, 'tool') ?? 'tool';
58
+ const id = stringField(part, 'callID') ?? stringField(part, 'id');
59
+ const state = isObject(part?.state) ? part.state : undefined;
60
+ const failed = state?.status === 'error';
61
+ const output = stringField(state, 'output') ?? stringField(state, 'error');
62
+ events.push({
63
+ type: 'tool-end',
64
+ ...(id ? { id } : {}),
65
+ name,
66
+ isError: failed,
67
+ ...(output !== undefined ? { output } : {}),
68
+ });
69
+ const path = stringField(state?.input, 'filePath');
70
+ if (!failed && EDIT_TOOLS.has(name) && path)
71
+ events.push({ type: 'file-change', paths: [path] });
72
+ break;
73
+ }
74
+ case 'step_finish': {
75
+ steps += 1;
76
+ const tokens = isObject(part?.tokens) ? part.tokens : undefined;
77
+ totals.inputTokens += numberField(tokens, 'input') ?? 0;
78
+ totals.outputTokens += numberField(tokens, 'output') ?? 0;
79
+ totals.cachedInputTokens += numberField(tokens?.cache, 'read') ?? 0;
80
+ costUsd += numberField(part, 'cost') ?? 0;
81
+ // Running totals across steps, so the last usage event covers the whole run.
82
+ if (tokens) {
83
+ events.push({
84
+ type: 'usage',
85
+ usage: { ...totals, totalTokens: totals.inputTokens + totals.outputTokens },
86
+ costUsd,
87
+ });
88
+ }
89
+ break;
90
+ }
91
+ case 'error': {
92
+ const error = isObject(value.error) ? value.error : undefined;
93
+ const message = stringField(error?.data, 'message') ?? stringField(error, 'name') ?? 'opencode error';
94
+ outcome = { ok: false, error: message };
95
+ events.push({ type: 'error', message });
96
+ break;
97
+ }
98
+ }
99
+ return events;
100
+ },
101
+ };
102
+ }
103
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/agents/drivers/opencode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Model-provider credentials an agent CLI would otherwise pick up from the parent
3
+ * process. Remove them when the agent should use its own login and billing instead
4
+ * of your application's keys.
5
+ */
6
+ export declare const PROVIDER_CREDENTIAL_VARS: readonly string[];
7
+ export interface ScrubEnvOptions {
8
+ /** Variable names to drop: exact names or patterns. */
9
+ names?: readonly (string | RegExp)[];
10
+ /** Drop any variable whose value matches one of these (a token prefix, for example). */
11
+ values?: readonly RegExp[];
12
+ }
13
+ /** A copy of `env` without the matching variables. `undefined` entries are dropped too. */
14
+ export declare function scrubEnv(env: NodeJS.ProcessEnv, options: ScrubEnvOptions): NodeJS.ProcessEnv;
15
+ /** `env` without `PROVIDER_CREDENTIAL_VARS`: the agent falls back to its own login. */
16
+ export declare function withoutProviderCredentials(env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Model-provider credentials an agent CLI would otherwise pick up from the parent
3
+ * process. Remove them when the agent should use its own login and billing instead
4
+ * of your application's keys.
5
+ */
6
+ export const PROVIDER_CREDENTIAL_VARS = [
7
+ 'ANTHROPIC_API_KEY',
8
+ 'ANTHROPIC_AUTH_TOKEN',
9
+ 'ANTHROPIC_BASE_URL',
10
+ 'CLAUDE_CODE_USE_BEDROCK',
11
+ 'CLAUDE_CODE_USE_VERTEX',
12
+ 'OPENAI_API_KEY',
13
+ 'OPENAI_BASE_URL',
14
+ 'OPENAI_ORG_ID',
15
+ 'CODEX_API_KEY',
16
+ 'GEMINI_API_KEY',
17
+ 'GOOGLE_API_KEY',
18
+ 'GOOGLE_APPLICATION_CREDENTIALS',
19
+ 'GOOGLE_GENAI_USE_VERTEXAI',
20
+ ];
21
+ /** A copy of `env` without the matching variables. `undefined` entries are dropped too. */
22
+ export function scrubEnv(env, options) {
23
+ const names = options.names ?? [];
24
+ const values = options.values ?? [];
25
+ const result = {};
26
+ for (const [name, value] of Object.entries(env)) {
27
+ if (value === undefined)
28
+ continue;
29
+ if (names.some((match) => (typeof match === 'string' ? match === name : matches(match, name))))
30
+ continue;
31
+ if (values.some((match) => matches(match, value)))
32
+ continue;
33
+ result[name] = value;
34
+ }
35
+ return result;
36
+ }
37
+ /** `test()` from the start every time: `/g` and `/y` patterns keep `lastIndex` between calls. */
38
+ function matches(pattern, text) {
39
+ pattern.lastIndex = 0;
40
+ return pattern.test(text);
41
+ }
42
+ /** `env` without `PROVIDER_CREDENTIAL_VARS`: the agent falls back to its own login. */
43
+ export function withoutProviderCredentials(env = process.env) {
44
+ return scrubEnv(env, { names: PROVIDER_CREDENTIAL_VARS });
45
+ }
46
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/agents/env.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsB;IACzD,mBAAmB;IACnB,sBAAsB;IACtB,oBAAoB;IACpB,yBAAyB;IACzB,wBAAwB;IACxB,gBAAgB;IAChB,iBAAiB;IACjB,eAAe;IACf,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,gCAAgC;IAChC,2BAA2B;CAC5B,CAAC;AASF,2FAA2F;AAC3F,MAAM,UAAU,QAAQ,CAAC,GAAsB,EAAE,OAAwB;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;IACpC,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YAAE,SAAS;QACzG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAAE,SAAS;QAC5D,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IACvB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,iGAAiG;AACjG,SAAS,OAAO,CAAC,OAAe,EAAE,IAAY;IAC5C,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;IACtB,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,0BAA0B,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7E,OAAO,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,44 @@
1
+ export interface EventQueueLimits {
2
+ /** Events kept for a run nobody iterates yet. The oldest are dropped past this. */
3
+ unreadItems: number;
4
+ /** Approximate bytes kept for a run nobody iterates yet. The oldest events are dropped past this. */
5
+ unreadBytes: number;
6
+ /** While iterated: above this many buffered bytes, ask the producer to pause. */
7
+ highWaterBytes: number;
8
+ /** While iterated: at or below this many buffered bytes, let a paused producer resume. */
9
+ lowWaterBytes: number;
10
+ }
11
+ /**
12
+ * Single-consumer queue bridging callbacks to `for await`, bounded by approximate size.
13
+ *
14
+ * Before anyone iterates, it keeps only the newest events within `unreadItems` and
15
+ * `unreadBytes`, since a run awaited only through `result` needs none of them. While
16
+ * iterated, it drops nothing: past `highWaterBytes` it calls `onPressure(true)` so the
17
+ * producer stops reading, and `onPressure(false)` once the consumer catches up.
18
+ * A consumer that stops iterating early releases the pressure and the rest is discarded.
19
+ */
20
+ export declare class EventQueue<T> {
21
+ private readonly sizeOf;
22
+ /** Called with true when the producer should pause and false when it may resume. */
23
+ onPressure: ((paused: boolean) => void) | undefined;
24
+ private readonly items;
25
+ private readonly limits;
26
+ private bytes;
27
+ private closed;
28
+ private claimed;
29
+ private abandoned;
30
+ private pressured;
31
+ private wake;
32
+ private roomWaiters;
33
+ constructor(sizeOf?: (item: T) => number, limits?: Partial<EventQueueLimits>);
34
+ /** Approximate bytes currently buffered. */
35
+ get bufferedBytes(): number;
36
+ push(item: T): void;
37
+ close(): void;
38
+ /** Resolve once the producer may go on: the queue is below its high-water mark, or nobody reads it. */
39
+ room(): Promise<void>;
40
+ iterate(): AsyncGenerator<T>;
41
+ private setPressure;
42
+ }
43
+ /** A cheap size estimate for a JSON-like value: string lengths plus a few bytes per other value. */
44
+ export declare function approximateSize(value: unknown, depth?: number): number;
@@ -0,0 +1,123 @@
1
+ const DEFAULT_LIMITS = {
2
+ unreadItems: 1_000,
3
+ unreadBytes: 8 * 1024 * 1024,
4
+ highWaterBytes: 8 * 1024 * 1024,
5
+ lowWaterBytes: 1024 * 1024,
6
+ };
7
+ /**
8
+ * Single-consumer queue bridging callbacks to `for await`, bounded by approximate size.
9
+ *
10
+ * Before anyone iterates, it keeps only the newest events within `unreadItems` and
11
+ * `unreadBytes`, since a run awaited only through `result` needs none of them. While
12
+ * iterated, it drops nothing: past `highWaterBytes` it calls `onPressure(true)` so the
13
+ * producer stops reading, and `onPressure(false)` once the consumer catches up.
14
+ * A consumer that stops iterating early releases the pressure and the rest is discarded.
15
+ */
16
+ export class EventQueue {
17
+ sizeOf;
18
+ /** Called with true when the producer should pause and false when it may resume. */
19
+ onPressure;
20
+ items = [];
21
+ limits;
22
+ bytes = 0;
23
+ closed = false;
24
+ claimed = false;
25
+ abandoned = false;
26
+ pressured = false;
27
+ wake;
28
+ roomWaiters = [];
29
+ constructor(sizeOf = () => 0, limits = {}) {
30
+ this.sizeOf = sizeOf;
31
+ this.limits = { ...DEFAULT_LIMITS, ...limits };
32
+ }
33
+ /** Approximate bytes currently buffered. */
34
+ get bufferedBytes() {
35
+ return this.bytes;
36
+ }
37
+ push(item) {
38
+ if (this.closed || this.abandoned)
39
+ return;
40
+ const size = this.sizeOf(item);
41
+ this.items.push({ item, size });
42
+ this.bytes += size;
43
+ if (!this.claimed) {
44
+ // The newest event always stays, so `done` survives however large the ones before it were.
45
+ while (this.items.length > 1 &&
46
+ (this.items.length > this.limits.unreadItems || this.bytes > this.limits.unreadBytes)) {
47
+ this.bytes -= this.items.shift().size;
48
+ }
49
+ }
50
+ else if (!this.pressured && this.bytes > this.limits.highWaterBytes) {
51
+ this.setPressure(true);
52
+ }
53
+ this.wake?.();
54
+ }
55
+ close() {
56
+ this.closed = true;
57
+ this.wake?.();
58
+ }
59
+ /** Resolve once the producer may go on: the queue is below its high-water mark, or nobody reads it. */
60
+ room() {
61
+ if (!this.pressured)
62
+ return Promise.resolve();
63
+ return new Promise((resolve) => this.roomWaiters.push(resolve));
64
+ }
65
+ async *iterate() {
66
+ if (this.claimed)
67
+ throw new Error('An AgentRun can be iterated only once.');
68
+ this.claimed = true;
69
+ try {
70
+ for (;;) {
71
+ const next = this.items.shift();
72
+ if (next !== undefined) {
73
+ this.bytes -= next.size;
74
+ if (this.pressured && this.bytes <= this.limits.lowWaterBytes)
75
+ this.setPressure(false);
76
+ yield next.item;
77
+ continue;
78
+ }
79
+ if (this.closed)
80
+ return;
81
+ await new Promise((resolve) => {
82
+ this.wake = resolve;
83
+ });
84
+ this.wake = undefined;
85
+ }
86
+ }
87
+ finally {
88
+ // Done, or the consumer broke out early: nothing reads further events, so do not hold the producer.
89
+ this.abandoned = true;
90
+ this.items.length = 0;
91
+ this.bytes = 0;
92
+ if (this.pressured)
93
+ this.setPressure(false);
94
+ }
95
+ }
96
+ setPressure(paused) {
97
+ this.pressured = paused;
98
+ this.onPressure?.(paused);
99
+ if (!paused) {
100
+ const waiters = this.roomWaiters;
101
+ this.roomWaiters = [];
102
+ waiters.forEach((resolve) => resolve());
103
+ }
104
+ }
105
+ }
106
+ /** A cheap size estimate for a JSON-like value: string lengths plus a few bytes per other value. */
107
+ export function approximateSize(value, depth = 0) {
108
+ if (typeof value === 'string')
109
+ return value.length;
110
+ if (value === null || typeof value !== 'object' || depth > 8)
111
+ return 8;
112
+ let size = 8;
113
+ if (Array.isArray(value)) {
114
+ for (const item of value)
115
+ size += approximateSize(item, depth + 1);
116
+ }
117
+ else {
118
+ for (const [key, item] of Object.entries(value))
119
+ size += key.length + approximateSize(item, depth + 1);
120
+ }
121
+ return size;
122
+ }
123
+ //# sourceMappingURL=event-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-queue.js","sourceRoot":"","sources":["../../src/agents/event-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { AgentCapabilities, AgentEvent, AgentTask, CodingAgent } from './types.js';
2
+ export type HostedTaskState = 'queued' | 'running' | 'completed' | 'failed' | 'cancelled';
3
+ /** What a hosted provider receives. `cwd` is the provider's workspace reference (a repo, a branch...). */
4
+ export type HostedTaskRequest = Omit<AgentTask, 'env' | 'signal' | 'onApproval' | 'timeoutMs'>;
5
+ export interface HostedPoll {
6
+ state: HostedTaskState;
7
+ /** Events since the previous poll. */
8
+ events?: AgentEvent[];
9
+ /** Opaque position handed back on the next poll. */
10
+ cursor?: string;
11
+ error?: string;
12
+ }
13
+ /**
14
+ * A remote coding-agent service: tasks run on the vendor's machines and are polled.
15
+ * Implement this for a hosted product and pass it to `hostedAgent()`.
16
+ */
17
+ export interface HostedAgentProvider {
18
+ readonly name: string;
19
+ readonly capabilities?: AgentCapabilities;
20
+ start(task: HostedTaskRequest, signal: AbortSignal): Promise<{
21
+ id: string;
22
+ }>;
23
+ poll(id: string, cursor: string | undefined, signal: AbortSignal): Promise<HostedPoll>;
24
+ /** Add input to a running task (backs `AgentRun.steer`). */
25
+ send?(id: string, text: string): Promise<void>;
26
+ cancel(id: string): Promise<void>;
27
+ }
28
+ export interface HostedAgentOptions {
29
+ /** Delay between polls. Default 5 s. */
30
+ pollIntervalMs?: number;
31
+ }
32
+ /** Adapt a `HostedAgentProvider` to `CodingAgent`, so hosted and local agents share one API. */
33
+ export declare function hostedAgent(provider: HostedAgentProvider, options?: HostedAgentOptions): CodingAgent;
@@ -0,0 +1,129 @@
1
+ import { RunRecorder } from './runtime.js';
2
+ const TERMINAL = new Set(['completed', 'failed', 'cancelled']);
3
+ /** Adapt a `HostedAgentProvider` to `CodingAgent`, so hosted and local agents share one API. */
4
+ export function hostedAgent(provider, options = {}) {
5
+ return {
6
+ name: provider.name,
7
+ command: provider.name,
8
+ capabilities: { ...provider.capabilities, steer: !!provider.send },
9
+ run: (task) => runHosted(provider, task, options.pollIntervalMs ?? 5_000),
10
+ };
11
+ }
12
+ function runHosted(provider, task, pollIntervalMs) {
13
+ const recorder = new RunRecorder(provider.name, provider.name);
14
+ const controller = new AbortController();
15
+ let stopReason;
16
+ let taskId;
17
+ const stop = (reason) => {
18
+ if (stopReason || controller.signal.aborted)
19
+ return;
20
+ stopReason = reason;
21
+ controller.abort();
22
+ };
23
+ const onAbort = () => stop('aborted');
24
+ task.signal?.addEventListener('abort', onAbort, { once: true });
25
+ if (task.signal?.aborted)
26
+ onAbort();
27
+ const timer = task.timeoutMs !== undefined ? setTimeout(() => stop('timeout'), task.timeoutMs) : undefined;
28
+ const exit = (reason, error) => ({
29
+ exitCode: null,
30
+ signal: null,
31
+ reason,
32
+ ...(error ? { error } : {}),
33
+ });
34
+ const work = async () => {
35
+ // Local-only fields (process env, callbacks, timers) never reach the provider.
36
+ const request = { ...task };
37
+ delete request.env;
38
+ delete request.signal;
39
+ delete request.onApproval;
40
+ delete request.timeoutMs;
41
+ try {
42
+ taskId = (await provider.start(request, controller.signal)).id;
43
+ }
44
+ catch (error) {
45
+ if (stopReason)
46
+ return { exit: exit(stopReason) };
47
+ return { exit: exit('spawn-error', error instanceof Error ? error : new Error(String(error))) };
48
+ }
49
+ recorder.emit({ type: 'session', sessionId: taskId });
50
+ let cursor;
51
+ while (!stopReason) {
52
+ let poll;
53
+ try {
54
+ poll = await provider.poll(taskId, cursor, controller.signal);
55
+ }
56
+ catch (error) {
57
+ if (stopReason)
58
+ break;
59
+ // Do not leave a task running (and billing) that nobody watches any more.
60
+ await provider.cancel(taskId).catch(() => undefined);
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ return { exit: exit('closed'), outcome: { ok: false, error: `Polling ${provider.name} failed: ${message}` } };
63
+ }
64
+ // Aborted while the poll was in flight: cancel, whatever state it reported.
65
+ if (stopReason)
66
+ break;
67
+ for (const event of poll.events ?? [])
68
+ recorder.emit(event);
69
+ cursor = poll.cursor ?? cursor;
70
+ if (TERMINAL.has(poll.state)) {
71
+ if (poll.state === 'cancelled')
72
+ return { exit: exit('aborted') };
73
+ return {
74
+ exit: exit('closed'),
75
+ outcome: poll.state === 'completed'
76
+ ? { ok: true }
77
+ : { ok: false, error: poll.error ?? `${provider.name} task failed.` },
78
+ };
79
+ }
80
+ // A consumer that falls behind holds the next poll instead of buffering without bound.
81
+ await untilAborted(recorder.events.room(), controller.signal);
82
+ await delay(pollIntervalMs, controller.signal);
83
+ }
84
+ await provider.cancel(taskId).catch(() => undefined);
85
+ return { exit: exit(stopReason ?? 'aborted') };
86
+ };
87
+ const result = work().then(({ exit: ended, outcome }) => {
88
+ clearTimeout(timer);
89
+ task.signal?.removeEventListener('abort', onAbort);
90
+ return recorder.finish(ended, outcome);
91
+ });
92
+ return {
93
+ result,
94
+ abort: () => stop('aborted'),
95
+ ...(provider.send
96
+ ? {
97
+ steer: (text) => taskId && !stopReason
98
+ ? provider.send(taskId, text)
99
+ : Promise.reject(new Error(`${provider.name} is not accepting input.`)),
100
+ }
101
+ : {}),
102
+ [Symbol.asyncIterator]: () => recorder.events.iterate(),
103
+ };
104
+ }
105
+ function delay(ms, signal) {
106
+ return new Promise((resolve) => {
107
+ const timer = setTimeout(done, ms);
108
+ signal.addEventListener('abort', done, { once: true });
109
+ function done() {
110
+ clearTimeout(timer);
111
+ signal.removeEventListener('abort', done);
112
+ resolve();
113
+ }
114
+ });
115
+ }
116
+ /** Resolve when `wait` does or `signal` aborts, whichever comes first. */
117
+ function untilAborted(wait, signal) {
118
+ if (signal.aborted)
119
+ return Promise.resolve();
120
+ return new Promise((resolve) => {
121
+ const done = () => {
122
+ signal.removeEventListener('abort', done);
123
+ resolve();
124
+ };
125
+ signal.addEventListener('abort', done, { once: true });
126
+ void wait.then(done);
127
+ });
128
+ }
129
+ //# sourceMappingURL=hosted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosted.js","sourceRoot":"","sources":["../../src/agents/hosted.ts"],"names":[],"mappings":"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"}