@adecore/agents 0.23.1 → 0.24.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 (153) hide show
  1. package/README.md +3 -3
  2. package/dist/chat/attachment-store.js +4 -5
  3. package/dist/chat/backend.d.ts +6 -1
  4. package/dist/chat/background-work.d.ts +1 -1
  5. package/dist/chat/background-work.js +2 -1
  6. package/dist/chat/chat-core.d.ts +53 -161
  7. package/dist/chat/chat-core.js +146 -112
  8. package/dist/chat/chat-log.js +3 -3
  9. package/dist/chat/chat-process.d.ts +21 -0
  10. package/dist/chat/chat-process.js +109 -9
  11. package/dist/chat/chat-session.d.ts +10 -17
  12. package/dist/chat/chat-session.js +141 -182
  13. package/dist/chat/chat-store.d.ts +1 -0
  14. package/dist/chat/chat-store.js +105 -1
  15. package/dist/chat/claude-backend.d.ts +4 -0
  16. package/dist/chat/claude-backend.js +51 -27
  17. package/dist/chat/claude-protocol.d.ts +12 -0
  18. package/dist/chat/claude-protocol.js +137 -7
  19. package/dist/chat/claude-title.d.ts +1 -3
  20. package/dist/chat/claude-title.js +11 -39
  21. package/dist/chat/claude-transcript.d.ts +1 -0
  22. package/dist/chat/claude-transcript.js +36 -17
  23. package/dist/chat/codex-backend.d.ts +21 -1
  24. package/dist/chat/codex-backend.js +168 -10
  25. package/dist/chat/codex-protocol.d.ts +2 -0
  26. package/dist/chat/codex-protocol.js +37 -3
  27. package/dist/chat/codex-thread.js +1 -3
  28. package/dist/chat/codex-transport.d.ts +3 -0
  29. package/dist/chat/codex-transport.js +38 -35
  30. package/dist/chat/context-breakdown.js +2 -2
  31. package/dist/chat/errors.d.ts +1 -1
  32. package/dist/chat/external-sessions.js +2 -2
  33. package/dist/chat/fixtures/claude-2.1.296-goal.json +136 -0
  34. package/dist/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10.jsonl +2 -0
  35. package/dist/chat/index.d.ts +29 -0
  36. package/dist/chat/index.js +23 -0
  37. package/dist/chat/projector.d.ts +2 -1
  38. package/dist/chat/projector.js +12 -3
  39. package/dist/chat/request-summary.js +1 -4
  40. package/dist/chat/subagent-settlement.js +1 -3
  41. package/dist/chat/thread.d.ts +3 -0
  42. package/dist/chat/thread.js +20 -3
  43. package/dist/chat/ui-queries.d.ts +2 -0
  44. package/dist/chat/ui-queries.js +40 -5
  45. package/dist/chat/ui-replies.d.ts +33 -0
  46. package/dist/chat/ui-replies.js +152 -0
  47. package/dist/context/index.d.ts +2 -0
  48. package/dist/context/index.js +3 -0
  49. package/dist/coordination/index.d.ts +15 -0
  50. package/dist/coordination/index.js +16 -0
  51. package/dist/host/handlers.js +8 -0
  52. package/dist/host/index.d.ts +7 -0
  53. package/dist/host/index.js +7 -0
  54. package/dist/index.d.ts +9 -0
  55. package/dist/index.js +10 -0
  56. package/dist/providers/accounts/status.js +1 -3
  57. package/dist/providers/claude.js +3 -1
  58. package/dist/providers/codex.js +3 -1
  59. package/dist/providers/index.d.ts +14 -0
  60. package/dist/providers/index.js +12 -0
  61. package/dist/run-process.js +54 -14
  62. package/dist/skills.d.ts +1 -0
  63. package/dist/skills.js +4 -0
  64. package/dist/tasks/task-coordinator.d.ts +4 -0
  65. package/dist/tasks/task-coordinator.js +16 -2
  66. package/dist/tasks/wiring.js +7 -1
  67. package/dist/{providers/accounts/test-accounts.d.ts → testing/accounts.d.ts} +2 -2
  68. package/dist/{providers/accounts/test-accounts.js → testing/accounts.js} +3 -3
  69. package/dist/testing/bin/fake-claude.d.ts +1 -0
  70. package/dist/testing/bin/fake-claude.js +6 -0
  71. package/dist/testing/bin/fake-codex.d.ts +1 -0
  72. package/dist/testing/bin/fake-codex.js +6 -0
  73. package/dist/{chat → testing}/fake-claude.d.ts +1 -1
  74. package/dist/{chat → testing}/fake-claude.js +0 -4
  75. package/dist/{chat → testing}/fake-cli.d.ts +1 -1
  76. package/dist/{chat → testing}/fake-codex.d.ts +1 -1
  77. package/dist/{chat → testing}/fake-codex.js +70 -8
  78. package/dist/testing/index.d.ts +6 -0
  79. package/dist/testing/index.js +7 -0
  80. package/dist/{outbox → testing}/manual-clock.d.ts +1 -1
  81. package/dist/{watch-test-helpers.d.ts → testing/watch.d.ts} +1 -1
  82. package/dist/usage/exchange.d.ts +5 -3
  83. package/dist/usage/exchange.js +25 -16
  84. package/dist/usage/index-file.d.ts +1 -0
  85. package/dist/usage/index-file.js +20 -2
  86. package/dist/usage/index.d.ts +9 -0
  87. package/dist/usage/index.js +6 -0
  88. package/dist/usage/limits/normalize.js +1 -3
  89. package/dist/usage/pricing.d.ts +5 -3
  90. package/dist/usage/pricing.js +28 -19
  91. package/dist/usage/scanner.js +39 -11
  92. package/dist/usage/usage-service.js +8 -3
  93. package/package.json +72 -11
  94. package/src/chat/attachment-store.ts +4 -6
  95. package/src/chat/backend.ts +8 -0
  96. package/src/chat/background-work.ts +2 -2
  97. package/src/chat/chat-core.ts +221 -143
  98. package/src/chat/chat-log.ts +3 -3
  99. package/src/chat/chat-process.ts +128 -8
  100. package/src/chat/chat-session.ts +153 -204
  101. package/src/chat/chat-store.ts +104 -1
  102. package/src/chat/claude-backend.ts +58 -26
  103. package/src/chat/claude-protocol.ts +147 -8
  104. package/src/chat/claude-title.ts +11 -39
  105. package/src/chat/claude-transcript.ts +38 -18
  106. package/src/chat/codex-backend.ts +182 -20
  107. package/src/chat/codex-protocol.ts +40 -5
  108. package/src/chat/codex-thread.ts +1 -4
  109. package/src/chat/codex-transport.ts +45 -35
  110. package/src/chat/context-breakdown.ts +2 -2
  111. package/src/chat/errors.ts +1 -0
  112. package/src/chat/external-sessions.ts +2 -2
  113. package/src/chat/fixtures/claude-2.1.296-goal.json +136 -0
  114. package/src/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10.jsonl +2 -0
  115. package/src/chat/index.ts +49 -0
  116. package/src/chat/projector.ts +13 -4
  117. package/src/chat/request-summary.ts +8 -5
  118. package/src/chat/subagent-settlement.ts +1 -4
  119. package/src/chat/thread.ts +22 -3
  120. package/src/chat/ui-queries.ts +46 -5
  121. package/src/chat/ui-replies.ts +187 -0
  122. package/src/context/index.ts +26 -0
  123. package/src/coordination/index.ts +67 -0
  124. package/src/host/handlers.ts +8 -0
  125. package/src/host/index.ts +8 -0
  126. package/src/index.ts +20 -0
  127. package/src/providers/accounts/status.ts +1 -4
  128. package/src/providers/claude.ts +3 -1
  129. package/src/providers/codex.ts +3 -1
  130. package/src/providers/index.ts +15 -0
  131. package/src/run-process.ts +56 -16
  132. package/src/skills.ts +5 -0
  133. package/src/tasks/task-coordinator.ts +22 -2
  134. package/src/tasks/wiring.ts +7 -1
  135. package/src/{providers/accounts/test-accounts.ts → testing/accounts.ts} +4 -4
  136. package/src/testing/bin/fake-claude.ts +7 -0
  137. package/src/testing/bin/fake-codex.ts +7 -0
  138. package/src/{chat → testing}/fake-claude.ts +1 -5
  139. package/src/{chat → testing}/fake-cli.ts +1 -1
  140. package/src/{chat → testing}/fake-codex.ts +75 -6
  141. package/src/testing/index.ts +7 -0
  142. package/src/{outbox → testing}/manual-clock.ts +1 -1
  143. package/src/{watch-test-helpers.ts → testing/watch.ts} +1 -1
  144. package/src/usage/exchange.ts +31 -20
  145. package/src/usage/index-file.ts +23 -2
  146. package/src/usage/index.ts +10 -0
  147. package/src/usage/limits/normalize.ts +1 -4
  148. package/src/usage/pricing.ts +34 -23
  149. package/src/usage/scanner.ts +48 -11
  150. package/src/usage/usage-service.ts +8 -3
  151. /package/dist/{chat → testing}/fake-cli.js +0 -0
  152. /package/dist/{outbox → testing}/manual-clock.js +0 -0
  153. /package/dist/{watch-test-helpers.js → testing/watch.js} +0 -0
@@ -12,7 +12,9 @@ export function spawnChatProcess(options) {
12
12
  env: options.env,
13
13
  stdio: ['pipe', 'pipe', 'pipe'],
14
14
  // A group of its own, so ending the chat also ends what its agent started (a dev server, a watcher).
15
- detached: true
15
+ // On Windows that would open a console window of its own instead; `taskkill` reaches the tree there.
16
+ detached: process.platform !== 'win32',
17
+ windowsHide: true
16
18
  });
17
19
  // Node reports a missing executable as an event after the call; a start that failed says so on the spot.
18
20
  child.on('error', () => undefined);
@@ -44,16 +46,31 @@ export function spawnChatProcess(options) {
44
46
  },
45
47
  stdout: Readable.toWeb(child.stdout),
46
48
  stderr: Readable.toWeb(child.stderr),
47
- kill: (signal) => {
48
- try {
49
- process.kill(-pid, signal);
50
- }
51
- catch {
52
- // Nothing of the group is left to signal.
53
- }
54
- }
49
+ kill: (signal) => killProcessTree(pid, signal)
55
50
  };
56
51
  }
52
+ /* Signals a process and everything it started. Windows has no process groups and no SIGTERM, so there the tree is ended at once. */
53
+ export function killProcessTree(pid, signal, options = {}) {
54
+ const { platform = process.platform, kill = process.kill, run = runQuietly } = options;
55
+ if (platform === 'win32') {
56
+ run(['taskkill', '/pid', String(pid), '/t', '/f']);
57
+ return;
58
+ }
59
+ try {
60
+ kill(-pid, signal);
61
+ }
62
+ catch {
63
+ // Nothing of the group is left to signal.
64
+ }
65
+ }
66
+ function runQuietly([command, ...args]) {
67
+ if (command === undefined) {
68
+ return;
69
+ }
70
+ const child = spawn(command, args, { stdio: 'ignore', windowsHide: true });
71
+ // A tree that already ended makes taskkill fail, which is what the caller wanted anyway.
72
+ child.on('error', () => undefined);
73
+ }
57
74
  // After stdin closed, a CLI that is still around is not going to say more.
58
75
  const EXIT_GRACE_MS = 3000;
59
76
  // What a CLI and everything it started get between the SIGTERM and the SIGKILL.
@@ -99,6 +116,89 @@ export class StreamTail {
99
116
  }
100
117
  }
101
118
  }
119
+ // Far above any frame either CLI writes, a base64 document in a tool result included; it only bounds a CLI that stopped breaking lines.
120
+ export const MAX_LINE_LENGTH = 64_000_000;
121
+ /*
122
+ * Cuts decoded output into lines. A chunk is searched only for itself and a partial line is joined
123
+ * once, when its line break comes, so a long line costs its length once. A line longer than `max`
124
+ * UTF-16 units is dropped whole, with `onOverflow` called once for it, and the next line reads as usual.
125
+ */
126
+ export class LineSplitter {
127
+ onLine;
128
+ onOverflow;
129
+ max;
130
+ parts = [];
131
+ length = 0;
132
+ dropping = false;
133
+ constructor(onLine, onOverflow, max = MAX_LINE_LENGTH) {
134
+ this.onLine = onLine;
135
+ this.onOverflow = onOverflow;
136
+ this.max = max;
137
+ }
138
+ push(text) {
139
+ let start = 0;
140
+ let newline = text.indexOf('\n');
141
+ while (newline >= 0) {
142
+ this.add(text.slice(start, newline));
143
+ const line = this.take();
144
+ if (line !== null) {
145
+ this.onLine(line);
146
+ }
147
+ start = newline + 1;
148
+ newline = text.indexOf('\n', start);
149
+ }
150
+ this.add(text.slice(start));
151
+ }
152
+ /* Hands on what came after the last line break, for a stream that ended without one. */
153
+ end() {
154
+ const line = this.take();
155
+ if (line !== null && line !== '') {
156
+ this.onLine(line);
157
+ }
158
+ }
159
+ add(piece) {
160
+ if (this.dropping || piece === '') {
161
+ return;
162
+ }
163
+ this.length += piece.length;
164
+ if (this.length > this.max) {
165
+ this.parts = [];
166
+ this.dropping = true;
167
+ this.onOverflow();
168
+ return;
169
+ }
170
+ this.parts.push(piece);
171
+ }
172
+ take() {
173
+ const line = this.dropping ? null : this.parts.join('');
174
+ this.parts = [];
175
+ this.length = 0;
176
+ this.dropping = false;
177
+ return line;
178
+ }
179
+ }
180
+ /*
181
+ * Hands every line of a CLI's output to `onLine` until the stream ends, through a `LineSplitter`.
182
+ * A read that fails rejects, after every line that came before it was handed on.
183
+ */
184
+ export async function readStreamLines(stream, onLine, onOverflow, max = MAX_LINE_LENGTH) {
185
+ const reader = stream.getReader();
186
+ const decoder = new TextDecoder();
187
+ const lines = new LineSplitter(onLine, onOverflow, max);
188
+ try {
189
+ while (true) {
190
+ const { value, done } = await reader.read();
191
+ if (done) {
192
+ break;
193
+ }
194
+ lines.push(decoder.decode(value, { stream: true }));
195
+ }
196
+ lines.end();
197
+ }
198
+ finally {
199
+ reader.releaseLock();
200
+ }
201
+ }
102
202
  /*
103
203
  * A spawned CLI and how it ends. Every signal goes to its process group, SIGTERM first and SIGKILL
104
204
  * after a grace, and only ever because a person stopped, removed or restarted something.
@@ -1,5 +1,4 @@
1
- import type { ChatAttachment, ChatAssistantItem, ChatCheckpointDiff, ChatEvent, ChatInfo, ChatItem, ChatQueuedMessage, ChatQuoteSource, ChatSkill, ChatUiChoiceOrigin, ChatUiChoicePayload, ChatUiQueryState, ModelSelection, RuntimeMode } from '@adecore/agent-contracts';
2
- import type { UiCompileOptions } from '@adecore/intelligent-ui/compiler';
1
+ import type { ChatAttachment, ChatCheckpointDiff, ChatEvent, ChatGoalAction, ChatInfo, ChatItem, ChatQueuedMessage, ChatQuoteSource, ChatSkill, ChatUiChoiceOrigin, ChatUiChoicePayload, ChatUiQueryState, ModelSelection, RuntimeMode } from '@adecore/agent-contracts';
3
2
  import type { ChatProvider } from '../providers/provider.ts';
4
3
  import type { LimitsUpdate } from '../usage/limits/normalize.ts';
5
4
  import type { BackendLaunch } from './backend.ts';
@@ -7,6 +6,7 @@ import type { SpawnChatProcess } from './chat-process.ts';
7
6
  import type { ChatTitleInput } from './chat-title.ts';
8
7
  import type { SubagentSettlement } from './subagent-settlement.ts';
9
8
  import { ChatThread } from './thread.ts';
9
+ import { type UiReplyHost } from './ui-replies.ts';
10
10
  import { type OutboxClock } from '../outbox/outbox-worker.ts';
11
11
  export interface TurnCheckpoints {
12
12
  take(cwd: string): Promise<string | null>;
@@ -46,10 +46,7 @@ export interface ChatSessionOptions {
46
46
  references?: ChatReferences;
47
47
  checkpoints?: TurnCheckpoints;
48
48
  uiFenceLanguage?: string;
49
- ui?: {
50
- schemas: UiCompileOptions['querySchemas'];
51
- observe(item: ChatAssistantItem, final: boolean): void;
52
- };
49
+ ui?: UiReplyHost;
53
50
  emit(event: ChatEvent): void;
54
51
  onLimits?(update: LimitsUpdate): void;
55
52
  persist(): void;
@@ -109,13 +106,8 @@ export declare class ChatSession {
109
106
  private pendingPreambles;
110
107
  private submission;
111
108
  private readonly steering;
112
- private readonly uiStreams;
113
- private readonly uiCompiled;
114
109
  private readonly capturedUiAccess;
115
- private readonly uiScanned;
116
- private readonly uiReferencing;
117
- private readonly uiAttachments;
118
- private readonly uiFenceLanguage;
110
+ private readonly uiReplies;
119
111
  constructor(options: ChatSessionOptions);
120
112
  get uiPreviews(): ChatEvent[];
121
113
  previewItems(items: ChatItem[]): ChatItem[];
@@ -125,6 +117,8 @@ export declare class ChatSession {
125
117
  get preambles(): readonly string[];
126
118
  get pid(): number | null;
127
119
  get busy(): boolean;
120
+ private goalWorks;
121
+ goal(action: ChatGoalAction): Promise<void>;
128
122
  configure(patch: {
129
123
  selection?: ModelSelection;
130
124
  runtimeMode?: RuntimeMode;
@@ -162,6 +156,8 @@ export declare class ChatSession {
162
156
  approve(requestId: string, decision: 'allow' | 'allow-always' | 'deny', message?: string): boolean;
163
157
  answer(requestId: string, answers: Record<string, string>): boolean;
164
158
  dismiss(itemId: string): boolean;
159
+ holdForPerson(key: string): void;
160
+ releaseHold(key: string): void;
165
161
  clear(force: boolean): Promise<void>;
166
162
  settleStored(selection: ModelSelection, resume: ResumeDecision): void;
167
163
  resume(turnId: string, attempt: number, words: ResumeWords): Promise<void>;
@@ -193,6 +189,7 @@ export declare class ChatSession {
193
189
  upsertItems(items: readonly ChatItem[]): void;
194
190
  addNote(level: 'info' | 'warning' | 'error', text: string): void;
195
191
  end(reason: string): void;
192
+ restart(): Promise<void>;
196
193
  freeze(): void;
197
194
  dispose(): Promise<void>;
198
195
  turnDiff(turnId: string): Promise<ChatCheckpointDiff | null>;
@@ -237,6 +234,7 @@ export declare class ChatSession {
237
234
  private pauseQueue;
238
235
  private clearWorkflowWarnings;
239
236
  private watchWorkflows;
237
+ private watchWorkflow;
240
238
  private reportsCurrentWindow;
241
239
  private refreshTitle;
242
240
  private applyTitle;
@@ -245,11 +243,6 @@ export declare class ChatSession {
245
243
  private settleFromTranscripts;
246
244
  private settleRows;
247
245
  private emit;
248
- private unscannedUiText;
249
- private forgetUiScan;
250
- private latestUiAttachment;
251
- private findUiAttachment;
252
- private clearUi;
253
246
  private delegatingChange;
254
247
  }
255
248
  export interface ResumeDecision {