neoctl 0.2.0 → 0.2.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.
- package/README.md +20 -9
- package/dist/context/compaction.d.ts +3 -0
- package/dist/context/compaction.js +231 -40
- package/dist/context/compaction.js.map +1 -1
- package/dist/context/prompts.js +4 -4
- package/dist/context/prompts.js.map +1 -1
- package/dist/core/commands.d.ts +66 -0
- package/dist/core/commands.js +151 -0
- package/dist/core/commands.js.map +1 -0
- package/dist/core/context-metrics.d.ts +5 -2
- package/dist/core/context-metrics.js +85 -9
- package/dist/core/context-metrics.js.map +1 -1
- package/dist/core/image-registry.d.ts +42 -0
- package/dist/core/image-registry.js +128 -0
- package/dist/core/image-registry.js.map +1 -0
- package/dist/core/message-pipeline.d.ts +6 -0
- package/dist/core/message-pipeline.js +12 -0
- package/dist/core/message-pipeline.js.map +1 -1
- package/dist/core/query-engine.d.ts +3 -5
- package/dist/core/query-engine.js +35 -48
- package/dist/core/query-engine.js.map +1 -1
- package/dist/core/query.d.ts +1 -5
- package/dist/core/query.js +21 -8
- package/dist/core/query.js.map +1 -1
- package/dist/core/runtime.d.ts +59 -0
- package/dist/core/runtime.js +161 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/state.d.ts +6 -7
- package/dist/core/state.js +2 -0
- package/dist/core/state.js.map +1 -1
- package/dist/index.d.ts +14 -10
- package/dist/index.js +14 -10
- package/dist/index.js.map +1 -1
- package/dist/model/anthropic-adapter.d.ts +30 -0
- package/dist/model/anthropic-adapter.js +106 -0
- package/dist/model/anthropic-adapter.js.map +1 -0
- package/dist/model/anthropic-mapper.d.ts +13 -0
- package/dist/model/anthropic-mapper.js +482 -0
- package/dist/model/anthropic-mapper.js.map +1 -0
- package/dist/model/config.d.ts +8 -2
- package/dist/model/config.js +24 -1
- package/dist/model/config.js.map +1 -1
- package/dist/model/model-gateway.js +1 -1
- package/dist/model/model-gateway.js.map +1 -1
- package/dist/model/openai-mappers.js +1 -1
- package/dist/model/openai-mappers.js.map +1 -1
- package/dist/model/provider-factory.js +17 -0
- package/dist/model/provider-factory.js.map +1 -1
- package/dist/model/smoke-anthropic-mapper.d.ts +1 -0
- package/dist/model/smoke-anthropic-mapper.js +85 -0
- package/dist/model/smoke-anthropic-mapper.js.map +1 -0
- package/dist/repl/index.js +77 -70
- package/dist/repl/index.js.map +1 -1
- package/dist/repl/markdown-renderer.d.ts +19 -0
- package/dist/repl/markdown-renderer.js +58 -3
- package/dist/repl/markdown-renderer.js.map +1 -1
- package/dist/repl/transcript-flush.d.ts +6 -0
- package/dist/repl/transcript-flush.js +54 -0
- package/dist/repl/transcript-flush.js.map +1 -0
- package/dist/repl/transcript-format.d.ts +16 -0
- package/dist/repl/transcript-format.js +199 -0
- package/dist/repl/transcript-format.js.map +1 -0
- package/dist/server/agent-manager.d.ts +56 -0
- package/dist/server/agent-manager.js +171 -0
- package/dist/server/agent-manager.js.map +1 -0
- package/dist/server/connection-manager.d.ts +18 -0
- package/dist/server/connection-manager.js +52 -0
- package/dist/server/connection-manager.js.map +1 -0
- package/dist/server/event-mapper.d.ts +4 -0
- package/dist/server/event-mapper.js +31 -0
- package/dist/server/event-mapper.js.map +1 -0
- package/dist/server/query-runtime.d.ts +29 -0
- package/dist/server/query-runtime.js +61 -0
- package/dist/server/query-runtime.js.map +1 -0
- package/dist/server/rpc-router.d.ts +24 -0
- package/dist/server/rpc-router.js +165 -0
- package/dist/server/rpc-router.js.map +1 -0
- package/dist/server/rpc-types.d.ts +92 -0
- package/dist/server/rpc-types.js +2 -0
- package/dist/server/rpc-types.js.map +1 -0
- package/dist/server/ws-server.d.ts +22 -0
- package/dist/server/ws-server.js +84 -0
- package/dist/server/ws-server.js.map +1 -0
- package/dist/session/session-export.d.ts +0 -1
- package/dist/session/session-export.js +1 -2
- package/dist/session/session-export.js.map +1 -1
- package/dist/skills/skill-tool.js +1 -1
- package/dist/skills/skill-tool.js.map +1 -1
- package/dist/tasks/task-record.d.ts +50 -0
- package/dist/tasks/task-record.js +50 -0
- package/dist/tasks/task-record.js.map +1 -0
- package/dist/tasks/task-store.d.ts +9 -23
- package/dist/tasks/task-store.js +2 -37
- package/dist/tasks/task-store.js.map +1 -1
- package/dist/tasks/task-tools.d.ts +3 -18
- package/dist/tasks/task-tools.js +9 -89
- package/dist/tasks/task-tools.js.map +1 -1
- package/dist/tips.js +6 -6
- package/dist/tips.js.map +1 -1
- package/dist/tools/builtins/exec-tool.js +2 -2
- package/dist/tools/builtins/exec-tool.js.map +1 -1
- package/dist/tools/builtins/image-loader-tool.d.ts +22 -0
- package/dist/tools/builtins/image-loader-tool.js +235 -0
- package/dist/tools/builtins/image-loader-tool.js.map +1 -0
- package/dist/types/messages.d.ts +0 -1
- package/dist/types/messages.js.map +1 -1
- package/dist/web/html.js +3 -4
- package/dist/web/html.js.map +1 -1
- package/dist/web/index.d.ts +11 -5
- package/dist/web/index.js +68 -28
- package/dist/web/index.js.map +1 -1
- package/package.json +3 -1
package/dist/web/html.js
CHANGED
|
@@ -686,8 +686,7 @@ async function submit() {
|
|
|
686
686
|
input.value = '';
|
|
687
687
|
state.attachments = [];
|
|
688
688
|
if (state.busy) {
|
|
689
|
-
state.
|
|
690
|
-
state.queuedInput = undefined;
|
|
689
|
+
state.queuedInput = text;
|
|
691
690
|
}
|
|
692
691
|
autosize();
|
|
693
692
|
renderCompletions();
|
|
@@ -752,8 +751,8 @@ input.addEventListener('keydown', (e) => {
|
|
|
752
751
|
if (e.key === 'ArrowUp' && !input.value) { e.preventDefault(); advanceTip(-1); return; }
|
|
753
752
|
if (e.key === 'ArrowDown' && state.historyIndex !== undefined) { e.preventDefault(); state.historyIndex -= 1; if (state.historyIndex < 0) { state.historyIndex = undefined; input.value = ''; } else input.value = state.history[state.historyIndex] || ''; autosize(); return; }
|
|
754
753
|
if (e.key === 'ArrowDown' && !input.value) { e.preventDefault(); advanceTip(); return; }
|
|
755
|
-
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'c') { if (input.value) { input.value = ''; autosize(); renderCompletions(); } else fetch('/api/interrupt', { method: 'POST' }); }
|
|
756
|
-
if (e.key === 'Escape') { state.completionIndex = 0; if (state.queuedInput) fetch('/api/
|
|
754
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'c') { if (input.value) { input.value = ''; autosize(); renderCompletions(); } else if (state.queuedInput) { state.queuedInput = undefined; scheduleRender(); fetch('/api/queue/cancel', { method: 'POST' }); } else fetch('/api/interrupt', { method: 'POST' }); }
|
|
755
|
+
if (e.key === 'Escape') { state.completionIndex = 0; if (state.queuedInput) { state.queuedInput = undefined; scheduleRender(); fetch('/api/queue/cancel', { method: 'POST' }); } else renderCompletions(); }
|
|
757
756
|
});
|
|
758
757
|
document.addEventListener('keydown', (e) => {
|
|
759
758
|
if (e.target === input || e.target.closest('input, textarea, select')) return;
|
package/dist/web/html.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/web/html.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/web/html.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA21B1B,CAAC"}
|
package/dist/web/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface WebRuntime {
|
|
|
13
13
|
communicationLogger: CommunicationLogger;
|
|
14
14
|
modelGateway: LoggingModelGateway;
|
|
15
15
|
agentRuntime: AgentToolRuntime;
|
|
16
|
-
usage:
|
|
16
|
+
usage: WebSessionUsageTracker;
|
|
17
17
|
taskStore: TaskStore;
|
|
18
18
|
tools: ToolRegistry;
|
|
19
19
|
initialMetrics: ContextMetrics;
|
|
@@ -21,7 +21,7 @@ export interface WebRuntime {
|
|
|
21
21
|
envPath: string;
|
|
22
22
|
envNotice?: string;
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
interface WebUsageTotals {
|
|
25
25
|
inputTokens: number;
|
|
26
26
|
outputTokens: number;
|
|
27
27
|
totalTokens: number;
|
|
@@ -30,12 +30,12 @@ export interface UsageTotals {
|
|
|
30
30
|
requests: number;
|
|
31
31
|
computedTotalTokens: boolean;
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
declare class WebSessionUsageTracker {
|
|
34
34
|
private totals;
|
|
35
35
|
private lastUsage?;
|
|
36
36
|
add(usage: ModelUsage): void;
|
|
37
37
|
reset(): void;
|
|
38
|
-
snapshot():
|
|
38
|
+
snapshot(): WebUsageTotals;
|
|
39
39
|
}
|
|
40
40
|
interface UiLineImage {
|
|
41
41
|
src: string;
|
|
@@ -140,6 +140,7 @@ export declare class WebRepl {
|
|
|
140
140
|
private status;
|
|
141
141
|
private busy;
|
|
142
142
|
private queuedInput;
|
|
143
|
+
private queuedAttachments;
|
|
143
144
|
private foregroundRun;
|
|
144
145
|
private foregroundRunToken;
|
|
145
146
|
private readonly backgroundSessionRuns;
|
|
@@ -165,7 +166,7 @@ export declare class WebRepl {
|
|
|
165
166
|
runningSessionIds: string[];
|
|
166
167
|
session: import("../index.js").SessionStoreSnapshot | undefined;
|
|
167
168
|
catalog: {
|
|
168
|
-
commands: import("../
|
|
169
|
+
commands: import("../core/commands.js").RuntimeCommandDefinition[];
|
|
169
170
|
modelIds: string[];
|
|
170
171
|
reasoning: string[];
|
|
171
172
|
envPath: string;
|
|
@@ -183,6 +184,7 @@ export declare class WebRepl {
|
|
|
183
184
|
ok: false;
|
|
184
185
|
error: string;
|
|
185
186
|
}>;
|
|
187
|
+
private startRun;
|
|
186
188
|
listSessions(): Promise<{
|
|
187
189
|
sessions: import("../index.js").SessionSummary[];
|
|
188
190
|
runningSessionIds: string[];
|
|
@@ -217,6 +219,10 @@ export declare class WebRepl {
|
|
|
217
219
|
ok: true;
|
|
218
220
|
interrupted: boolean;
|
|
219
221
|
};
|
|
222
|
+
cancelQueue(): {
|
|
223
|
+
ok: true;
|
|
224
|
+
cancelled: boolean;
|
|
225
|
+
};
|
|
220
226
|
private append;
|
|
221
227
|
private updateLine;
|
|
222
228
|
private replaceLineText;
|
package/dist/web/index.js
CHANGED
|
@@ -20,11 +20,11 @@ import { grepTool } from "../tools/builtins/grep-tool.js";
|
|
|
20
20
|
import { searchTool } from "../tools/builtins/search-tool.js";
|
|
21
21
|
import { planTool } from "../tools/builtins/plan-tool.js";
|
|
22
22
|
import { createOpenAIImageGenerationTool } from "../tools/builtins/image-generation-tool.js";
|
|
23
|
-
import {
|
|
23
|
+
import { createLoadImageTool } from "../tools/builtins/image-loader-tool.js";
|
|
24
24
|
import { createAgentTool, resumeAgentTask } from "../agents/agent-tool.js";
|
|
25
25
|
import { createTaskTools } from "../tasks/task-tools.js";
|
|
26
26
|
import { TaskStore } from "../tasks/task-store.js";
|
|
27
|
-
import { parseReplCommand, helpText, replCommandDefinitions } from "../
|
|
27
|
+
import { parseReplCommand, helpText, replCommandDefinitions } from "../core/commands.js";
|
|
28
28
|
import { writeSessionMarkdownExport } from "../session/session-export.js";
|
|
29
29
|
import { WEB_HTML } from "./html.js";
|
|
30
30
|
import { appTips, formatTipLine, initialTipIndex, tipAt } from "../tips.js";
|
|
@@ -35,8 +35,8 @@ const highlightPackageDir = path.dirname(require.resolve("@highlightjs/cdn-asset
|
|
|
35
35
|
const markedAssetPath = path.join(markedPackageDir, "lib", "marked.esm.js");
|
|
36
36
|
const highlightAssetPath = path.join(highlightPackageDir, "highlight.min.js");
|
|
37
37
|
const highlightThemeAssetPath = path.join(highlightPackageDir, "styles", "atom-one-dark.min.css");
|
|
38
|
-
|
|
39
|
-
totals =
|
|
38
|
+
class WebSessionUsageTracker {
|
|
39
|
+
totals = emptyWebUsageTotals();
|
|
40
40
|
lastUsage;
|
|
41
41
|
add(usage) {
|
|
42
42
|
if (usage === this.lastUsage)
|
|
@@ -61,14 +61,14 @@ export class SessionUsageTracker {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
reset() {
|
|
64
|
-
this.totals =
|
|
64
|
+
this.totals = emptyWebUsageTotals();
|
|
65
65
|
this.lastUsage = undefined;
|
|
66
66
|
}
|
|
67
67
|
snapshot() {
|
|
68
68
|
return { ...this.totals };
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
function
|
|
71
|
+
function emptyWebUsageTotals() {
|
|
72
72
|
return { inputTokens: 0, outputTokens: 0, totalTokens: 0, reasoningTokens: 0, cachedTokens: 0, requests: 0, computedTotalTokens: false };
|
|
73
73
|
}
|
|
74
74
|
function usageTokenValue(value) {
|
|
@@ -121,7 +121,7 @@ export async function createWebRuntime(options = {}) {
|
|
|
121
121
|
tools.register(readFileTool);
|
|
122
122
|
tools.register(grepTool);
|
|
123
123
|
tools.register(searchTool);
|
|
124
|
-
tools.register(
|
|
124
|
+
tools.register(createLoadImageTool());
|
|
125
125
|
if (modelConfig?.provider === "openai")
|
|
126
126
|
tools.register(createOpenAIImageGenerationTool());
|
|
127
127
|
tools.register(planTool);
|
|
@@ -163,7 +163,7 @@ export async function createWebRuntime(options = {}) {
|
|
|
163
163
|
communicationLogger,
|
|
164
164
|
modelGateway,
|
|
165
165
|
agentRuntime,
|
|
166
|
-
usage: new
|
|
166
|
+
usage: new WebSessionUsageTracker(),
|
|
167
167
|
taskStore,
|
|
168
168
|
tools,
|
|
169
169
|
initialMetrics,
|
|
@@ -193,12 +193,8 @@ function syncImageGenerationTool(runtime, provider) {
|
|
|
193
193
|
if (provider === "openai")
|
|
194
194
|
runtime.tools.register(createOpenAIImageGenerationTool());
|
|
195
195
|
}
|
|
196
|
-
function syncVisionTool(runtime, model) {
|
|
197
|
-
runtime.tools.unregister("vision");
|
|
198
|
-
runtime.tools.register(createVisionTool({ modelGateway: runtime.modelGateway, model }));
|
|
199
|
-
}
|
|
200
196
|
function formatCreatedEnvNotice(dotEnvPath) {
|
|
201
|
-
return `Created default config file: ${dotEnvPath}\nSet MODEL_PROVIDER and the matching provider section (for example OPENAI_API_KEY or KIMI_API_KEY), then restart neo.`;
|
|
197
|
+
return `Created default config file: ${dotEnvPath}\nSet MODEL_PROVIDER and the matching provider section (for example OPENAI_API_KEY, ANTHROPIC_API_KEY, or KIMI_API_KEY), then restart neo.`;
|
|
202
198
|
}
|
|
203
199
|
function parseResumeFlag(value) {
|
|
204
200
|
if (!value)
|
|
@@ -258,6 +254,7 @@ export class WebRepl {
|
|
|
258
254
|
status;
|
|
259
255
|
busy = false;
|
|
260
256
|
queuedInput;
|
|
257
|
+
queuedAttachments;
|
|
261
258
|
foregroundRun;
|
|
262
259
|
foregroundRunToken = 0;
|
|
263
260
|
backgroundSessionRuns = new Map();
|
|
@@ -315,8 +312,15 @@ export class WebRepl {
|
|
|
315
312
|
await this.detachRunningForeground("session browser");
|
|
316
313
|
}
|
|
317
314
|
else if (this.busy) {
|
|
318
|
-
this.
|
|
315
|
+
this.queuedInput = text;
|
|
316
|
+
this.queuedAttachments = attachments;
|
|
317
|
+
this.broadcastSync();
|
|
318
|
+
return { ok: true };
|
|
319
319
|
}
|
|
320
|
+
this.startRun(text, attachments);
|
|
321
|
+
return { ok: true };
|
|
322
|
+
}
|
|
323
|
+
startRun(text, attachments = []) {
|
|
320
324
|
const run = this.handleCommandOrPrompt(text, attachments).catch((error) => {
|
|
321
325
|
this.append({ kind: "error", text: error instanceof Error ? error.message : String(error) });
|
|
322
326
|
this.setBusy(false);
|
|
@@ -327,7 +331,6 @@ export class WebRepl {
|
|
|
327
331
|
if (this.foregroundRun === run)
|
|
328
332
|
this.foregroundRun = undefined;
|
|
329
333
|
}).catch(() => undefined);
|
|
330
|
-
return { ok: true };
|
|
331
334
|
}
|
|
332
335
|
async listSessions() {
|
|
333
336
|
const sessions = await this.runtime.engine.listSessions(Number.POSITIVE_INFINITY);
|
|
@@ -413,7 +416,7 @@ export class WebRepl {
|
|
|
413
416
|
async saveLogin(providerValue, values) {
|
|
414
417
|
const provider = parseLoginProvider(providerValue);
|
|
415
418
|
if (!provider)
|
|
416
|
-
return { ok: false, error: "provider must be openai, deepseek, or kimi" };
|
|
419
|
+
return { ok: false, error: "provider must be openai, anthropic, deepseek, or kimi" };
|
|
417
420
|
const payload = { ...createLoginFormPayload(this.runtime.envPath, provider), provider, values };
|
|
418
421
|
const validationError = validateLoginFormPayload(payload);
|
|
419
422
|
if (validationError)
|
|
@@ -429,7 +432,6 @@ export class WebRepl {
|
|
|
429
432
|
this.runtime.agentRuntime.modelGateway = this.runtime.modelGateway;
|
|
430
433
|
this.runtime.engine.setModelProvider({ modelGateway: this.runtime.modelGateway, model: config.model, fallbackModel: config.fallbackModel, reasoning: config.defaultReasoning });
|
|
431
434
|
syncImageGenerationTool(this.runtime, config.provider);
|
|
432
|
-
syncVisionTool(this.runtime, config.model);
|
|
433
435
|
this.runtime.defaultReasoning = config.defaultReasoning;
|
|
434
436
|
const metrics = await this.runtime.engine.contextMetrics();
|
|
435
437
|
this.setStatus({ ...this.status, metrics, activityTick: this.status.activityTick + 1 });
|
|
@@ -446,6 +448,14 @@ export class WebRepl {
|
|
|
446
448
|
const interrupted = this.stopForegroundRun("Interrupted from neo web");
|
|
447
449
|
return { ok: true, interrupted };
|
|
448
450
|
}
|
|
451
|
+
cancelQueue() {
|
|
452
|
+
const had = this.queuedInput !== undefined;
|
|
453
|
+
this.queuedInput = undefined;
|
|
454
|
+
this.queuedAttachments = undefined;
|
|
455
|
+
if (had)
|
|
456
|
+
this.broadcastSync();
|
|
457
|
+
return { ok: true, cancelled: had };
|
|
458
|
+
}
|
|
449
459
|
append(line) {
|
|
450
460
|
const id = ++this.lineId;
|
|
451
461
|
this.lines.push({ id, ...line });
|
|
@@ -490,6 +500,7 @@ export class WebRepl {
|
|
|
490
500
|
this.activeAbortController = undefined;
|
|
491
501
|
this.interruptArmed = false;
|
|
492
502
|
this.queuedInput = undefined;
|
|
503
|
+
this.queuedAttachments = undefined;
|
|
493
504
|
this.finalizeForegroundView();
|
|
494
505
|
this.busy = false;
|
|
495
506
|
this.status = { ...this.status, phase: "ready", detail: undefined, inputTokenUpdatedAt: undefined, outputTokenUpdatedAt: undefined, retryCooldownUntil: undefined };
|
|
@@ -534,6 +545,7 @@ export class WebRepl {
|
|
|
534
545
|
this.activeAbortController = undefined;
|
|
535
546
|
this.interruptArmed = false;
|
|
536
547
|
this.queuedInput = undefined;
|
|
548
|
+
this.queuedAttachments = undefined;
|
|
537
549
|
this.busy = false;
|
|
538
550
|
this.status = { ...this.status, phase: "ready", detail: undefined };
|
|
539
551
|
this.append(systemLine(`Detached running ${sessionId} to background for ${reason}.`));
|
|
@@ -675,7 +687,7 @@ export class WebRepl {
|
|
|
675
687
|
if (command.type === "help")
|
|
676
688
|
return void this.append(systemLine(helpText, EXPANDED_SUMMARY_MAX_LINES));
|
|
677
689
|
if (command.type === "cost")
|
|
678
|
-
return void this.append({ kind: "system", text:
|
|
690
|
+
return void this.append({ kind: "system", text: formatWebUsageTotals(this.runtime.usage.snapshot()), previewStyle: "summary" });
|
|
679
691
|
if (command.type === "reset") {
|
|
680
692
|
this.runtime.engine.reset();
|
|
681
693
|
this.runtime.usage.reset();
|
|
@@ -794,9 +806,19 @@ export class WebRepl {
|
|
|
794
806
|
this.activeAbortController = undefined;
|
|
795
807
|
this.interruptArmed = false;
|
|
796
808
|
this.finalizeForegroundView();
|
|
797
|
-
this.
|
|
798
|
-
|
|
799
|
-
this.
|
|
809
|
+
const queuedText = this.queuedInput;
|
|
810
|
+
const queuedAttach = this.queuedAttachments;
|
|
811
|
+
this.queuedInput = undefined;
|
|
812
|
+
this.queuedAttachments = undefined;
|
|
813
|
+
if (queuedText !== undefined) {
|
|
814
|
+
this.startRun(queuedText, queuedAttach ?? []);
|
|
815
|
+
this.broadcastSync();
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
this.setBusy(false);
|
|
819
|
+
this.setStatus({ ...this.status, phase: "ready", detail: undefined, inputTokenUpdatedAt: undefined, outputTokenUpdatedAt: undefined, retryCooldownUntil: undefined });
|
|
820
|
+
this.broadcastSync();
|
|
821
|
+
}
|
|
800
822
|
}
|
|
801
823
|
}
|
|
802
824
|
async runCompaction(type) {
|
|
@@ -870,6 +892,8 @@ async function route(req, res, router) {
|
|
|
870
892
|
}
|
|
871
893
|
if (req.method === "POST" && url.pathname === "/api/interrupt")
|
|
872
894
|
return sendJson(res, repl.interrupt());
|
|
895
|
+
if (req.method === "POST" && url.pathname === "/api/queue/cancel")
|
|
896
|
+
return sendJson(res, repl.cancelQueue());
|
|
873
897
|
if (req.method === "GET" && url.pathname === "/api/sessions")
|
|
874
898
|
return sendJson(res, await repl.listSessions());
|
|
875
899
|
if (req.method === "POST" && url.pathname === "/api/sessions/resume") {
|
|
@@ -1086,7 +1110,6 @@ async function handleModelCommand(command, runtime) {
|
|
|
1086
1110
|
runtime.agentRuntime.modelGateway = runtime.modelGateway;
|
|
1087
1111
|
runtime.engine.setModelProvider({ modelGateway: runtime.modelGateway, model: config.model, fallbackModel: config.fallbackModel, reasoning: config.defaultReasoning });
|
|
1088
1112
|
syncImageGenerationTool(runtime, config.provider);
|
|
1089
|
-
syncVisionTool(runtime, config.model);
|
|
1090
1113
|
runtime.defaultReasoning = config.defaultReasoning;
|
|
1091
1114
|
}
|
|
1092
1115
|
}
|
|
@@ -1137,14 +1160,14 @@ async function persistModelCommandSettings(runtime, command, reasoningUpdate) {
|
|
|
1137
1160
|
return { providerChanged: targetProvider !== currentProvider };
|
|
1138
1161
|
}
|
|
1139
1162
|
function currentModelProvider() {
|
|
1140
|
-
return parseLoginProvider(process.env.MODEL_PROVIDER) ?? "openai";
|
|
1163
|
+
return parseLoginProvider(process.env.MODEL_PROVIDER) ?? (process.env.ANTHROPIC_API_KEY ? "anthropic" : "openai");
|
|
1141
1164
|
}
|
|
1142
1165
|
function parseLoginProvider(value) {
|
|
1143
|
-
if (value === "openai" || value === "deepseek" || value === "kimi")
|
|
1166
|
+
if (value === "openai" || value === "anthropic" || value === "deepseek" || value === "kimi")
|
|
1144
1167
|
return value;
|
|
1145
1168
|
return undefined;
|
|
1146
1169
|
}
|
|
1147
|
-
const LOGIN_PROVIDERS = ["openai", "deepseek", "kimi"];
|
|
1170
|
+
const LOGIN_PROVIDERS = ["openai", "anthropic", "deepseek", "kimi"];
|
|
1148
1171
|
const SHARED_LOGIN_FIELDS = [
|
|
1149
1172
|
{ key: "reasoningEffort", label: "Reasoning effort", envKey: "MODEL_REASONING_EFFORT", scope: "shared", options: ["", "off", "none", "minimal", "low", "medium", "high", "xhigh", "max"] },
|
|
1150
1173
|
{ key: "reasoningSummary", label: "Reasoning summary", envKey: "MODEL_REASONING_SUMMARY", scope: "shared", options: ["", "auto", "concise", "detailed"] },
|
|
@@ -1162,6 +1185,14 @@ const LOGIN_FIELD_DEFINITIONS = {
|
|
|
1162
1185
|
{ key: "endpoint", label: "Endpoint", envKey: "OPENAI_ENDPOINT", scope: "provider", placeholder: "auto", options: ["auto", "responses", "chat"] },
|
|
1163
1186
|
...SHARED_LOGIN_FIELDS,
|
|
1164
1187
|
],
|
|
1188
|
+
anthropic: [
|
|
1189
|
+
{ key: "apiKey", label: "API key", envKey: "ANTHROPIC_API_KEY", scope: "provider", required: true, secret: true, placeholder: "sk-ant-..." },
|
|
1190
|
+
{ key: "baseUrl", label: "Base URL", envKey: "ANTHROPIC_BASE_URL", scope: "provider", placeholder: "https://api.anthropic.com" },
|
|
1191
|
+
{ key: "model", label: "Model", envKey: "ANTHROPIC_MODEL", scope: "provider", required: true, placeholder: "claude-sonnet-4-6" },
|
|
1192
|
+
{ key: "fallbackModel", label: "Fallback model", envKey: "ANTHROPIC_FALLBACK_MODEL", scope: "provider" },
|
|
1193
|
+
{ key: "version", label: "Anthropic version", envKey: "ANTHROPIC_VERSION", scope: "provider", placeholder: "2023-06-01" },
|
|
1194
|
+
...SHARED_LOGIN_FIELDS,
|
|
1195
|
+
],
|
|
1165
1196
|
deepseek: [
|
|
1166
1197
|
{ key: "apiKey", label: "API key", envKey: "DEEPSEEK_API_KEY", scope: "provider", required: true, secret: true, placeholder: "sk-..." },
|
|
1167
1198
|
{ key: "baseUrl", label: "Base URL", envKey: "DEEPSEEK_BASE_URL", scope: "provider", placeholder: "https://api.deepseek.com" },
|
|
@@ -1180,6 +1211,7 @@ const LOGIN_FIELD_DEFINITIONS = {
|
|
|
1180
1211
|
const DEPRECATED_MODEL_ENV_KEYS = [
|
|
1181
1212
|
"MODEL_API_KEY", "MODEL_BASE_URL", "MODEL_ID", "MODEL_FALLBACK_ID", "MODEL_ENDPOINT", "OPENAI_PROVIDER",
|
|
1182
1213
|
"OPENAI_REASONING_EFFORT", "OPENAI_REASONING_SUMMARY", "OPENAI_MAX_OUTPUT_TOKENS", "OPENAI_TIMEOUT_MS", "OPENAI_STREAM_IDLE_TIMEOUT_MS", "OPENAI_MAX_RETRIES",
|
|
1214
|
+
"ANTHROPIC_REASONING_EFFORT", "ANTHROPIC_REASONING_SUMMARY", "ANTHROPIC_MAX_OUTPUT_TOKENS", "ANTHROPIC_TIMEOUT_MS", "ANTHROPIC_STREAM_IDLE_TIMEOUT_MS", "ANTHROPIC_MAX_RETRIES",
|
|
1183
1215
|
"DEEPSEEK_REASONING_EFFORT", "DEEPSEEK_REASONING_SUMMARY", "DEEPSEEK_MAX_OUTPUT_TOKENS", "DEEPSEEK_TIMEOUT_MS", "DEEPSEEK_STREAM_IDLE_TIMEOUT_MS", "DEEPSEEK_MAX_RETRIES",
|
|
1184
1216
|
"KIMI_REASONING_EFFORT", "KIMI_REASONING_SUMMARY", "KIMI_MAX_OUTPUT_TOKENS", "KIMI_TIMEOUT_MS", "KIMI_STREAM_IDLE_TIMEOUT_MS", "KIMI_MAX_RETRIES",
|
|
1185
1217
|
"MOONSHOT_REASONING_EFFORT", "MOONSHOT_REASONING_SUMMARY", "MOONSHOT_MAX_OUTPUT_TOKENS", "MOONSHOT_TIMEOUT_MS", "MOONSHOT_STREAM_IDLE_TIMEOUT_MS", "MOONSHOT_MAX_RETRIES",
|
|
@@ -1218,9 +1250,13 @@ function guessLoginProvider(env) {
|
|
|
1218
1250
|
return "kimi";
|
|
1219
1251
|
if (env.DEEPSEEK_API_KEY ?? process.env.DEEPSEEK_API_KEY)
|
|
1220
1252
|
return "deepseek";
|
|
1253
|
+
if (env.ANTHROPIC_API_KEY ?? process.env.ANTHROPIC_API_KEY)
|
|
1254
|
+
return "anthropic";
|
|
1221
1255
|
return currentModelProvider();
|
|
1222
1256
|
}
|
|
1223
1257
|
function defaultBaseUrlForLoginProvider(provider) {
|
|
1258
|
+
if (provider === "anthropic")
|
|
1259
|
+
return "https://api.anthropic.com";
|
|
1224
1260
|
if (provider === "deepseek")
|
|
1225
1261
|
return "https://api.deepseek.com";
|
|
1226
1262
|
if (provider === "kimi")
|
|
@@ -1228,6 +1264,8 @@ function defaultBaseUrlForLoginProvider(provider) {
|
|
|
1228
1264
|
return "https://api.openai.com";
|
|
1229
1265
|
}
|
|
1230
1266
|
function defaultModelForLoginProvider(provider) {
|
|
1267
|
+
if (provider === "anthropic")
|
|
1268
|
+
return "claude-sonnet-4-6";
|
|
1231
1269
|
if (provider === "deepseek")
|
|
1232
1270
|
return "deepseek-chat";
|
|
1233
1271
|
if (provider === "kimi")
|
|
@@ -1288,6 +1326,8 @@ function stripEnvQuotes(value) {
|
|
|
1288
1326
|
return value;
|
|
1289
1327
|
}
|
|
1290
1328
|
function modelEnvKeyForProvider(provider) {
|
|
1329
|
+
if (provider === "anthropic")
|
|
1330
|
+
return "ANTHROPIC_MODEL";
|
|
1291
1331
|
if (provider === "deepseek")
|
|
1292
1332
|
return "DEEPSEEK_MODEL";
|
|
1293
1333
|
if (provider === "kimi")
|
|
@@ -1844,7 +1884,7 @@ function truncate(value, maxLength) {
|
|
|
1844
1884
|
function estimateTokens(text) {
|
|
1845
1885
|
return text ? Math.max(1, Math.ceil(text.length / 4)) : 0;
|
|
1846
1886
|
}
|
|
1847
|
-
function
|
|
1887
|
+
function formatWebUsageTotals(totals) {
|
|
1848
1888
|
const totalLabel = totals.computedTotalTokens ? "Total tokens (computed)" : "Total tokens";
|
|
1849
1889
|
return [
|
|
1850
1890
|
"Session usage:",
|
|
@@ -1859,12 +1899,12 @@ function formatUsageTotals(totals) {
|
|
|
1859
1899
|
function formatManualCompaction(result) {
|
|
1860
1900
|
if (!result.changed)
|
|
1861
1901
|
return "No context compaction was needed.";
|
|
1862
|
-
return `context compacted: ${result.messages.length} message(s) retained, ${formatNumber(result.tokensFreed ?? 0)} chars removed`;
|
|
1902
|
+
return `context compacted: ${result.messages.length} message(s) retained, ${formatNumber(result.charsFreed ?? result.tokensFreed ?? 0)} chars removed`;
|
|
1863
1903
|
}
|
|
1864
1904
|
function formatPureCompaction(result) {
|
|
1865
1905
|
if (!result.changed)
|
|
1866
1906
|
return "No context available to purify.";
|
|
1867
|
-
return `pure context compacted: ${result.messages.length} sanitized message(s) retained, ${formatNumber(result.tokensFreed ?? 0)} chars removed; raw command/log/code details omitted`;
|
|
1907
|
+
return `pure context compacted: ${result.messages.length} sanitized message(s) retained, ${formatNumber(result.charsFreed ?? result.tokensFreed ?? 0)} chars removed; raw command/log/code details omitted`;
|
|
1868
1908
|
}
|
|
1869
1909
|
function formatNumber(value) {
|
|
1870
1910
|
return value === undefined ? "?" : new Intl.NumberFormat("en-US").format(Math.round(value));
|