atom-agent 1.3.0 → 1.5.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.
- package/CHANGELOG.md +62 -0
- package/README.md +220 -224
- package/dist/App.js +922 -341
- package/dist/adapters.js +127 -14
- package/dist/agent/goal-evaluator.js +3 -0
- package/dist/agent/loop.js +211 -430
- package/dist/agent/tool-pipeline.js +398 -0
- package/dist/agent/turn-events.js +12 -0
- package/dist/cli.js +57 -8
- package/dist/compact.js +72 -8
- package/dist/config.js +19 -0
- package/dist/context-manager.js +6 -2
- package/dist/extensions.js +6 -0
- package/dist/file-diffs.js +108 -0
- package/dist/kilo.js +1 -1
- package/dist/local-discovery.js +2 -2
- package/dist/media.js +276 -0
- package/dist/overflow.js +140 -0
- package/dist/policy.js +8 -0
- package/dist/scheduler.js +38 -9
- package/dist/session-revert.js +125 -0
- package/dist/sessions.js +101 -0
- package/dist/snapshots.js +69 -0
- package/dist/system.js +2 -89
- package/dist/telemetry.js +26 -1
- package/dist/todos.js +241 -0
- package/dist/tools/filesystem.js +102 -22
- package/dist/tools/registry.js +184 -45
- package/dist/tools/ripgrep.js +7 -6
- package/dist/tools/search.js +172 -17
- package/dist/tools/shared.js +6 -0
- package/dist/tools.js +7 -39
- package/dist/ui/diff-panel.js +5 -5
- package/dist/ui/diff-view.js +16 -7
- package/dist/ui/diff.js +73 -51
- package/dist/ui/errors.js +20 -6
- package/dist/ui/input.js +24 -20
- package/dist/ui/live-tail.js +36 -1
- package/dist/ui/markdown.js +9 -4
- package/dist/ui/modals.js +6 -4
- package/dist/ui/paint-scheduler.js +120 -0
- package/dist/ui/palette.js +4 -2
- package/dist/ui/pickers.js +4 -1
- package/dist/ui/side-by-side.js +88 -27
- package/dist/ui/status-bar.js +63 -8
- package/dist/ui/stream-store.js +7 -0
- package/dist/ui/theme.js +23 -1
- package/dist/ui/todo-panel.js +5 -2
- package/dist/ui/tool-inspector.js +33 -4
- package/dist/ui/transcript.js +9 -6
- package/dist/web/events.js +93 -0
- package/dist/web/runtime.js +790 -0
- package/dist/web/server.js +570 -0
- package/dist/web/ui/app.js +1925 -0
- package/dist/web/ui/index.html +135 -0
- package/dist/web/ui/styles.css +515 -0
- package/dist/zen.js +115 -4
- package/documentation/cli.md +5 -5
- package/documentation/configuration.md +11 -6
- package/documentation/development.md +4 -3
- package/documentation/extensions.md +1 -1
- package/documentation/goals.md +1 -1
- package/documentation/index.md +4 -4
- package/documentation/providers.md +2 -3
- package/documentation/skills.md +3 -3
- package/documentation/tools.md +8 -3
- package/documentation/troubleshooting.md +1 -1
- package/examples/extensions/01-audit-gate.js +2 -2
- package/examples/extensions/02-notes-tool.js +2 -2
- package/examples/extensions/03-custom-command.js +2 -2
- package/package.json +3 -2
package/dist/adapters.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// Normalized output matches zen ChatResult:
|
|
7
7
|
// {content, tool_calls:[{id,function:{name,arguments}}], usage?}
|
|
8
8
|
// so runAgenticLoop/retry/rollback/status code is untouched.
|
|
9
|
-
import {
|
|
9
|
+
import { chatToolDefinitions } from "./tools.js";
|
|
10
10
|
import { getProvider, modelsUrlForProvider, } from "./providers.js";
|
|
11
11
|
export const ANTHROPIC_VERSION = "2023-06-01";
|
|
12
12
|
export const ANTHROPIC_MAX_TOKENS = 4096;
|
|
@@ -64,10 +64,13 @@ export function geminiThinkingLevelFor(effort) {
|
|
|
64
64
|
export function isEffortRejection(errorText) {
|
|
65
65
|
return /reasoning_effort|reasoning effort|thinking_level|budget_tokens|\bthinking\b/i.test(errorText);
|
|
66
66
|
}
|
|
67
|
-
function toolDefs() {
|
|
67
|
+
function toolDefs(includeUpdateGoal = true) {
|
|
68
68
|
// Builtins plus extension-registered custom tools, so non-OpenAI kinds
|
|
69
69
|
// see the same model-visible surface as the OpenAI-chat path.
|
|
70
|
-
|
|
70
|
+
// includeUpdateGoal:false hides update_goal when the turn has no live
|
|
71
|
+
// goal (same contract as chatToolDefinitions — default keeps every
|
|
72
|
+
// existing caller byte-identical).
|
|
73
|
+
return chatToolDefinitions(includeUpdateGoal);
|
|
71
74
|
}
|
|
72
75
|
function parseArgsObject(raw) {
|
|
73
76
|
try {
|
|
@@ -81,11 +84,16 @@ function parseArgsObject(raw) {
|
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
import { ephemeralBreakpoint, assemblePrefix } from "./prompt-cache.js";
|
|
87
|
+
import { hasMediaRefs, resolveMediaRefs, stripMedia, } from "./media.js";
|
|
84
88
|
export function buildAnthropicBody(history, model, opts) {
|
|
85
89
|
const systems = [];
|
|
86
90
|
const messages = [];
|
|
87
91
|
// Group consecutive tool messages into one user message with
|
|
88
92
|
// multiple tool_result blocks (Anthropic convention).
|
|
93
|
+
// Media lowering (see src/media.ts): histories without descriptors take
|
|
94
|
+
// the string path byte-identically; descriptor-bearing user/tool content
|
|
95
|
+
// expands to text + base64 image blocks (strip mode: prose markers).
|
|
96
|
+
const strip = opts?.stripMedia === true;
|
|
89
97
|
let pendingToolResults = [];
|
|
90
98
|
function flushTools() {
|
|
91
99
|
if (pendingToolResults.length === 0)
|
|
@@ -95,20 +103,64 @@ export function buildAnthropicBody(history, model, opts) {
|
|
|
95
103
|
}
|
|
96
104
|
for (const m of history) {
|
|
97
105
|
if (m.role === "system") {
|
|
98
|
-
systems.push(m.content);
|
|
106
|
+
systems.push(strip ? stripMedia(m.content) : m.content);
|
|
99
107
|
continue;
|
|
100
108
|
}
|
|
101
109
|
if (m.role === "tool") {
|
|
110
|
+
if (!hasMediaRefs(m.content)) {
|
|
111
|
+
pendingToolResults.push({
|
|
112
|
+
type: "tool_result",
|
|
113
|
+
tool_use_id: m.tool_call_id,
|
|
114
|
+
content: strip ? stripMedia(m.content) : m.content,
|
|
115
|
+
});
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (strip) {
|
|
119
|
+
pendingToolResults.push({
|
|
120
|
+
type: "tool_result",
|
|
121
|
+
tool_use_id: m.tool_call_id,
|
|
122
|
+
content: stripMedia(m.content),
|
|
123
|
+
});
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const { text, media } = resolveMediaRefs(m.content);
|
|
127
|
+
const blocks = [{ type: "text", text }];
|
|
128
|
+
for (const part of media) {
|
|
129
|
+
if (!part.ok)
|
|
130
|
+
continue; // placeholder already inline in text
|
|
131
|
+
blocks.push({
|
|
132
|
+
type: "image",
|
|
133
|
+
source: { type: "base64", media_type: part.mime, data: part.base64 },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
102
136
|
pendingToolResults.push({
|
|
103
137
|
type: "tool_result",
|
|
104
138
|
tool_use_id: m.tool_call_id,
|
|
105
|
-
content:
|
|
139
|
+
content: blocks,
|
|
106
140
|
});
|
|
107
141
|
continue;
|
|
108
142
|
}
|
|
109
143
|
flushTools();
|
|
110
144
|
if (m.role === "user") {
|
|
111
|
-
|
|
145
|
+
if (!hasMediaRefs(m.content)) {
|
|
146
|
+
messages.push({ role: "user", content: strip ? stripMedia(m.content) : m.content });
|
|
147
|
+
}
|
|
148
|
+
else if (strip) {
|
|
149
|
+
messages.push({ role: "user", content: stripMedia(m.content) });
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const { text, media } = resolveMediaRefs(m.content);
|
|
153
|
+
const blocks = [{ type: "text", text }];
|
|
154
|
+
for (const part of media) {
|
|
155
|
+
if (!part.ok)
|
|
156
|
+
continue;
|
|
157
|
+
blocks.push({
|
|
158
|
+
type: "image",
|
|
159
|
+
source: { type: "base64", media_type: part.mime, data: part.base64 },
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
messages.push({ role: "user", content: blocks });
|
|
163
|
+
}
|
|
112
164
|
}
|
|
113
165
|
else {
|
|
114
166
|
// assistant: text + tool_use blocks
|
|
@@ -140,7 +192,7 @@ export function buildAnthropicBody(history, model, opts) {
|
|
|
140
192
|
// Compaction path (includeTools:false) omits `tools` + `tool_choice`
|
|
141
193
|
// entirely — asserted in tests as "no `tools` key".
|
|
142
194
|
if (includeTools) {
|
|
143
|
-
const defs = toolDefs().map((t) => ({
|
|
195
|
+
const defs = toolDefs(opts?.includeUpdateGoal !== false).map((t) => ({
|
|
144
196
|
name: t.function.name,
|
|
145
197
|
description: t.function.description,
|
|
146
198
|
input_schema: t.function.parameters,
|
|
@@ -222,10 +274,15 @@ export function geminiHeaders(apiKey) {
|
|
|
222
274
|
};
|
|
223
275
|
}
|
|
224
276
|
export function buildGeminiBody(history, _model, opts) {
|
|
277
|
+
// Media lowering (see src/media.ts): histories without descriptors take
|
|
278
|
+
// the legacy path byte-identically. Tool-result images ride as inline_data
|
|
279
|
+
// user parts after their functionResponse (function responses stay text);
|
|
280
|
+
// user-message images ride inline. Strip mode: prose markers only.
|
|
281
|
+
const strip = opts?.stripMedia === true;
|
|
225
282
|
const systems = [];
|
|
226
283
|
for (const m of history) {
|
|
227
284
|
if (m.role === "system")
|
|
228
|
-
systems.push(m.content);
|
|
285
|
+
systems.push(strip ? stripMedia(m.content) : m.content);
|
|
229
286
|
}
|
|
230
287
|
// tool_call_id -> function name (tool messages carry only the id).
|
|
231
288
|
const nameById = new Map();
|
|
@@ -239,27 +296,83 @@ export function buildGeminiBody(history, _model, opts) {
|
|
|
239
296
|
}
|
|
240
297
|
const contents = [];
|
|
241
298
|
let pendingResponses = [];
|
|
299
|
+
// Images resolved out of tool results (flushed as user inline_data parts
|
|
300
|
+
// right after their functionResponse group).
|
|
301
|
+
let pendingToolImages = [];
|
|
242
302
|
function flushResponses() {
|
|
243
|
-
if (pendingResponses.length === 0)
|
|
303
|
+
if (pendingResponses.length === 0 && pendingToolImages.length === 0)
|
|
244
304
|
return;
|
|
245
|
-
|
|
246
|
-
|
|
305
|
+
if (pendingResponses.length > 0) {
|
|
306
|
+
contents.push({ role: "user", parts: pendingResponses });
|
|
307
|
+
pendingResponses = [];
|
|
308
|
+
}
|
|
309
|
+
if (pendingToolImages.length > 0) {
|
|
310
|
+
const parts = [
|
|
311
|
+
{
|
|
312
|
+
text: `Image(s) from tool result: ${pendingToolImages.map((i) => i.name).join(", ")}`,
|
|
313
|
+
},
|
|
314
|
+
];
|
|
315
|
+
for (const img of pendingToolImages) {
|
|
316
|
+
parts.push({ inline_data: { mime_type: img.mime, data: img.data } });
|
|
317
|
+
}
|
|
318
|
+
pendingToolImages = [];
|
|
319
|
+
contents.push({ role: "user", parts });
|
|
320
|
+
}
|
|
247
321
|
}
|
|
248
322
|
for (const m of history) {
|
|
249
323
|
if (m.role === "system")
|
|
250
324
|
continue;
|
|
251
325
|
if (m.role === "tool") {
|
|
326
|
+
if (!hasMediaRefs(m.content)) {
|
|
327
|
+
pendingResponses.push({
|
|
328
|
+
functionResponse: {
|
|
329
|
+
name: nameById.get(m.tool_call_id) ?? "unknown",
|
|
330
|
+
response: { result: strip ? stripMedia(m.content) : m.content },
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (strip) {
|
|
336
|
+
pendingResponses.push({
|
|
337
|
+
functionResponse: {
|
|
338
|
+
name: nameById.get(m.tool_call_id) ?? "unknown",
|
|
339
|
+
response: { result: stripMedia(m.content) },
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const { text, media } = resolveMediaRefs(m.content);
|
|
252
345
|
pendingResponses.push({
|
|
253
346
|
functionResponse: {
|
|
254
347
|
name: nameById.get(m.tool_call_id) ?? "unknown",
|
|
255
|
-
response: { result:
|
|
348
|
+
response: { result: text },
|
|
256
349
|
},
|
|
257
350
|
});
|
|
351
|
+
for (const part of media) {
|
|
352
|
+
if (!part.ok)
|
|
353
|
+
continue;
|
|
354
|
+
pendingToolImages.push({ mime: part.mime, data: part.base64, name: part.name });
|
|
355
|
+
}
|
|
258
356
|
continue;
|
|
259
357
|
}
|
|
260
358
|
flushResponses();
|
|
261
359
|
if (m.role === "user") {
|
|
262
|
-
|
|
360
|
+
if (!hasMediaRefs(m.content)) {
|
|
361
|
+
contents.push({ role: "user", parts: [{ text: strip ? stripMedia(m.content) : m.content }] });
|
|
362
|
+
}
|
|
363
|
+
else if (strip) {
|
|
364
|
+
contents.push({ role: "user", parts: [{ text: stripMedia(m.content) }] });
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
const { text, media } = resolveMediaRefs(m.content);
|
|
368
|
+
const parts = [{ text }];
|
|
369
|
+
for (const part of media) {
|
|
370
|
+
if (!part.ok)
|
|
371
|
+
continue;
|
|
372
|
+
parts.push({ inline_data: { mime_type: part.mime, data: part.base64 } });
|
|
373
|
+
}
|
|
374
|
+
contents.push({ role: "user", parts });
|
|
375
|
+
}
|
|
263
376
|
}
|
|
264
377
|
else {
|
|
265
378
|
const am = m;
|
|
@@ -290,7 +403,7 @@ export function buildGeminiBody(history, _model, opts) {
|
|
|
290
403
|
if (includeTools) {
|
|
291
404
|
body.tools = [
|
|
292
405
|
{
|
|
293
|
-
functionDeclarations: toolDefs().map((t) => ({
|
|
406
|
+
functionDeclarations: toolDefs(opts?.includeUpdateGoal !== false).map((t) => ({
|
|
294
407
|
name: t.function.name,
|
|
295
408
|
description: t.function.description,
|
|
296
409
|
parameters: stripGeminiSchemaKeys(t.function.parameters),
|
|
@@ -51,6 +51,9 @@ export async function requestGoalVerdict(req) {
|
|
|
51
51
|
endpointOverride: req.endpointOverride,
|
|
52
52
|
disableTools: true,
|
|
53
53
|
maxOutputTokens: req.maxOutputTokens ?? GOAL_JUDGE_MAX_TOKENS,
|
|
54
|
+
// The judge needs prose, not pixels — same strip contract as the
|
|
55
|
+
// compaction summary POST.
|
|
56
|
+
stripMedia: true,
|
|
54
57
|
...(req.signal ? { signal: req.signal } : {}),
|
|
55
58
|
});
|
|
56
59
|
// Totals keep accumulating: forward real judge usage when present.
|