open-agents-ai 0.59.0 → 0.61.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/dist/index.js +1060 -271
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19081,7 +19081,7 @@ var require_extension = __commonJS({
|
|
|
19081
19081
|
var require_websocket = __commonJS({
|
|
19082
19082
|
"node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js"(exports, module) {
|
|
19083
19083
|
"use strict";
|
|
19084
|
-
var
|
|
19084
|
+
var EventEmitter4 = __require("events");
|
|
19085
19085
|
var https = __require("https");
|
|
19086
19086
|
var http = __require("http");
|
|
19087
19087
|
var net = __require("net");
|
|
@@ -19113,7 +19113,7 @@ var require_websocket = __commonJS({
|
|
|
19113
19113
|
var protocolVersions = [8, 13];
|
|
19114
19114
|
var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
|
|
19115
19115
|
var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
19116
|
-
var WebSocket2 = class _WebSocket extends
|
|
19116
|
+
var WebSocket2 = class _WebSocket extends EventEmitter4 {
|
|
19117
19117
|
/**
|
|
19118
19118
|
* Create a new `WebSocket`.
|
|
19119
19119
|
*
|
|
@@ -20110,7 +20110,7 @@ var require_subprotocol = __commonJS({
|
|
|
20110
20110
|
var require_websocket_server = __commonJS({
|
|
20111
20111
|
"node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js"(exports, module) {
|
|
20112
20112
|
"use strict";
|
|
20113
|
-
var
|
|
20113
|
+
var EventEmitter4 = __require("events");
|
|
20114
20114
|
var http = __require("http");
|
|
20115
20115
|
var { Duplex } = __require("stream");
|
|
20116
20116
|
var { createHash: createHash2 } = __require("crypto");
|
|
@@ -20123,7 +20123,7 @@ var require_websocket_server = __commonJS({
|
|
|
20123
20123
|
var RUNNING = 0;
|
|
20124
20124
|
var CLOSING = 1;
|
|
20125
20125
|
var CLOSED = 2;
|
|
20126
|
-
var WebSocketServer2 = class extends
|
|
20126
|
+
var WebSocketServer2 = class extends EventEmitter4 {
|
|
20127
20127
|
/**
|
|
20128
20128
|
* Create a `WebSocketServer` instance.
|
|
20129
20129
|
*
|
|
@@ -21604,7 +21604,10 @@ function connect() {
|
|
|
21604
21604
|
ws = null;
|
|
21605
21605
|
}
|
|
21606
21606
|
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
21607
|
-
|
|
21607
|
+
const urlParams = new URLSearchParams(location.search);
|
|
21608
|
+
const sessionKey = urlParams.get('key') || '';
|
|
21609
|
+
const keyParam = sessionKey ? '?key=' + encodeURIComponent(sessionKey) : '';
|
|
21610
|
+
ws = new WebSocket(proto + '//' + location.host + '/ws' + keyParam);
|
|
21608
21611
|
ws.binaryType = 'arraybuffer';
|
|
21609
21612
|
|
|
21610
21613
|
ws.onopen = () => {
|
|
@@ -21903,6 +21906,47 @@ var init_voice_session = __esm({
|
|
|
21903
21906
|
}
|
|
21904
21907
|
}
|
|
21905
21908
|
}
|
|
21909
|
+
/**
|
|
21910
|
+
* Send TTS audio to a specific client by clientId.
|
|
21911
|
+
*/
|
|
21912
|
+
sendAudioToClient(clientId, pcmInt16) {
|
|
21913
|
+
const ws = this.wsClients.get(clientId);
|
|
21914
|
+
if (ws) {
|
|
21915
|
+
try {
|
|
21916
|
+
if (ws.readyState === import_websocket.default.OPEN)
|
|
21917
|
+
ws.send(pcmInt16);
|
|
21918
|
+
} catch {
|
|
21919
|
+
}
|
|
21920
|
+
}
|
|
21921
|
+
}
|
|
21922
|
+
/**
|
|
21923
|
+
* Send speaking state change to a specific client.
|
|
21924
|
+
*/
|
|
21925
|
+
sendSpeakingStateToClient(clientId, speaking) {
|
|
21926
|
+
const ws = this.wsClients.get(clientId);
|
|
21927
|
+
if (ws) {
|
|
21928
|
+
const msg = JSON.stringify({ type: speaking ? "speaking_start" : "speaking_end" });
|
|
21929
|
+
try {
|
|
21930
|
+
if (ws.readyState === import_websocket.default.OPEN)
|
|
21931
|
+
ws.send(msg);
|
|
21932
|
+
} catch {
|
|
21933
|
+
}
|
|
21934
|
+
}
|
|
21935
|
+
}
|
|
21936
|
+
/**
|
|
21937
|
+
* Send a transcript message to a specific client.
|
|
21938
|
+
*/
|
|
21939
|
+
sendTranscriptToClient(clientId, speaker, text) {
|
|
21940
|
+
const ws = this.wsClients.get(clientId);
|
|
21941
|
+
if (ws) {
|
|
21942
|
+
const msg = JSON.stringify({ type: "transcript", speaker, text });
|
|
21943
|
+
try {
|
|
21944
|
+
if (ws.readyState === import_websocket.default.OPEN)
|
|
21945
|
+
ws.send(msg);
|
|
21946
|
+
} catch {
|
|
21947
|
+
}
|
|
21948
|
+
}
|
|
21949
|
+
}
|
|
21906
21950
|
/**
|
|
21907
21951
|
* Signal TTS speaking state to clients.
|
|
21908
21952
|
*/
|
|
@@ -21951,9 +21995,11 @@ var init_voice_session = __esm({
|
|
|
21951
21995
|
// ── WebSocket connection handler (using ws package) ──────────────────
|
|
21952
21996
|
handleWSConnection(ws, req) {
|
|
21953
21997
|
const clientId = `ws-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
21998
|
+
const url = new URL(req.url ?? "/", `http://localhost`);
|
|
21999
|
+
const sessionKey = url.searchParams.get("key") ?? null;
|
|
21954
22000
|
this.wsClients.set(clientId, ws);
|
|
21955
22001
|
this.state.connectedUsers.set(clientId, { username: "web-user", connectedAt: Date.now() });
|
|
21956
|
-
this.emit("userConnected", clientId, "web-user");
|
|
22002
|
+
this.emit("userConnected", clientId, "web-user", sessionKey);
|
|
21957
22003
|
this.resetIdleTimer();
|
|
21958
22004
|
const keepaliveInterval = setInterval(() => {
|
|
21959
22005
|
if (ws.readyState !== import_websocket.default.OPEN) {
|
|
@@ -22079,6 +22125,279 @@ var init_voice_session = __esm({
|
|
|
22079
22125
|
}
|
|
22080
22126
|
});
|
|
22081
22127
|
|
|
22128
|
+
// packages/cli/dist/tui/call-agent.js
|
|
22129
|
+
import { EventEmitter as EventEmitter3 } from "node:events";
|
|
22130
|
+
import crypto2 from "node:crypto";
|
|
22131
|
+
function adaptTool(tool) {
|
|
22132
|
+
return {
|
|
22133
|
+
name: tool.name,
|
|
22134
|
+
description: tool.description,
|
|
22135
|
+
parameters: tool.parameters,
|
|
22136
|
+
async execute(args) {
|
|
22137
|
+
const result = await tool.execute(args);
|
|
22138
|
+
return { success: result.success, output: result.output, error: result.error };
|
|
22139
|
+
}
|
|
22140
|
+
};
|
|
22141
|
+
}
|
|
22142
|
+
function getActivityFeed() {
|
|
22143
|
+
if (!_globalFeed)
|
|
22144
|
+
_globalFeed = new ActivityFeed();
|
|
22145
|
+
return _globalFeed;
|
|
22146
|
+
}
|
|
22147
|
+
function generateSessionKey() {
|
|
22148
|
+
return crypto2.randomBytes(16).toString("hex");
|
|
22149
|
+
}
|
|
22150
|
+
var ActivityFeed, _globalFeed, CallSubAgent;
|
|
22151
|
+
var init_call_agent = __esm({
|
|
22152
|
+
"packages/cli/dist/tui/call-agent.js"() {
|
|
22153
|
+
"use strict";
|
|
22154
|
+
init_dist5();
|
|
22155
|
+
init_dist2();
|
|
22156
|
+
ActivityFeed = class {
|
|
22157
|
+
entries = [];
|
|
22158
|
+
maxEntries = 100;
|
|
22159
|
+
push(entry) {
|
|
22160
|
+
this.entries.push(entry);
|
|
22161
|
+
if (this.entries.length > this.maxEntries) {
|
|
22162
|
+
this.entries = this.entries.slice(-this.maxEntries);
|
|
22163
|
+
}
|
|
22164
|
+
}
|
|
22165
|
+
/** Get recent activity as a text summary for sub-agent context */
|
|
22166
|
+
getSummary(maxItems = 20, verbose = false) {
|
|
22167
|
+
const recent = this.entries.slice(-maxItems);
|
|
22168
|
+
if (recent.length === 0)
|
|
22169
|
+
return "No recent activity.";
|
|
22170
|
+
return recent.map((e) => {
|
|
22171
|
+
const src = e.source === "main" ? "Agent" : "Call";
|
|
22172
|
+
const tool = e.toolName ? ` [${e.toolName}]` : "";
|
|
22173
|
+
const status = e.success !== void 0 ? e.success ? " ok" : " fail" : "";
|
|
22174
|
+
if (verbose) {
|
|
22175
|
+
return `[${new Date(e.ts).toLocaleTimeString()}] ${src}${tool}${status}: ${e.summary}`;
|
|
22176
|
+
}
|
|
22177
|
+
return `${src}${tool}${status}: ${e.summary}`;
|
|
22178
|
+
}).join("\n");
|
|
22179
|
+
}
|
|
22180
|
+
/** Get entries since a timestamp */
|
|
22181
|
+
since(ts) {
|
|
22182
|
+
return this.entries.filter((e) => e.ts > ts);
|
|
22183
|
+
}
|
|
22184
|
+
clear() {
|
|
22185
|
+
this.entries.length = 0;
|
|
22186
|
+
}
|
|
22187
|
+
};
|
|
22188
|
+
_globalFeed = null;
|
|
22189
|
+
CallSubAgent = class extends EventEmitter3 {
|
|
22190
|
+
tier;
|
|
22191
|
+
clientId;
|
|
22192
|
+
runner = null;
|
|
22193
|
+
config;
|
|
22194
|
+
repoRoot;
|
|
22195
|
+
opts;
|
|
22196
|
+
processing = false;
|
|
22197
|
+
pendingTranscripts = [];
|
|
22198
|
+
conversationHistory = [];
|
|
22199
|
+
disposed = false;
|
|
22200
|
+
constructor(clientId, opts) {
|
|
22201
|
+
super();
|
|
22202
|
+
this.clientId = clientId;
|
|
22203
|
+
this.tier = opts.tier;
|
|
22204
|
+
this.config = opts.config;
|
|
22205
|
+
this.repoRoot = opts.repoRoot;
|
|
22206
|
+
this.opts = opts;
|
|
22207
|
+
}
|
|
22208
|
+
/** Initialize the runner with appropriate tools for the access tier */
|
|
22209
|
+
async init() {
|
|
22210
|
+
const backend = new OllamaAgenticBackend(this.config.backendUrl, this.config.model, this.config.apiKey);
|
|
22211
|
+
const feed = getActivityFeed();
|
|
22212
|
+
const systemPrompt = this.buildSystemPrompt();
|
|
22213
|
+
const runnerOpts = {
|
|
22214
|
+
maxTurns: this.tier === "admin" ? 15 : 5,
|
|
22215
|
+
maxTokens: 4096,
|
|
22216
|
+
temperature: 0.3,
|
|
22217
|
+
requestTimeoutMs: 3e4,
|
|
22218
|
+
taskTimeoutMs: 12e4,
|
|
22219
|
+
modelTier: this.opts.modelTier ?? "large",
|
|
22220
|
+
contextWindowSize: this.opts.contextWindowSize,
|
|
22221
|
+
personality: this.opts.personality,
|
|
22222
|
+
streamEnabled: false,
|
|
22223
|
+
bruteForce: false,
|
|
22224
|
+
dynamicContext: systemPrompt
|
|
22225
|
+
};
|
|
22226
|
+
this.runner = new AgenticRunner(backend, runnerOpts);
|
|
22227
|
+
this.runner.setWorkingDirectory(this.repoRoot);
|
|
22228
|
+
const tools = this.buildTools();
|
|
22229
|
+
this.runner.registerTools(tools);
|
|
22230
|
+
const clientId = this.clientId;
|
|
22231
|
+
const self = this;
|
|
22232
|
+
this.runner.registerTool({
|
|
22233
|
+
name: "task_complete",
|
|
22234
|
+
description: "Call this when you have fully answered the user's question or completed their request. The summary should be your spoken response to the user.",
|
|
22235
|
+
parameters: {
|
|
22236
|
+
type: "object",
|
|
22237
|
+
properties: {
|
|
22238
|
+
summary: {
|
|
22239
|
+
type: "string",
|
|
22240
|
+
description: "Your spoken response to the user. Keep it concise and conversational \u2014 this will be spoken aloud via TTS."
|
|
22241
|
+
}
|
|
22242
|
+
},
|
|
22243
|
+
required: ["summary"]
|
|
22244
|
+
},
|
|
22245
|
+
execute: async (args) => {
|
|
22246
|
+
const summary = String(args["summary"] ?? "");
|
|
22247
|
+
self.emit("response", summary);
|
|
22248
|
+
feed.push({
|
|
22249
|
+
ts: Date.now(),
|
|
22250
|
+
source: "call",
|
|
22251
|
+
sourceId: clientId,
|
|
22252
|
+
summary: `Responded: ${summary.slice(0, 100)}`
|
|
22253
|
+
});
|
|
22254
|
+
return { success: true, output: summary };
|
|
22255
|
+
}
|
|
22256
|
+
});
|
|
22257
|
+
this.runner.onEvent((event) => {
|
|
22258
|
+
if (event.type === "tool_call") {
|
|
22259
|
+
const toolName = event.toolName ?? "unknown";
|
|
22260
|
+
const args = event.toolArgs ?? {};
|
|
22261
|
+
this.emit("toolCall", toolName, args);
|
|
22262
|
+
feed.push({
|
|
22263
|
+
ts: Date.now(),
|
|
22264
|
+
source: "call",
|
|
22265
|
+
sourceId: this.clientId,
|
|
22266
|
+
summary: `${toolName}(${Object.keys(args).join(", ")})`,
|
|
22267
|
+
toolName
|
|
22268
|
+
});
|
|
22269
|
+
}
|
|
22270
|
+
if (event.type === "tool_result") {
|
|
22271
|
+
const toolName = event.toolName ?? "unknown";
|
|
22272
|
+
const success = event.success ?? false;
|
|
22273
|
+
const content = String(event.content ?? "").slice(0, 100);
|
|
22274
|
+
this.emit("toolResult", toolName, success, content);
|
|
22275
|
+
feed.push({
|
|
22276
|
+
ts: Date.now(),
|
|
22277
|
+
source: "call",
|
|
22278
|
+
sourceId: this.clientId,
|
|
22279
|
+
summary: content,
|
|
22280
|
+
toolName,
|
|
22281
|
+
success
|
|
22282
|
+
});
|
|
22283
|
+
}
|
|
22284
|
+
if (event.type === "model_response" && event.content) {
|
|
22285
|
+
this.emit("response", event.content);
|
|
22286
|
+
}
|
|
22287
|
+
});
|
|
22288
|
+
}
|
|
22289
|
+
/** Process a voice transcript — queues if already processing */
|
|
22290
|
+
handleTranscript(text) {
|
|
22291
|
+
if (this.disposed)
|
|
22292
|
+
return;
|
|
22293
|
+
this.conversationHistory.push({ role: "user", text });
|
|
22294
|
+
if (this.processing) {
|
|
22295
|
+
this.pendingTranscripts.push(text);
|
|
22296
|
+
return;
|
|
22297
|
+
}
|
|
22298
|
+
this.processTranscript(text).catch((err) => {
|
|
22299
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
22300
|
+
});
|
|
22301
|
+
}
|
|
22302
|
+
/** Dispose and clean up */
|
|
22303
|
+
dispose() {
|
|
22304
|
+
this.disposed = true;
|
|
22305
|
+
this.pendingTranscripts.length = 0;
|
|
22306
|
+
this.runner = null;
|
|
22307
|
+
}
|
|
22308
|
+
// ── Private ──────────────────────────────────────────────────────────
|
|
22309
|
+
async processTranscript(text) {
|
|
22310
|
+
if (!this.runner || this.disposed)
|
|
22311
|
+
return;
|
|
22312
|
+
this.processing = true;
|
|
22313
|
+
try {
|
|
22314
|
+
const historyContext = this.conversationHistory.slice(-10).map((h) => `${h.role === "user" ? "User" : "You"}: ${h.text}`).join("\n");
|
|
22315
|
+
const feed = getActivityFeed();
|
|
22316
|
+
const activitySummary = feed.getSummary(this.tier === "admin" ? 20 : 10, this.tier === "admin");
|
|
22317
|
+
const taskPrompt = [
|
|
22318
|
+
`The user said (via voice): "${text}"`,
|
|
22319
|
+
"",
|
|
22320
|
+
"Recent conversation:",
|
|
22321
|
+
historyContext,
|
|
22322
|
+
"",
|
|
22323
|
+
"Recent agent activity:",
|
|
22324
|
+
activitySummary,
|
|
22325
|
+
"",
|
|
22326
|
+
"Respond conversationally and concisely. Your response will be spoken aloud via TTS.",
|
|
22327
|
+
"Call task_complete with your spoken response as the summary."
|
|
22328
|
+
].join("\n");
|
|
22329
|
+
const result = await this.runner.run(taskPrompt, `Working directory: ${this.repoRoot}`);
|
|
22330
|
+
if (result.summary) {
|
|
22331
|
+
this.conversationHistory.push({ role: "assistant", text: result.summary });
|
|
22332
|
+
}
|
|
22333
|
+
} catch (err) {
|
|
22334
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
22335
|
+
} finally {
|
|
22336
|
+
this.processing = false;
|
|
22337
|
+
this.emit("done");
|
|
22338
|
+
if (this.pendingTranscripts.length > 0) {
|
|
22339
|
+
const next = this.pendingTranscripts.shift();
|
|
22340
|
+
this.processTranscript(next).catch((err) => {
|
|
22341
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
22342
|
+
});
|
|
22343
|
+
}
|
|
22344
|
+
}
|
|
22345
|
+
}
|
|
22346
|
+
buildSystemPrompt() {
|
|
22347
|
+
const base = [
|
|
22348
|
+
"You are a voice assistant for an AI coding agent. Users are speaking to you through a live audio call.",
|
|
22349
|
+
"Keep responses SHORT and conversational \u2014 they will be spoken aloud via text-to-speech.",
|
|
22350
|
+
"Avoid code blocks, markdown formatting, or long technical explanations in your spoken responses.",
|
|
22351
|
+
"If the user asks about what the agent is doing, summarize the recent activity concisely."
|
|
22352
|
+
];
|
|
22353
|
+
if (this.opts.emotionContext) {
|
|
22354
|
+
base.push("", "Current emotional context:", this.opts.emotionContext);
|
|
22355
|
+
}
|
|
22356
|
+
if (this.tier === "admin") {
|
|
22357
|
+
base.push("", "This is an ADMIN call \u2014 you have full access to all tools and can execute commands, read/write files, search code, etc.", "You can take actions on behalf of the user just like the main agent.");
|
|
22358
|
+
} else {
|
|
22359
|
+
base.push("", "This is a PUBLIC call \u2014 you have read-only access. You can read files and search code but cannot modify anything.", "You can answer questions about the project and explain what the agent is working on.", "Be helpful and friendly but do not execute any write operations.");
|
|
22360
|
+
}
|
|
22361
|
+
return base.join("\n");
|
|
22362
|
+
}
|
|
22363
|
+
buildTools() {
|
|
22364
|
+
if (this.tier === "admin") {
|
|
22365
|
+
return this.buildAdminTools();
|
|
22366
|
+
}
|
|
22367
|
+
return this.buildPublicTools();
|
|
22368
|
+
}
|
|
22369
|
+
buildAdminTools() {
|
|
22370
|
+
const tools = [
|
|
22371
|
+
new FileReadTool(this.repoRoot),
|
|
22372
|
+
new FileWriteTool(this.repoRoot),
|
|
22373
|
+
new FileEditTool(this.repoRoot),
|
|
22374
|
+
new ShellTool(this.repoRoot),
|
|
22375
|
+
new GrepSearchTool(this.repoRoot),
|
|
22376
|
+
new GlobFindTool(this.repoRoot),
|
|
22377
|
+
new ListDirectoryTool(this.repoRoot),
|
|
22378
|
+
new WebSearchTool(),
|
|
22379
|
+
new WebFetchTool(),
|
|
22380
|
+
new MemoryReadTool(this.repoRoot),
|
|
22381
|
+
new MemoryWriteTool(this.repoRoot),
|
|
22382
|
+
new MemorySearchTool(this.repoRoot)
|
|
22383
|
+
];
|
|
22384
|
+
return tools.map(adaptTool);
|
|
22385
|
+
}
|
|
22386
|
+
buildPublicTools() {
|
|
22387
|
+
const tools = [
|
|
22388
|
+
new FileReadTool(this.repoRoot),
|
|
22389
|
+
new GrepSearchTool(this.repoRoot),
|
|
22390
|
+
new GlobFindTool(this.repoRoot),
|
|
22391
|
+
new ListDirectoryTool(this.repoRoot),
|
|
22392
|
+
new MemoryReadTool(this.repoRoot),
|
|
22393
|
+
new MemorySearchTool(this.repoRoot)
|
|
22394
|
+
];
|
|
22395
|
+
return tools.map(adaptTool);
|
|
22396
|
+
}
|
|
22397
|
+
};
|
|
22398
|
+
}
|
|
22399
|
+
});
|
|
22400
|
+
|
|
22082
22401
|
// packages/cli/dist/tui/model-picker.js
|
|
22083
22402
|
async function fetchOllamaModels(baseUrl) {
|
|
22084
22403
|
const url = `${normalizeBaseUrl(baseUrl)}/api/tags`;
|
|
@@ -26671,265 +26990,286 @@ function modelOnnxPath(id) {
|
|
|
26671
26990
|
function modelConfigPath(id) {
|
|
26672
26991
|
return join34(modelDir(id), "config.json");
|
|
26673
26992
|
}
|
|
26674
|
-
function
|
|
26675
|
-
|
|
26676
|
-
|
|
26677
|
-
|
|
26678
|
-
|
|
26679
|
-
|
|
26680
|
-
|
|
26681
|
-
|
|
26993
|
+
function resetNarrationContext() {
|
|
26994
|
+
narration.toolCount = 0;
|
|
26995
|
+
narration.toolCounts = {};
|
|
26996
|
+
narration.consecutiveErrors = 0;
|
|
26997
|
+
narration.totalErrors = 0;
|
|
26998
|
+
narration.lastTool = "";
|
|
26999
|
+
narration.lastFile = "";
|
|
27000
|
+
narration.filesSeen.clear();
|
|
27001
|
+
narration.lastVariantIdx = {};
|
|
27002
|
+
}
|
|
27003
|
+
function pick(key, variants) {
|
|
27004
|
+
if (variants.length === 1)
|
|
27005
|
+
return variants[0];
|
|
27006
|
+
const last = narration.lastVariantIdx[key] ?? -1;
|
|
27007
|
+
let idx;
|
|
27008
|
+
do {
|
|
27009
|
+
idx = Math.floor(Math.random() * variants.length);
|
|
27010
|
+
} while (idx === last && variants.length > 1);
|
|
27011
|
+
narration.lastVariantIdx[key] = idx;
|
|
27012
|
+
return variants[idx];
|
|
27013
|
+
}
|
|
27014
|
+
function getShellCategory(cmd) {
|
|
27015
|
+
if (/npm\s+test|vitest|jest|mocha/.test(cmd))
|
|
27016
|
+
return "test";
|
|
27017
|
+
if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
|
|
27018
|
+
return "build";
|
|
27019
|
+
if (/npm\s+install|pnpm\s+install/.test(cmd))
|
|
27020
|
+
return "install";
|
|
27021
|
+
if (/git\s+/.test(cmd))
|
|
27022
|
+
return "git";
|
|
27023
|
+
if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
|
|
27024
|
+
return "lint";
|
|
27025
|
+
if (/node\s+/.test(cmd))
|
|
27026
|
+
return "node";
|
|
27027
|
+
if (/python|pip/.test(cmd))
|
|
27028
|
+
return "python";
|
|
27029
|
+
if (/curl|wget|fetch/.test(cmd))
|
|
27030
|
+
return "network";
|
|
27031
|
+
if (/docker|podman/.test(cmd))
|
|
27032
|
+
return "container";
|
|
27033
|
+
return "generic";
|
|
27034
|
+
}
|
|
27035
|
+
function contextPrefix(toolName, file) {
|
|
27036
|
+
const count = narration.toolCounts[toolName] ?? 0;
|
|
27037
|
+
const isSameFile = file && file === narration.lastFile;
|
|
27038
|
+
const isRevisit = file && narration.filesSeen.has(file);
|
|
27039
|
+
if (narration.toolCount === 0)
|
|
27040
|
+
return "";
|
|
27041
|
+
if (narration.consecutiveErrors === 1) {
|
|
27042
|
+
const afterError = ["Okay, ", "Right, ", "Alright, "];
|
|
27043
|
+
return pick("ctx_aftererr", afterError);
|
|
27044
|
+
}
|
|
27045
|
+
if (narration.consecutiveErrors === 2) {
|
|
27046
|
+
const afterMultiErr = ["Let me try something different. ", "New approach. ", "Switching tactics. "];
|
|
27047
|
+
return pick("ctx_multierr", afterMultiErr);
|
|
27048
|
+
}
|
|
27049
|
+
if (narration.consecutiveErrors >= 3) {
|
|
27050
|
+
const persistent = ["Third time's the charm. ", "One more try. ", "Okay, different angle entirely. "];
|
|
27051
|
+
return pick("ctx_persistent", persistent);
|
|
27052
|
+
}
|
|
27053
|
+
if (isSameFile && count > 0) {
|
|
27054
|
+
const sameFile = ["Back to ", "Still working on ", ""];
|
|
27055
|
+
const chosen = pick("ctx_samefile", sameFile);
|
|
27056
|
+
if (chosen)
|
|
27057
|
+
return chosen;
|
|
27058
|
+
}
|
|
27059
|
+
if (isRevisit && !isSameFile) {
|
|
27060
|
+
const revisit = ["Coming back to ", "Revisiting ", ""];
|
|
27061
|
+
const chosen = pick("ctx_revisit", revisit);
|
|
27062
|
+
if (chosen)
|
|
27063
|
+
return chosen;
|
|
27064
|
+
}
|
|
27065
|
+
if (narration.toolCount > 0 && narration.toolCount % 8 === 0) {
|
|
27066
|
+
const beats = ["Making good progress. ", "Moving along. ", ""];
|
|
27067
|
+
return pick("ctx_beat", beats);
|
|
26682
27068
|
}
|
|
26683
|
-
return
|
|
27069
|
+
return "";
|
|
26684
27070
|
}
|
|
26685
|
-
function
|
|
26686
|
-
|
|
26687
|
-
|
|
26688
|
-
|
|
26689
|
-
|
|
26690
|
-
|
|
26691
|
-
case "file_edit":
|
|
26692
|
-
return `Editing ${file}`;
|
|
26693
|
-
case "file_patch":
|
|
26694
|
-
return `Patching ${file}`;
|
|
26695
|
-
case "shell":
|
|
26696
|
-
return describeShellTerse(String(args["command"] ?? ""));
|
|
26697
|
-
case "grep_search":
|
|
26698
|
-
return `Searching for ${args["pattern"] ?? "pattern"}`;
|
|
26699
|
-
case "find_files":
|
|
26700
|
-
return `Finding files matching ${args["pattern"] ?? "pattern"}`;
|
|
26701
|
-
case "list_directory":
|
|
26702
|
-
return `Listing directory ${file || "contents"}`;
|
|
26703
|
-
case "web_search":
|
|
26704
|
-
return `Searching the web`;
|
|
26705
|
-
case "web_fetch":
|
|
26706
|
-
return `Fetching web page`;
|
|
26707
|
-
case "memory_read":
|
|
26708
|
-
return `Reading from memory`;
|
|
26709
|
-
case "memory_write":
|
|
26710
|
-
return `Saving to memory`;
|
|
26711
|
-
case "task_complete":
|
|
26712
|
-
return String(args["summary"] ?? "Task complete");
|
|
26713
|
-
case "batch_edit":
|
|
26714
|
-
return `Editing multiple files`;
|
|
26715
|
-
case "codebase_map":
|
|
26716
|
-
return `Mapping project structure`;
|
|
26717
|
-
case "diagnostic":
|
|
26718
|
-
return `Running diagnostics`;
|
|
26719
|
-
case "git_info":
|
|
26720
|
-
return `Checking git status`;
|
|
26721
|
-
case "aiwg_setup":
|
|
26722
|
-
return `Setting up development framework`;
|
|
26723
|
-
case "aiwg_health":
|
|
26724
|
-
return `Analyzing project health`;
|
|
26725
|
-
case "aiwg_workflow":
|
|
26726
|
-
return `Running workflow command`;
|
|
26727
|
-
case "background_run":
|
|
26728
|
-
return `Starting background task`;
|
|
26729
|
-
case "task_status":
|
|
26730
|
-
return `Checking task status`;
|
|
26731
|
-
case "task_output":
|
|
26732
|
-
return `Reading task output`;
|
|
26733
|
-
case "task_stop":
|
|
26734
|
-
return `Stopping background task`;
|
|
26735
|
-
case "sub_agent":
|
|
26736
|
-
return `Delegating to sub agent`;
|
|
26737
|
-
case "image_read":
|
|
26738
|
-
return `Reading image`;
|
|
26739
|
-
case "screenshot":
|
|
26740
|
-
return `Taking screenshot`;
|
|
26741
|
-
case "ocr":
|
|
26742
|
-
return `Extracting text from image`;
|
|
26743
|
-
case "create_tool":
|
|
26744
|
-
return `Creating custom tool`;
|
|
26745
|
-
case "manage_tools":
|
|
26746
|
-
return `Managing custom tools`;
|
|
26747
|
-
case "browser_action":
|
|
26748
|
-
return `Browser ${args["action"] ?? "action"}`;
|
|
26749
|
-
case "scheduler":
|
|
26750
|
-
return `${args["action"] === "create" ? "Scheduling task" : "Checking scheduler"}`;
|
|
26751
|
-
case "reminder":
|
|
26752
|
-
return `${args["action"] === "set" ? "Setting reminder" : "Checking reminders"}`;
|
|
26753
|
-
case "agenda":
|
|
26754
|
-
return `Checking agenda`;
|
|
26755
|
-
default:
|
|
26756
|
-
return `Using ${toolName}`;
|
|
26757
|
-
}
|
|
27071
|
+
function getTier(personality) {
|
|
27072
|
+
if (personality <= 2)
|
|
27073
|
+
return "terse";
|
|
27074
|
+
if (personality <= 3)
|
|
27075
|
+
return "conv";
|
|
27076
|
+
return "chatty";
|
|
26758
27077
|
}
|
|
26759
|
-
function
|
|
27078
|
+
function describeToolCall(toolName, args, personality = 2) {
|
|
27079
|
+
const path = args["path"];
|
|
27080
|
+
const file = path ? path.split("/").pop() ?? path : "";
|
|
27081
|
+
const tier = getTier(personality);
|
|
27082
|
+
const prefix = personality >= 3 ? contextPrefix(toolName, file) : "";
|
|
27083
|
+
narration.toolCount++;
|
|
27084
|
+
narration.toolCounts[toolName] = (narration.toolCounts[toolName] ?? 0) + 1;
|
|
27085
|
+
narration.lastTool = toolName;
|
|
27086
|
+
if (file) {
|
|
27087
|
+
narration.filesSeen.add(file);
|
|
27088
|
+
narration.lastFile = file;
|
|
27089
|
+
}
|
|
27090
|
+
let base;
|
|
27091
|
+
const poolKey = `${toolName}_${tier}`;
|
|
26760
27092
|
switch (toolName) {
|
|
26761
27093
|
case "file_read":
|
|
26762
|
-
|
|
27094
|
+
base = pick(poolKey, (FILE_READ_VARIANTS[tier] ?? FILE_READ_VARIANTS.terse)(file, args));
|
|
27095
|
+
break;
|
|
26763
27096
|
case "file_write":
|
|
26764
|
-
|
|
27097
|
+
base = pick(poolKey, (FILE_WRITE_VARIANTS[tier] ?? FILE_WRITE_VARIANTS.terse)(file, args));
|
|
27098
|
+
break;
|
|
26765
27099
|
case "file_edit":
|
|
26766
|
-
return `Making some edits to ${file}`;
|
|
26767
27100
|
case "file_patch":
|
|
26768
|
-
|
|
26769
|
-
|
|
26770
|
-
|
|
27101
|
+
base = pick(poolKey, (FILE_EDIT_VARIANTS[tier] ?? FILE_EDIT_VARIANTS.terse)(file, args));
|
|
27102
|
+
break;
|
|
27103
|
+
case "shell": {
|
|
27104
|
+
const cat = getShellCategory(String(args["command"] ?? ""));
|
|
27105
|
+
const pool = SHELL_VARIANTS[cat] ?? SHELL_VARIANTS.generic;
|
|
27106
|
+
base = pick(`shell_${cat}_${tier}`, pool[tier] ?? pool.terse);
|
|
27107
|
+
break;
|
|
27108
|
+
}
|
|
26771
27109
|
case "grep_search":
|
|
26772
|
-
|
|
26773
|
-
|
|
26774
|
-
|
|
26775
|
-
|
|
26776
|
-
|
|
27110
|
+
base = pick(poolKey, (GREP_VARIANTS[tier] ?? GREP_VARIANTS.terse)(file, args));
|
|
27111
|
+
break;
|
|
27112
|
+
case "find_files": {
|
|
27113
|
+
const pat = args["pattern"] ?? "pattern";
|
|
27114
|
+
const findVariants = {
|
|
27115
|
+
terse: [`Finding ${pat}`, `Searching for ${pat}`],
|
|
27116
|
+
conv: [`Looking for files matching ${pat}`, `Finding files that match ${pat}`],
|
|
27117
|
+
chatty: [`Scouring the project for ${pat}`, `Searching far and wide for ${pat}`, `Let me find everything matching ${pat}`]
|
|
27118
|
+
};
|
|
27119
|
+
base = pick(poolKey, findVariants[tier] ?? findVariants.terse);
|
|
27120
|
+
break;
|
|
27121
|
+
}
|
|
27122
|
+
case "list_directory": {
|
|
27123
|
+
const dir = file || "the directory";
|
|
27124
|
+
const listVariants = {
|
|
27125
|
+
terse: [`Listing ${dir}`, `Checking ${dir}`],
|
|
27126
|
+
conv: [`Checking what's in ${dir}`, `Looking at ${dir} contents`],
|
|
27127
|
+
chatty: [`Let's see what we've got in ${dir}`, `Browsing through ${dir}`]
|
|
27128
|
+
};
|
|
27129
|
+
base = pick(poolKey, listVariants[tier] ?? listVariants.terse);
|
|
27130
|
+
break;
|
|
27131
|
+
}
|
|
26777
27132
|
case "web_search":
|
|
26778
|
-
|
|
27133
|
+
base = pick(poolKey, (WEB_SEARCH_VARIANTS[tier] ?? WEB_SEARCH_VARIANTS.terse)(file, args));
|
|
27134
|
+
break;
|
|
26779
27135
|
case "web_fetch":
|
|
26780
|
-
|
|
27136
|
+
base = pick(poolKey, (WEB_FETCH_VARIANTS[tier] ?? WEB_FETCH_VARIANTS.terse)(file, args));
|
|
27137
|
+
break;
|
|
26781
27138
|
case "memory_read":
|
|
26782
|
-
|
|
27139
|
+
base = pick(poolKey, (MEMORY_READ_VARIANTS[tier] ?? MEMORY_READ_VARIANTS.terse)(file, args));
|
|
27140
|
+
break;
|
|
26783
27141
|
case "memory_write":
|
|
26784
|
-
|
|
27142
|
+
base = pick(poolKey, (MEMORY_WRITE_VARIANTS[tier] ?? MEMORY_WRITE_VARIANTS.terse)(file, args));
|
|
27143
|
+
break;
|
|
26785
27144
|
case "task_complete":
|
|
26786
|
-
|
|
26787
|
-
|
|
26788
|
-
return `Editing several files at once`;
|
|
26789
|
-
case "codebase_map":
|
|
26790
|
-
return `Mapping out the project structure`;
|
|
26791
|
-
case "diagnostic":
|
|
26792
|
-
return `Running some diagnostics`;
|
|
26793
|
-
case "git_info":
|
|
26794
|
-
return `Checking the git status`;
|
|
27145
|
+
base = String(args["summary"] ?? (tier === "chatty" ? "And that's a wrap" : tier === "conv" ? "All done" : "Task complete"));
|
|
27146
|
+
break;
|
|
26795
27147
|
case "sub_agent":
|
|
26796
|
-
|
|
26797
|
-
|
|
26798
|
-
|
|
26799
|
-
|
|
26800
|
-
|
|
26801
|
-
|
|
26802
|
-
|
|
26803
|
-
|
|
26804
|
-
|
|
26805
|
-
|
|
26806
|
-
|
|
26807
|
-
case "
|
|
26808
|
-
|
|
26809
|
-
|
|
26810
|
-
|
|
27148
|
+
base = pick(poolKey, (SUB_AGENT_VARIANTS[tier] ?? SUB_AGENT_VARIANTS.terse)(file, args));
|
|
27149
|
+
break;
|
|
27150
|
+
case "batch_edit": {
|
|
27151
|
+
const batchV = {
|
|
27152
|
+
terse: ["Editing multiple files", "Batch editing"],
|
|
27153
|
+
conv: ["Editing several files at once", "Making changes across multiple files"],
|
|
27154
|
+
chatty: ["Okay, editing a bunch of files here, bear with me", "Touching several files at once, lot of ground to cover"]
|
|
27155
|
+
};
|
|
27156
|
+
base = pick(poolKey, batchV[tier] ?? batchV.terse);
|
|
27157
|
+
break;
|
|
27158
|
+
}
|
|
27159
|
+
case "codebase_map": {
|
|
27160
|
+
const mapV = {
|
|
27161
|
+
terse: ["Mapping project", "Scanning structure"],
|
|
27162
|
+
conv: ["Mapping out the project structure", "Getting the project layout"],
|
|
27163
|
+
chatty: ["Let me get the lay of the land on this project", "Mapping the whole codebase out"]
|
|
27164
|
+
};
|
|
27165
|
+
base = pick(poolKey, mapV[tier] ?? mapV.terse);
|
|
27166
|
+
break;
|
|
27167
|
+
}
|
|
27168
|
+
case "diagnostic": {
|
|
27169
|
+
const diagV = {
|
|
27170
|
+
terse: ["Running diagnostics", "Diagnostic check"],
|
|
27171
|
+
conv: ["Running some diagnostics", "Let me run a diagnostic"],
|
|
27172
|
+
chatty: ["Running diagnostics, let's see if anything looks off", "Time for a health check"]
|
|
27173
|
+
};
|
|
27174
|
+
base = pick(poolKey, diagV[tier] ?? diagV.terse);
|
|
27175
|
+
break;
|
|
27176
|
+
}
|
|
27177
|
+
case "git_info": {
|
|
27178
|
+
const gitV = {
|
|
27179
|
+
terse: ["Checking git", "Git status"],
|
|
27180
|
+
conv: ["Checking the git status", "Looking at git info"],
|
|
27181
|
+
chatty: ["Checking in with git to see where things stand", "Let me see what git has to say"]
|
|
27182
|
+
};
|
|
27183
|
+
base = pick(poolKey, gitV[tier] ?? gitV.terse);
|
|
27184
|
+
break;
|
|
27185
|
+
}
|
|
27186
|
+
case "image_read": {
|
|
27187
|
+
const imgV = {
|
|
27188
|
+
terse: ["Reading image", "Loading image"],
|
|
27189
|
+
conv: ["Taking a look at that image", "Opening the image"],
|
|
27190
|
+
chatty: ["Let me get a good look at that image", "Opening up the image to see what's there"]
|
|
27191
|
+
};
|
|
27192
|
+
base = pick(poolKey, imgV[tier] ?? imgV.terse);
|
|
27193
|
+
break;
|
|
27194
|
+
}
|
|
27195
|
+
case "screenshot": {
|
|
27196
|
+
const ssV = {
|
|
27197
|
+
terse: ["Taking screenshot", "Capturing screen"],
|
|
27198
|
+
conv: ["Grabbing a screenshot", "Capturing what's on screen"],
|
|
27199
|
+
chatty: ["Snapping a screenshot to see what's happening", "Let me grab a visual"]
|
|
27200
|
+
};
|
|
27201
|
+
base = pick(poolKey, ssV[tier] ?? ssV.terse);
|
|
27202
|
+
break;
|
|
27203
|
+
}
|
|
27204
|
+
case "ocr": {
|
|
27205
|
+
const ocrV = {
|
|
27206
|
+
terse: ["Extracting text", "Running OCR"],
|
|
27207
|
+
conv: ["Extracting text from the image", "Running OCR on this"],
|
|
27208
|
+
chatty: ["Let me pull the text out of this image", "Running optical character recognition"]
|
|
27209
|
+
};
|
|
27210
|
+
base = pick(poolKey, ocrV[tier] ?? ocrV.terse);
|
|
27211
|
+
break;
|
|
27212
|
+
}
|
|
27213
|
+
case "browser_action": {
|
|
27214
|
+
const action = args["action"] ?? "action";
|
|
27215
|
+
const browserV = {
|
|
27216
|
+
terse: [`Browser ${action}`],
|
|
27217
|
+
conv: [
|
|
27218
|
+
action === "navigate" ? "Opening that page" : action === "screenshot" ? "Grabbing a screenshot of the browser" : `Browser ${action}`
|
|
27219
|
+
],
|
|
27220
|
+
chatty: [
|
|
27221
|
+
action === "navigate" ? "Firing up the browser, let's see what's on that page" : action === "screenshot" ? "Getting a visual from the browser" : `Doing a browser ${action}`
|
|
27222
|
+
]
|
|
27223
|
+
};
|
|
27224
|
+
base = pick(poolKey, browserV[tier] ?? browserV.terse);
|
|
27225
|
+
break;
|
|
27226
|
+
}
|
|
27227
|
+
default: {
|
|
27228
|
+
const defaultV = {
|
|
27229
|
+
terse: [`Using ${toolName}`],
|
|
27230
|
+
conv: [`Working with ${toolName}`, `Using ${toolName}`],
|
|
27231
|
+
chatty: [`Pulling in ${toolName}, hang tight`, `Using ${toolName} for this`, `Working with ${toolName} here`]
|
|
27232
|
+
};
|
|
27233
|
+
base = pick(poolKey, defaultV[tier] ?? defaultV.terse);
|
|
27234
|
+
break;
|
|
27235
|
+
}
|
|
26811
27236
|
}
|
|
26812
|
-
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
|
|
26816
|
-
|
|
26817
|
-
|
|
26818
|
-
return `Time to write this out to ${file}`;
|
|
26819
|
-
case "file_edit":
|
|
26820
|
-
return `Let me tweak ${file}, I think I see what needs to change`;
|
|
26821
|
-
case "file_patch":
|
|
26822
|
-
return `Patching up ${file}, this should do the trick`;
|
|
26823
|
-
case "shell":
|
|
26824
|
-
return describeShellChatty(String(args["command"] ?? ""));
|
|
26825
|
-
case "grep_search":
|
|
26826
|
-
return `Hunting through the code for ${args["pattern"] ?? "what we need"}`;
|
|
26827
|
-
case "find_files":
|
|
26828
|
-
return `Scouring the project for files matching ${args["pattern"] ?? "our target"}`;
|
|
26829
|
-
case "list_directory":
|
|
26830
|
-
return `Let's see what we've got in ${file || "this directory"}`;
|
|
26831
|
-
case "web_search":
|
|
26832
|
-
return `Off to the web to track this down`;
|
|
26833
|
-
case "web_fetch":
|
|
26834
|
-
return `Grabbing that page, one moment`;
|
|
26835
|
-
case "memory_read":
|
|
26836
|
-
return `Let me dig through my notes on this`;
|
|
26837
|
-
case "memory_write":
|
|
26838
|
-
return `Stashing this away for later`;
|
|
26839
|
-
case "task_complete":
|
|
26840
|
-
return String(args["summary"] ?? "And that's a wrap");
|
|
26841
|
-
case "batch_edit":
|
|
26842
|
-
return `Okay, editing a bunch of files here, bear with me`;
|
|
26843
|
-
case "codebase_map":
|
|
26844
|
-
return `Let me get the lay of the land on this project`;
|
|
26845
|
-
case "diagnostic":
|
|
26846
|
-
return `Running diagnostics, let's see if anything looks off`;
|
|
26847
|
-
case "git_info":
|
|
26848
|
-
return `Checking in with git to see where things stand`;
|
|
26849
|
-
case "sub_agent":
|
|
26850
|
-
return `Bringing in reinforcements for this one`;
|
|
26851
|
-
case "image_read":
|
|
26852
|
-
return `Let me get a good look at that image`;
|
|
26853
|
-
case "screenshot":
|
|
26854
|
-
return `Snapping a screenshot to see what's happening`;
|
|
26855
|
-
case "browser_action":
|
|
26856
|
-
return `Firing up the browser, let's ${args["action"] === "navigate" ? "see what's on that page" : args["action"] === "screenshot" ? "get a visual" : `${args["action"] ?? "do this"}`}`;
|
|
26857
|
-
case "scheduler":
|
|
26858
|
-
return `${args["action"] === "create" ? "Alright, let me set up a recurring task for you" : "Let me pull up the schedule and see what's coming up"}`;
|
|
26859
|
-
case "reminder":
|
|
26860
|
-
return `${args["action"] === "set" ? "Leaving myself a note for future me, don't let me forget" : "Let me check if past me left any reminders"}`;
|
|
26861
|
-
case "agenda":
|
|
26862
|
-
return `Let me see the full picture of what needs doing`;
|
|
26863
|
-
default:
|
|
26864
|
-
return `Pulling in ${toolName}, hang tight`;
|
|
27237
|
+
if (!prefix)
|
|
27238
|
+
return base;
|
|
27239
|
+
if (prefix.endsWith(". ") || prefix.endsWith("! "))
|
|
27240
|
+
return prefix + base;
|
|
27241
|
+
if (prefix && base.length > 0) {
|
|
27242
|
+
return prefix + base.charAt(0).toLowerCase() + base.slice(1);
|
|
26865
27243
|
}
|
|
26866
|
-
|
|
26867
|
-
function describeShellTerse(cmd) {
|
|
26868
|
-
if (/npm\s+test|vitest|jest|mocha/.test(cmd))
|
|
26869
|
-
return "Running tests";
|
|
26870
|
-
if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
|
|
26871
|
-
return "Building project";
|
|
26872
|
-
if (/npm\s+install|pnpm\s+install/.test(cmd))
|
|
26873
|
-
return "Installing dependencies";
|
|
26874
|
-
if (/git\s+/.test(cmd))
|
|
26875
|
-
return "Running git command";
|
|
26876
|
-
if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
|
|
26877
|
-
return "Running linter";
|
|
26878
|
-
if (cmd.length > 40)
|
|
26879
|
-
return "Running shell command";
|
|
26880
|
-
return `Running ${cmd.slice(0, 30)}`;
|
|
26881
|
-
}
|
|
26882
|
-
function describeShellConversational(cmd) {
|
|
26883
|
-
if (/npm\s+test|vitest|jest|mocha/.test(cmd))
|
|
26884
|
-
return "Let's run the tests and see how we're doing";
|
|
26885
|
-
if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
|
|
26886
|
-
return "Building the project now";
|
|
26887
|
-
if (/npm\s+install|pnpm\s+install/.test(cmd))
|
|
26888
|
-
return "Installing the dependencies";
|
|
26889
|
-
if (/git\s+/.test(cmd))
|
|
26890
|
-
return "Running a git command";
|
|
26891
|
-
if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
|
|
26892
|
-
return "Checking the code with the linter";
|
|
26893
|
-
return "Running a command";
|
|
26894
|
-
}
|
|
26895
|
-
function describeShellChatty(cmd) {
|
|
26896
|
-
if (/npm\s+test|vitest|jest|mocha/.test(cmd))
|
|
26897
|
-
return "Alright, moment of truth, let's see if the tests pass";
|
|
26898
|
-
if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
|
|
26899
|
-
return "Kicking off a build, fingers crossed";
|
|
26900
|
-
if (/npm\s+install|pnpm\s+install/.test(cmd))
|
|
26901
|
-
return "Pulling in dependencies, this might take a sec";
|
|
26902
|
-
if (/git\s+/.test(cmd))
|
|
26903
|
-
return "Checking in with git";
|
|
26904
|
-
if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
|
|
26905
|
-
return "Running the linter, let's keep things tidy";
|
|
26906
|
-
return "Firing off a shell command";
|
|
27244
|
+
return base;
|
|
26907
27245
|
}
|
|
26908
27246
|
function describeToolResult(toolName, success, personality = 2) {
|
|
26909
27247
|
if (toolName === "task_complete")
|
|
26910
27248
|
return "";
|
|
26911
|
-
|
|
26912
|
-
|
|
27249
|
+
const tier = getTier(personality);
|
|
27250
|
+
if (success) {
|
|
27251
|
+
narration.consecutiveErrors = 0;
|
|
27252
|
+
if (personality >= 3 && Math.random() < 0.4)
|
|
27253
|
+
return "";
|
|
27254
|
+
return pick(`result_ok_${tier}`, RESULT_SUCCESS_VARIANTS[tier] ?? RESULT_SUCCESS_VARIANTS.terse);
|
|
26913
27255
|
}
|
|
26914
|
-
|
|
26915
|
-
|
|
27256
|
+
narration.consecutiveErrors++;
|
|
27257
|
+
narration.totalErrors++;
|
|
27258
|
+
if (narration.consecutiveErrors >= 3) {
|
|
27259
|
+
return pick(`result_multifail_${tier}`, RESULT_MULTI_FAIL_VARIANTS[tier] ?? RESULT_MULTI_FAIL_VARIANTS.terse);
|
|
26916
27260
|
}
|
|
26917
|
-
return
|
|
27261
|
+
return pick(`result_fail_${tier}`, RESULT_FAIL_VARIANTS[tier] ?? RESULT_FAIL_VARIANTS.terse);
|
|
26918
27262
|
}
|
|
26919
27263
|
function describeTaskComplete(summary, completed, personality = 2) {
|
|
26920
27264
|
const truncated = summary.length > 300 ? summary.slice(0, 300) + "..." : summary;
|
|
27265
|
+
const tier = getTier(personality);
|
|
26921
27266
|
if (!completed) {
|
|
26922
|
-
|
|
26923
|
-
return "Task did not complete.";
|
|
26924
|
-
if (personality <= 3)
|
|
26925
|
-
return "I wasn't able to finish that one.";
|
|
26926
|
-
return "Well, that didn't quite get there. You might want to take a look at what's left.";
|
|
27267
|
+
return pick(`task_incomplete_${tier}`, TASK_INCOMPLETE_VARIANTS[tier] ?? TASK_INCOMPLETE_VARIANTS.terse);
|
|
26927
27268
|
}
|
|
26928
|
-
|
|
26929
|
-
|
|
26930
|
-
|
|
26931
|
-
|
|
26932
|
-
return `And we're done! ${truncated}`;
|
|
27269
|
+
const opener = pick(`task_complete_${tier}`, TASK_COMPLETE_VARIANTS[tier] ?? TASK_COMPLETE_VARIANTS.terse);
|
|
27270
|
+
if (truncated)
|
|
27271
|
+
return `${opener} ${truncated}`;
|
|
27272
|
+
return opener;
|
|
26933
27273
|
}
|
|
26934
27274
|
function formatBytes2(bytes) {
|
|
26935
27275
|
if (bytes < 1024)
|
|
@@ -26938,7 +27278,7 @@ function formatBytes2(bytes) {
|
|
|
26938
27278
|
return `${(bytes / 1024).toFixed(0)}KB`;
|
|
26939
27279
|
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
26940
27280
|
}
|
|
26941
|
-
var VOICE_MODELS, VoiceEngine;
|
|
27281
|
+
var VOICE_MODELS, VoiceEngine, narration, FILE_READ_VARIANTS, FILE_WRITE_VARIANTS, FILE_EDIT_VARIANTS, GREP_VARIANTS, WEB_SEARCH_VARIANTS, WEB_FETCH_VARIANTS, MEMORY_READ_VARIANTS, MEMORY_WRITE_VARIANTS, SUB_AGENT_VARIANTS, SHELL_VARIANTS, RESULT_SUCCESS_VARIANTS, RESULT_FAIL_VARIANTS, RESULT_MULTI_FAIL_VARIANTS, TASK_COMPLETE_VARIANTS, TASK_INCOMPLETE_VARIANTS;
|
|
26942
27282
|
var init_voice = __esm({
|
|
26943
27283
|
"packages/cli/dist/tui/voice.js"() {
|
|
26944
27284
|
"use strict";
|
|
@@ -27500,6 +27840,368 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
27500
27840
|
renderInfo("Voice model loaded.");
|
|
27501
27841
|
}
|
|
27502
27842
|
};
|
|
27843
|
+
narration = {
|
|
27844
|
+
toolCount: 0,
|
|
27845
|
+
toolCounts: {},
|
|
27846
|
+
consecutiveErrors: 0,
|
|
27847
|
+
totalErrors: 0,
|
|
27848
|
+
lastTool: "",
|
|
27849
|
+
lastFile: "",
|
|
27850
|
+
filesSeen: /* @__PURE__ */ new Set(),
|
|
27851
|
+
lastVariantIdx: {}
|
|
27852
|
+
};
|
|
27853
|
+
FILE_READ_VARIANTS = {
|
|
27854
|
+
terse: (f) => [`Reading ${f}`, `Opening ${f}`, `Loading ${f}`],
|
|
27855
|
+
conv: (f) => [
|
|
27856
|
+
`Let me take a look at ${f}`,
|
|
27857
|
+
`Opening up ${f}`,
|
|
27858
|
+
`Pulling up ${f}`,
|
|
27859
|
+
`Checking ${f}`,
|
|
27860
|
+
`Let me see what's in ${f}`
|
|
27861
|
+
],
|
|
27862
|
+
chatty: (f) => [
|
|
27863
|
+
`Alright, let's crack open ${f} and see what we're working with`,
|
|
27864
|
+
`Diving into ${f}`,
|
|
27865
|
+
`Let me pull up ${f} and see what's going on`,
|
|
27866
|
+
`Time to see what ${f} has for us`,
|
|
27867
|
+
`Opening ${f}, let's see what we've got`,
|
|
27868
|
+
`Taking a look inside ${f}`
|
|
27869
|
+
]
|
|
27870
|
+
};
|
|
27871
|
+
FILE_WRITE_VARIANTS = {
|
|
27872
|
+
terse: (f) => [`Writing ${f}`, `Saving ${f}`, `Creating ${f}`],
|
|
27873
|
+
conv: (f) => [
|
|
27874
|
+
`Writing changes to ${f}`,
|
|
27875
|
+
`Saving the updates to ${f}`,
|
|
27876
|
+
`Putting this into ${f}`,
|
|
27877
|
+
`Writing this out to ${f}`
|
|
27878
|
+
],
|
|
27879
|
+
chatty: (f) => [
|
|
27880
|
+
`Time to write this out to ${f}`,
|
|
27881
|
+
`Laying down the changes in ${f}`,
|
|
27882
|
+
`Writing the new version of ${f}`,
|
|
27883
|
+
`Let me save this to ${f} before I forget`,
|
|
27884
|
+
`Committing these changes to ${f}`
|
|
27885
|
+
]
|
|
27886
|
+
};
|
|
27887
|
+
FILE_EDIT_VARIANTS = {
|
|
27888
|
+
terse: (f) => [`Editing ${f}`, `Modifying ${f}`, `Updating ${f}`],
|
|
27889
|
+
conv: (f) => [
|
|
27890
|
+
`Making some edits to ${f}`,
|
|
27891
|
+
`Adjusting ${f}`,
|
|
27892
|
+
`Tweaking ${f}`,
|
|
27893
|
+
`Updating ${f} with the fix`,
|
|
27894
|
+
`Applying changes to ${f}`
|
|
27895
|
+
],
|
|
27896
|
+
chatty: (f) => [
|
|
27897
|
+
`Let me tweak ${f}, I think I see what needs to change`,
|
|
27898
|
+
`Making some surgical edits to ${f}`,
|
|
27899
|
+
`Alright, adjusting ${f} now`,
|
|
27900
|
+
`Got it, let me fix that up in ${f}`,
|
|
27901
|
+
`Reshaping ${f} a bit here`,
|
|
27902
|
+
`Modifying ${f}, this should get us closer`
|
|
27903
|
+
]
|
|
27904
|
+
};
|
|
27905
|
+
GREP_VARIANTS = {
|
|
27906
|
+
terse: (_f, a) => [`Searching for ${a["pattern"] ?? "pattern"}`, `Grepping ${a["pattern"] ?? "code"}`],
|
|
27907
|
+
conv: (_f, a) => [
|
|
27908
|
+
`Searching the code for ${a["pattern"] ?? "that pattern"}`,
|
|
27909
|
+
`Looking for ${a["pattern"] ?? "matches"} in the codebase`,
|
|
27910
|
+
`Scanning for ${a["pattern"] ?? "that"} across the files`
|
|
27911
|
+
],
|
|
27912
|
+
chatty: (_f, a) => [
|
|
27913
|
+
`Hunting through the code for ${a["pattern"] ?? "what we need"}`,
|
|
27914
|
+
`Let me track down ${a["pattern"] ?? "that"} in the source`,
|
|
27915
|
+
`Scouring the codebase for ${a["pattern"] ?? "our target"}`,
|
|
27916
|
+
`Searching high and low for ${a["pattern"] ?? "this pattern"}`
|
|
27917
|
+
]
|
|
27918
|
+
};
|
|
27919
|
+
WEB_SEARCH_VARIANTS = {
|
|
27920
|
+
terse: () => [`Searching the web`, `Web search`, `Looking it up online`],
|
|
27921
|
+
conv: () => [
|
|
27922
|
+
`Let me search the web for that`,
|
|
27923
|
+
`Checking online for that`,
|
|
27924
|
+
`Let me look that up`,
|
|
27925
|
+
`Searching the web real quick`
|
|
27926
|
+
],
|
|
27927
|
+
chatty: () => [
|
|
27928
|
+
`Off to the web to track this down`,
|
|
27929
|
+
`Let me see what the internet has to say about this`,
|
|
27930
|
+
`Heading online to dig up some answers`,
|
|
27931
|
+
`Time for a quick web search`,
|
|
27932
|
+
`Let me consult the wider world on this one`
|
|
27933
|
+
]
|
|
27934
|
+
};
|
|
27935
|
+
WEB_FETCH_VARIANTS = {
|
|
27936
|
+
terse: () => [`Fetching page`, `Loading page`, `Downloading page`],
|
|
27937
|
+
conv: () => [
|
|
27938
|
+
`Pulling up that web page`,
|
|
27939
|
+
`Fetching the page now`,
|
|
27940
|
+
`Loading that page`,
|
|
27941
|
+
`Grabbing the content from that URL`
|
|
27942
|
+
],
|
|
27943
|
+
chatty: () => [
|
|
27944
|
+
`Grabbing that page, one moment`,
|
|
27945
|
+
`Let me pull that page up and see what's there`,
|
|
27946
|
+
`Fetching the goods from that URL`,
|
|
27947
|
+
`Loading up that page now`
|
|
27948
|
+
]
|
|
27949
|
+
};
|
|
27950
|
+
MEMORY_READ_VARIANTS = {
|
|
27951
|
+
terse: () => [`Reading memory`, `Checking notes`, `Recalling`],
|
|
27952
|
+
conv: () => [
|
|
27953
|
+
`Checking my notes`,
|
|
27954
|
+
`Let me see what I remember`,
|
|
27955
|
+
`Pulling up my notes on this`,
|
|
27956
|
+
`Looking through memory`
|
|
27957
|
+
],
|
|
27958
|
+
chatty: () => [
|
|
27959
|
+
`Let me dig through my notes on this`,
|
|
27960
|
+
`Checking what I've got stored away`,
|
|
27961
|
+
`Searching my memory for something relevant`,
|
|
27962
|
+
`Let me recall what I know about this`
|
|
27963
|
+
]
|
|
27964
|
+
};
|
|
27965
|
+
MEMORY_WRITE_VARIANTS = {
|
|
27966
|
+
terse: () => [`Saving to memory`, `Noting that`, `Remembering`],
|
|
27967
|
+
conv: () => [
|
|
27968
|
+
`Making a note of that`,
|
|
27969
|
+
`Saving this for later`,
|
|
27970
|
+
`Jotting that down`,
|
|
27971
|
+
`Storing that away`
|
|
27972
|
+
],
|
|
27973
|
+
chatty: () => [
|
|
27974
|
+
`Stashing this away for later`,
|
|
27975
|
+
`Making a mental note of this one`,
|
|
27976
|
+
`Saving this to memory so I don't forget`,
|
|
27977
|
+
`Filing this away for next time`
|
|
27978
|
+
]
|
|
27979
|
+
};
|
|
27980
|
+
SUB_AGENT_VARIANTS = {
|
|
27981
|
+
terse: () => [`Delegating to sub agent`, `Spawning sub agent`, `Handing off`],
|
|
27982
|
+
conv: () => [
|
|
27983
|
+
`Handing this off to a sub agent`,
|
|
27984
|
+
`Bringing in some help for this`,
|
|
27985
|
+
`Delegating this part of the work`
|
|
27986
|
+
],
|
|
27987
|
+
chatty: () => [
|
|
27988
|
+
`Bringing in reinforcements for this one`,
|
|
27989
|
+
`Let me hand this off to a specialist`,
|
|
27990
|
+
`Calling in backup on this`,
|
|
27991
|
+
`This needs a dedicated agent, passing it along`
|
|
27992
|
+
]
|
|
27993
|
+
};
|
|
27994
|
+
SHELL_VARIANTS = {
|
|
27995
|
+
test: {
|
|
27996
|
+
terse: ["Running tests", "Testing", "Executing tests"],
|
|
27997
|
+
conv: [
|
|
27998
|
+
"Let's run the tests and see how we're doing",
|
|
27999
|
+
"Running the test suite",
|
|
28000
|
+
"Time to check if the tests pass",
|
|
28001
|
+
"Let me run those tests"
|
|
28002
|
+
],
|
|
28003
|
+
chatty: [
|
|
28004
|
+
"Alright, moment of truth, let's see if the tests pass",
|
|
28005
|
+
"Running the tests, fingers crossed",
|
|
28006
|
+
"Test time, let's see where we stand",
|
|
28007
|
+
"Kicking off the test suite, here goes nothing",
|
|
28008
|
+
"Let's put this to the test, literally"
|
|
28009
|
+
]
|
|
28010
|
+
},
|
|
28011
|
+
build: {
|
|
28012
|
+
terse: ["Building project", "Compiling", "Building"],
|
|
28013
|
+
conv: [
|
|
28014
|
+
"Building the project now",
|
|
28015
|
+
"Compiling everything",
|
|
28016
|
+
"Starting the build",
|
|
28017
|
+
"Let me build this"
|
|
28018
|
+
],
|
|
28019
|
+
chatty: [
|
|
28020
|
+
"Kicking off a build, fingers crossed",
|
|
28021
|
+
"Time to compile and see if everything holds together",
|
|
28022
|
+
"Building the project, let's see how it goes",
|
|
28023
|
+
"Alright, build time",
|
|
28024
|
+
"Compiling the whole thing, one moment"
|
|
28025
|
+
]
|
|
28026
|
+
},
|
|
28027
|
+
install: {
|
|
28028
|
+
terse: ["Installing dependencies", "Installing packages", "Running install"],
|
|
28029
|
+
conv: [
|
|
28030
|
+
"Installing the dependencies",
|
|
28031
|
+
"Pulling in the packages",
|
|
28032
|
+
"Getting the dependencies set up"
|
|
28033
|
+
],
|
|
28034
|
+
chatty: [
|
|
28035
|
+
"Pulling in dependencies, this might take a sec",
|
|
28036
|
+
"Installing packages, grab a coffee",
|
|
28037
|
+
"Setting up the dependencies now"
|
|
28038
|
+
]
|
|
28039
|
+
},
|
|
28040
|
+
git: {
|
|
28041
|
+
terse: ["Running git command", "Git operation", "Checking git"],
|
|
28042
|
+
conv: [
|
|
28043
|
+
"Running a git command",
|
|
28044
|
+
"Checking with git",
|
|
28045
|
+
"Let me do a git operation"
|
|
28046
|
+
],
|
|
28047
|
+
chatty: [
|
|
28048
|
+
"Checking in with git to see where things stand",
|
|
28049
|
+
"Let me consult git on this",
|
|
28050
|
+
"Running a quick git operation",
|
|
28051
|
+
"Talking to git for a second"
|
|
28052
|
+
]
|
|
28053
|
+
},
|
|
28054
|
+
lint: {
|
|
28055
|
+
terse: ["Running linter", "Linting", "Checking style"],
|
|
28056
|
+
conv: [
|
|
28057
|
+
"Checking the code with the linter",
|
|
28058
|
+
"Running the linter",
|
|
28059
|
+
"Let me check the code style"
|
|
28060
|
+
],
|
|
28061
|
+
chatty: [
|
|
28062
|
+
"Running the linter, let's keep things tidy",
|
|
28063
|
+
"Lint check time, making sure everything's clean",
|
|
28064
|
+
"Let's see if the linter is happy with this"
|
|
28065
|
+
]
|
|
28066
|
+
},
|
|
28067
|
+
node: {
|
|
28068
|
+
terse: ["Running Node script", "Executing script"],
|
|
28069
|
+
conv: [
|
|
28070
|
+
"Running a Node script",
|
|
28071
|
+
"Executing this script",
|
|
28072
|
+
"Let me run this"
|
|
28073
|
+
],
|
|
28074
|
+
chatty: [
|
|
28075
|
+
"Firing up this Node script, let's see what happens",
|
|
28076
|
+
"Running the script now",
|
|
28077
|
+
"Executing this one, stand by"
|
|
28078
|
+
]
|
|
28079
|
+
},
|
|
28080
|
+
python: {
|
|
28081
|
+
terse: ["Running Python", "Executing Python script"],
|
|
28082
|
+
conv: ["Running a Python script", "Executing the Python code"],
|
|
28083
|
+
chatty: [
|
|
28084
|
+
"Running the Python script, one moment",
|
|
28085
|
+
"Firing up Python for this one"
|
|
28086
|
+
]
|
|
28087
|
+
},
|
|
28088
|
+
network: {
|
|
28089
|
+
terse: ["Making network request", "Fetching data"],
|
|
28090
|
+
conv: ["Making a network request", "Fetching some data"],
|
|
28091
|
+
chatty: ["Reaching out to the network", "Making a request, let's see what comes back"]
|
|
28092
|
+
},
|
|
28093
|
+
container: {
|
|
28094
|
+
terse: ["Running container command", "Docker operation"],
|
|
28095
|
+
conv: ["Running a container command", "Working with containers"],
|
|
28096
|
+
chatty: ["Spinning up containers, one moment", "Doing some container work"]
|
|
28097
|
+
},
|
|
28098
|
+
generic: {
|
|
28099
|
+
terse: ["Running command", "Executing command", "Shell command"],
|
|
28100
|
+
conv: [
|
|
28101
|
+
"Running a command",
|
|
28102
|
+
"Executing a shell command",
|
|
28103
|
+
"Let me run this command",
|
|
28104
|
+
"Firing off a command"
|
|
28105
|
+
],
|
|
28106
|
+
chatty: [
|
|
28107
|
+
"Running a command, one moment",
|
|
28108
|
+
"Let me execute this and see what we get",
|
|
28109
|
+
"Firing off a shell command, stand by",
|
|
28110
|
+
"Executing this, let's see the output",
|
|
28111
|
+
"Running something in the shell real quick"
|
|
28112
|
+
]
|
|
28113
|
+
}
|
|
28114
|
+
};
|
|
28115
|
+
RESULT_SUCCESS_VARIANTS = {
|
|
28116
|
+
terse: ["Done", "OK", "Complete", "Got it"],
|
|
28117
|
+
conv: [
|
|
28118
|
+
"Got it",
|
|
28119
|
+
"That worked",
|
|
28120
|
+
"Good to go",
|
|
28121
|
+
"Looking good",
|
|
28122
|
+
"All set",
|
|
28123
|
+
"Done"
|
|
28124
|
+
],
|
|
28125
|
+
chatty: [
|
|
28126
|
+
"Looking good, moving on",
|
|
28127
|
+
"That went well, next step",
|
|
28128
|
+
"Nice, onward",
|
|
28129
|
+
"Perfect, let's keep going",
|
|
28130
|
+
"Got what I needed, moving on",
|
|
28131
|
+
"That came through, great",
|
|
28132
|
+
"Worked like a charm"
|
|
28133
|
+
]
|
|
28134
|
+
};
|
|
28135
|
+
RESULT_FAIL_VARIANTS = {
|
|
28136
|
+
terse: [
|
|
28137
|
+
"Failed, retrying",
|
|
28138
|
+
"Error, adjusting",
|
|
28139
|
+
"That failed, fixing"
|
|
28140
|
+
],
|
|
28141
|
+
conv: [
|
|
28142
|
+
"That didn't work, let me try another approach",
|
|
28143
|
+
"Hit a snag, adjusting course",
|
|
28144
|
+
"Ran into an issue, trying again",
|
|
28145
|
+
"Didn't go as expected, let me rethink this",
|
|
28146
|
+
"Not quite, let me try something else"
|
|
28147
|
+
],
|
|
28148
|
+
chatty: [
|
|
28149
|
+
"Hmm, that didn't go as planned, let me try a different angle",
|
|
28150
|
+
"Well that didn't work, but I've got another idea",
|
|
28151
|
+
"Okay, that approach didn't pan out, pivoting",
|
|
28152
|
+
"Hit a wall there, but I think I see another way",
|
|
28153
|
+
"Not the result I was hoping for, let me regroup",
|
|
28154
|
+
"That blew up, but no worries, I'll come at it differently",
|
|
28155
|
+
"Alright, that wasn't it, but I'm not giving up"
|
|
28156
|
+
]
|
|
28157
|
+
};
|
|
28158
|
+
RESULT_MULTI_FAIL_VARIANTS = {
|
|
28159
|
+
terse: ["Still failing, changing approach", "Error again, different method"],
|
|
28160
|
+
conv: [
|
|
28161
|
+
"Another miss, time to rethink this fundamentally",
|
|
28162
|
+
"Still not working, let me step back and reconsider",
|
|
28163
|
+
"Okay, clearly this approach isn't it"
|
|
28164
|
+
],
|
|
28165
|
+
chatty: [
|
|
28166
|
+
"That's a few misses now, time to really change things up",
|
|
28167
|
+
"Alright, clearly I need a completely different strategy here",
|
|
28168
|
+
"This keeps failing, let me take a step back and think about this differently",
|
|
28169
|
+
"Okay, I've been going about this wrong, new plan"
|
|
28170
|
+
]
|
|
28171
|
+
};
|
|
28172
|
+
TASK_COMPLETE_VARIANTS = {
|
|
28173
|
+
terse: ["Task complete.", "Done.", "Finished."],
|
|
28174
|
+
conv: [
|
|
28175
|
+
"All done.",
|
|
28176
|
+
"That's everything.",
|
|
28177
|
+
"Finished up.",
|
|
28178
|
+
"All taken care of.",
|
|
28179
|
+
"Wrapped that up."
|
|
28180
|
+
],
|
|
28181
|
+
chatty: [
|
|
28182
|
+
"And we're done!",
|
|
28183
|
+
"That's a wrap!",
|
|
28184
|
+
"All finished, good stuff.",
|
|
28185
|
+
"Mission accomplished.",
|
|
28186
|
+
"Everything's taken care of.",
|
|
28187
|
+
"Done and dusted."
|
|
28188
|
+
]
|
|
28189
|
+
};
|
|
28190
|
+
TASK_INCOMPLETE_VARIANTS = {
|
|
28191
|
+
terse: ["Task did not complete.", "Incomplete.", "Could not finish."],
|
|
28192
|
+
conv: [
|
|
28193
|
+
"I wasn't able to finish that one.",
|
|
28194
|
+
"Didn't quite get there.",
|
|
28195
|
+
"Ran out of steam on that one.",
|
|
28196
|
+
"Couldn't quite wrap that up."
|
|
28197
|
+
],
|
|
28198
|
+
chatty: [
|
|
28199
|
+
"Well, that didn't quite get there. You might want to take a look at what's left.",
|
|
28200
|
+
"I gave it my best shot, but couldn't finish everything.",
|
|
28201
|
+
"Got partway there, but some things still need attention.",
|
|
28202
|
+
"Not fully done, but I made progress on it."
|
|
28203
|
+
]
|
|
28204
|
+
};
|
|
27503
28205
|
}
|
|
27504
28206
|
});
|
|
27505
28207
|
|
|
@@ -28134,7 +28836,7 @@ ${sections.join("\n\n")}`;
|
|
|
28134
28836
|
return "";
|
|
28135
28837
|
}
|
|
28136
28838
|
}
|
|
28137
|
-
function
|
|
28839
|
+
function adaptTool2(tool) {
|
|
28138
28840
|
return {
|
|
28139
28841
|
name: tool.name,
|
|
28140
28842
|
description: tool.description,
|
|
@@ -28836,7 +29538,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
28836
29538
|
new MemoryReadTool(this.repoRoot),
|
|
28837
29539
|
new MemorySearchTool(this.repoRoot)
|
|
28838
29540
|
];
|
|
28839
|
-
return [...tools.map(
|
|
29541
|
+
return [...tools.map(adaptTool2), taskComplete];
|
|
28840
29542
|
}
|
|
28841
29543
|
case "monitor": {
|
|
28842
29544
|
const tools = [
|
|
@@ -28846,7 +29548,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
28846
29548
|
new AutoresearchTool(this.repoRoot)
|
|
28847
29549
|
// status-only in prompt
|
|
28848
29550
|
];
|
|
28849
|
-
return [...tools.map(
|
|
29551
|
+
return [...tools.map(adaptTool2), taskComplete];
|
|
28850
29552
|
}
|
|
28851
29553
|
case "evaluator": {
|
|
28852
29554
|
const tools = [
|
|
@@ -28858,7 +29560,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
28858
29560
|
new MemoryWriteTool(this.repoRoot),
|
|
28859
29561
|
new GrepSearchTool(this.repoRoot)
|
|
28860
29562
|
];
|
|
28861
|
-
return [...tools.map(
|
|
29563
|
+
return [...tools.map(adaptTool2), taskComplete];
|
|
28862
29564
|
}
|
|
28863
29565
|
case "critic": {
|
|
28864
29566
|
const tools = [
|
|
@@ -28867,7 +29569,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
28867
29569
|
new MemorySearchTool(this.repoRoot),
|
|
28868
29570
|
new GrepSearchTool(this.repoRoot)
|
|
28869
29571
|
];
|
|
28870
|
-
return [...tools.map(
|
|
29572
|
+
return [...tools.map(adaptTool2), taskComplete];
|
|
28871
29573
|
}
|
|
28872
29574
|
case "flow_maintainer": {
|
|
28873
29575
|
const tools = [
|
|
@@ -28875,7 +29577,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
28875
29577
|
new MemoryWriteTool(this.repoRoot),
|
|
28876
29578
|
new MemorySearchTool(this.repoRoot)
|
|
28877
29579
|
];
|
|
28878
|
-
return [...tools.map(
|
|
29580
|
+
return [...tools.map(adaptTool2), taskComplete];
|
|
28879
29581
|
}
|
|
28880
29582
|
}
|
|
28881
29583
|
}
|
|
@@ -29233,7 +29935,7 @@ ${summaryResult}
|
|
|
29233
29935
|
new WebSearchTool()
|
|
29234
29936
|
];
|
|
29235
29937
|
return [
|
|
29236
|
-
...tools.map(
|
|
29938
|
+
...tools.map(adaptTool2),
|
|
29237
29939
|
this.createTaskCompleteTool()
|
|
29238
29940
|
];
|
|
29239
29941
|
}
|
|
@@ -29252,8 +29954,8 @@ ${summaryResult}
|
|
|
29252
29954
|
new DreamShellTool(this.repoRoot)
|
|
29253
29955
|
];
|
|
29254
29956
|
return [
|
|
29255
|
-
...readTools.map(
|
|
29256
|
-
...dreamWriteTools.map(
|
|
29957
|
+
...readTools.map(adaptTool2),
|
|
29958
|
+
...dreamWriteTools.map(adaptTool2),
|
|
29257
29959
|
this.createTaskCompleteTool()
|
|
29258
29960
|
];
|
|
29259
29961
|
}
|
|
@@ -29661,7 +30363,7 @@ Write consolidation insights and new reflections to memory before selecting a ta
|
|
|
29661
30363
|
The next DMN cycle (and the main agent) will benefit from anything you store now.
|
|
29662
30364
|
`;
|
|
29663
30365
|
}
|
|
29664
|
-
function
|
|
30366
|
+
function adaptTool3(tool) {
|
|
29665
30367
|
return {
|
|
29666
30368
|
name: tool.name,
|
|
29667
30369
|
description: tool.description,
|
|
@@ -29929,7 +30631,7 @@ DMN state directory: ${this.stateDir}`);
|
|
|
29929
30631
|
new WebSearchTool()
|
|
29930
30632
|
];
|
|
29931
30633
|
return [
|
|
29932
|
-
...tools.map(
|
|
30634
|
+
...tools.map(adaptTool3),
|
|
29933
30635
|
this.createTaskCompleteTool()
|
|
29934
30636
|
];
|
|
29935
30637
|
}
|
|
@@ -30204,7 +30906,7 @@ OUTPUT: Call task_complete with JSON:
|
|
|
30204
30906
|
tools.push(new MemoryWriteTool(this.repoRoot));
|
|
30205
30907
|
}
|
|
30206
30908
|
runner.registerTools([
|
|
30207
|
-
...tools.map(
|
|
30909
|
+
...tools.map(adaptTool3),
|
|
30208
30910
|
{
|
|
30209
30911
|
name: "task_complete",
|
|
30210
30912
|
description: `Signal that the ${role} analysis is complete.`,
|
|
@@ -30448,7 +31150,7 @@ function computeSparsity(entries) {
|
|
|
30448
31150
|
const avgOverlap = totalJaccard / totalPairs;
|
|
30449
31151
|
return Math.max(0, Math.min(1, 1 - avgOverlap));
|
|
30450
31152
|
}
|
|
30451
|
-
function
|
|
31153
|
+
function adaptTool4(tool) {
|
|
30452
31154
|
return {
|
|
30453
31155
|
name: tool.name,
|
|
30454
31156
|
description: tool.description,
|
|
@@ -30625,7 +31327,7 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
30625
31327
|
new MemorySearchTool(this.repoRoot)
|
|
30626
31328
|
];
|
|
30627
31329
|
runner.registerTools([
|
|
30628
|
-
...tools.map(
|
|
31330
|
+
...tools.map(adaptTool4),
|
|
30629
31331
|
{
|
|
30630
31332
|
name: "task_complete",
|
|
30631
31333
|
description: "Signal evaluation is complete with your scored results.",
|
|
@@ -31115,7 +31817,7 @@ function formatIntermediateState(event) {
|
|
|
31115
31817
|
}
|
|
31116
31818
|
return null;
|
|
31117
31819
|
}
|
|
31118
|
-
function
|
|
31820
|
+
function adaptTool5(tool) {
|
|
31119
31821
|
return {
|
|
31120
31822
|
name: tool.name,
|
|
31121
31823
|
description: tool.description,
|
|
@@ -31774,7 +32476,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
31774
32476
|
new TranscribeFileTool(repoRoot),
|
|
31775
32477
|
new TranscribeUrlTool(repoRoot)
|
|
31776
32478
|
];
|
|
31777
|
-
let adaptedTools = allTools.map(
|
|
32479
|
+
let adaptedTools = allTools.map(adaptTool5);
|
|
31778
32480
|
adaptedTools = applyToolPolicy(adaptedTools, context, this.toolPolicyConfig);
|
|
31779
32481
|
if (context !== "telegram-admin-dm") {
|
|
31780
32482
|
const memWriteIdx = adaptedTools.findIndex((t) => t.name === "memory_write");
|
|
@@ -33407,7 +34109,7 @@ function getVersion() {
|
|
|
33407
34109
|
}
|
|
33408
34110
|
return "0.0.0";
|
|
33409
34111
|
}
|
|
33410
|
-
function
|
|
34112
|
+
function adaptTool6(tool) {
|
|
33411
34113
|
return {
|
|
33412
34114
|
name: tool.name,
|
|
33413
34115
|
description: tool.description,
|
|
@@ -33505,7 +34207,7 @@ function buildTools(repoRoot, config, contextWindowSize) {
|
|
|
33505
34207
|
new AgendaTool(repoRoot)
|
|
33506
34208
|
];
|
|
33507
34209
|
return [
|
|
33508
|
-
...executionTools.map(
|
|
34210
|
+
...executionTools.map(adaptTool6),
|
|
33509
34211
|
createSubAgentTool(config, repoRoot, contextWindowSize),
|
|
33510
34212
|
createTaskCompleteTool()
|
|
33511
34213
|
];
|
|
@@ -33557,7 +34259,7 @@ function createSubAgentTool(config, repoRoot, ctxWindowSize) {
|
|
|
33557
34259
|
new MemoryReadTool(repoRoot),
|
|
33558
34260
|
new MemoryWriteTool(repoRoot)
|
|
33559
34261
|
];
|
|
33560
|
-
subRunner.registerTools(subTools.map(
|
|
34262
|
+
subRunner.registerTools(subTools.map(adaptTool6));
|
|
33561
34263
|
subRunner.registerTool(createTaskCompleteTool());
|
|
33562
34264
|
if (background) {
|
|
33563
34265
|
const promise = subRunner.run(task, `Working directory: ${repoRoot}`).then((result2) => {
|
|
@@ -33793,6 +34495,13 @@ ${entry.fullContent}`
|
|
|
33793
34495
|
filesTouched.add(event.toolArgs.path);
|
|
33794
34496
|
}
|
|
33795
34497
|
}
|
|
34498
|
+
getActivityFeed().push({
|
|
34499
|
+
ts: Date.now(),
|
|
34500
|
+
source: "main",
|
|
34501
|
+
sourceId: "main",
|
|
34502
|
+
summary: `${event.toolName ?? "unknown"}(${Object.keys(event.toolArgs ?? {}).join(", ")})`,
|
|
34503
|
+
toolName: event.toolName ?? "unknown"
|
|
34504
|
+
});
|
|
33796
34505
|
lastToolCall = { name: event.toolName ?? "unknown", args: event.toolArgs ?? {} };
|
|
33797
34506
|
statusBar?.recordSpeedToolCall(event.toolName ?? "unknown");
|
|
33798
34507
|
toolCallStartMs = Date.now();
|
|
@@ -33811,6 +34520,14 @@ ${entry.fullContent}`
|
|
|
33811
34520
|
editHistory.logToolCall(lastToolCall.name, lastToolCall.args, event.success ?? false);
|
|
33812
34521
|
lastToolCall = null;
|
|
33813
34522
|
}
|
|
34523
|
+
getActivityFeed().push({
|
|
34524
|
+
ts: Date.now(),
|
|
34525
|
+
source: "main",
|
|
34526
|
+
sourceId: "main",
|
|
34527
|
+
summary: String(event.content ?? "").slice(0, 120),
|
|
34528
|
+
toolName: event.toolName ?? "unknown",
|
|
34529
|
+
success: event.success ?? false
|
|
34530
|
+
});
|
|
33814
34531
|
const resultLen = event.content?.length ?? 0;
|
|
33815
34532
|
if (resultLen > 0) {
|
|
33816
34533
|
statusBar?.recordSpeedToolResult(event.toolName ?? "unknown", resultLen);
|
|
@@ -33922,6 +34639,7 @@ ${entry.fullContent}`
|
|
|
33922
34639
|
const systemContext = emotionContext ? `Working directory: ${repoRoot}
|
|
33923
34640
|
|
|
33924
34641
|
${emotionContext}` : `Working directory: ${repoRoot}`;
|
|
34642
|
+
resetNarrationContext();
|
|
33925
34643
|
const promise = runner.run(task, systemContext).then((result) => {
|
|
33926
34644
|
const tokens = { total: result.totalTokens, estimated: result.estimatedTokens };
|
|
33927
34645
|
contentWrite(() => {
|
|
@@ -34187,6 +34905,8 @@ async function startInteractive(config, repoPath) {
|
|
|
34187
34905
|
});
|
|
34188
34906
|
const voiceEngine = new VoiceEngine();
|
|
34189
34907
|
let voiceSession = null;
|
|
34908
|
+
let adminSessionKey = null;
|
|
34909
|
+
const callSubAgents = /* @__PURE__ */ new Map();
|
|
34190
34910
|
const streamRenderer = new StreamRenderer();
|
|
34191
34911
|
if (savedSettings.voice) {
|
|
34192
34912
|
voiceEngine.toggle().catch(() => {
|
|
@@ -34854,34 +35574,83 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
34854
35574
|
return text ? `Stopped. Last transcript: "${text}"` : "Stopped listening.";
|
|
34855
35575
|
},
|
|
34856
35576
|
// Voice call session — standalone cloudflared tunnel for /call
|
|
34857
|
-
//
|
|
35577
|
+
// Each connecting WebSocket client gets a dedicated CallSubAgent.
|
|
35578
|
+
// Admin callers (matching session key) get full tool access; public callers get read-only.
|
|
34858
35579
|
async callStart() {
|
|
34859
35580
|
if (voiceSession?.isActive) {
|
|
34860
35581
|
return voiceSession.tunnelUrl;
|
|
34861
35582
|
}
|
|
35583
|
+
if (!adminSessionKey) {
|
|
35584
|
+
adminSessionKey = generateSessionKey();
|
|
35585
|
+
}
|
|
34862
35586
|
voiceSession = new VoiceSession();
|
|
34863
|
-
const callState = {
|
|
35587
|
+
const callState = {
|
|
35588
|
+
transcribers: /* @__PURE__ */ new Map(),
|
|
35589
|
+
loading: false,
|
|
35590
|
+
sharedTranscriber: null
|
|
35591
|
+
};
|
|
34864
35592
|
const engine = getListenEngine();
|
|
34865
35593
|
voiceSession.onUserAudio = (pcmChunk, userId) => {
|
|
34866
|
-
if (callState.
|
|
34867
|
-
callState.
|
|
35594
|
+
if (callState.sharedTranscriber)
|
|
35595
|
+
callState.sharedTranscriber.write(pcmChunk);
|
|
34868
35596
|
};
|
|
34869
|
-
voiceSession.on("userConnected", (id, username) => {
|
|
35597
|
+
voiceSession.on("userConnected", (id, username, sessionKey) => {
|
|
34870
35598
|
writeContent(() => renderVoiceSessionUser("connected", username));
|
|
34871
|
-
|
|
35599
|
+
const tier = sessionKey && sessionKey === adminSessionKey ? "admin" : "public";
|
|
35600
|
+
writeContent(() => renderInfo(`Call client ${id} connected as ${tier.toUpperCase()}`));
|
|
35601
|
+
const emotionState = emotionEngine?.getState?.();
|
|
35602
|
+
const subAgent = new CallSubAgent(id, {
|
|
35603
|
+
config: currentConfig,
|
|
35604
|
+
repoRoot,
|
|
35605
|
+
tier,
|
|
35606
|
+
emotionContext: emotionState?.label ? `Current mood: ${emotionState.emoji ?? ""} ${emotionState.label}` : void 0,
|
|
35607
|
+
modelTier: getModelTier(currentConfig.model),
|
|
35608
|
+
contextWindowSize: resolvedContextWindowSize > 0 ? resolvedContextWindowSize : void 0
|
|
35609
|
+
});
|
|
35610
|
+
subAgent.on("response", (text) => {
|
|
35611
|
+
writeContent(() => renderVoiceSessionTranscript("agent", text));
|
|
35612
|
+
voiceSession?.sendTranscriptToClient(id, "agent", text);
|
|
35613
|
+
if (voiceEngine.enabled && voiceEngine.ready) {
|
|
35614
|
+
const session = voiceSession;
|
|
35615
|
+
voiceEngine.synthesizeToPCM(text).then((result) => {
|
|
35616
|
+
if (result && session?.isActive) {
|
|
35617
|
+
const { pcm, sampleRate } = result;
|
|
35618
|
+
session.sendSpeakingStateToClient(id, true);
|
|
35619
|
+
session.sendAudioToClient(id, pcm);
|
|
35620
|
+
const durationMs = pcm.length / 2 / sampleRate * 1e3;
|
|
35621
|
+
setTimeout(() => session.sendSpeakingStateToClient(id, false), durationMs);
|
|
35622
|
+
}
|
|
35623
|
+
}).catch(() => {
|
|
35624
|
+
});
|
|
35625
|
+
}
|
|
35626
|
+
});
|
|
35627
|
+
subAgent.on("error", (err) => {
|
|
35628
|
+
writeContent(() => renderWarning(`Call sub-agent error (${id}): ${err.message}`));
|
|
35629
|
+
});
|
|
35630
|
+
subAgent.init().then(() => {
|
|
35631
|
+
callSubAgents.set(id, subAgent);
|
|
35632
|
+
}).catch((err) => {
|
|
35633
|
+
writeContent(() => renderWarning(`Call sub-agent init failed (${id}): ${err instanceof Error ? err.message : String(err)}`));
|
|
35634
|
+
});
|
|
35635
|
+
if (!callState.sharedTranscriber && !callState.loading) {
|
|
34872
35636
|
callState.loading = true;
|
|
34873
35637
|
engine.createCallTranscriber().then((t) => {
|
|
34874
35638
|
if (!t || !voiceSession?.isActive)
|
|
34875
35639
|
return;
|
|
34876
|
-
callState.
|
|
34877
|
-
callState.
|
|
35640
|
+
callState.sharedTranscriber = t;
|
|
35641
|
+
callState.sharedTranscriber.on("transcript", (evt) => {
|
|
34878
35642
|
if (!evt.text?.trim() || !voiceSession?.isActive)
|
|
34879
35643
|
return;
|
|
34880
35644
|
const text = evt.text.trim();
|
|
34881
35645
|
writeContent(() => renderVoiceSessionTranscript("user", text));
|
|
34882
35646
|
voiceSession?.sendTranscript("user", text);
|
|
34883
35647
|
if (evt.isFinal) {
|
|
34884
|
-
|
|
35648
|
+
for (const [clientId, agent] of callSubAgents) {
|
|
35649
|
+
agent.handleTranscript(text);
|
|
35650
|
+
}
|
|
35651
|
+
if (callSubAgents.size === 0) {
|
|
35652
|
+
rl.write(text + "\n");
|
|
35653
|
+
}
|
|
34885
35654
|
}
|
|
34886
35655
|
});
|
|
34887
35656
|
writeContent(() => renderInfo("Call ASR ready \u2014 listening for speech"));
|
|
@@ -34892,6 +35661,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
34892
35661
|
});
|
|
34893
35662
|
voiceSession.on("userDisconnected", (id) => {
|
|
34894
35663
|
writeContent(() => renderVoiceSessionUser("disconnected", id));
|
|
35664
|
+
const subAgent = callSubAgents.get(id);
|
|
35665
|
+
if (subAgent) {
|
|
35666
|
+
subAgent.dispose();
|
|
35667
|
+
callSubAgents.delete(id);
|
|
35668
|
+
}
|
|
34895
35669
|
});
|
|
34896
35670
|
voiceSession.on("wsClose", (id, code, reason) => {
|
|
34897
35671
|
if (code > 0)
|
|
@@ -34902,15 +35676,21 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
34902
35676
|
});
|
|
34903
35677
|
voiceSession.on("idle_timeout", () => {
|
|
34904
35678
|
writeContent(() => renderWarning("Call session auto-closed (1 min idle \u2014 no users connected)"));
|
|
34905
|
-
if (callState.
|
|
34906
|
-
callState.
|
|
34907
|
-
callState.
|
|
35679
|
+
if (callState.sharedTranscriber) {
|
|
35680
|
+
callState.sharedTranscriber.stop();
|
|
35681
|
+
callState.sharedTranscriber = null;
|
|
34908
35682
|
}
|
|
35683
|
+
for (const agent of callSubAgents.values())
|
|
35684
|
+
agent.dispose();
|
|
35685
|
+
callSubAgents.clear();
|
|
34909
35686
|
voiceSession = null;
|
|
34910
35687
|
});
|
|
34911
35688
|
try {
|
|
34912
35689
|
const tunnelUrl = await voiceSession.start();
|
|
35690
|
+
const adminUrl = adminSessionKey ? `${tunnelUrl}?key=${adminSessionKey}` : tunnelUrl;
|
|
34913
35691
|
writeContent(() => renderVoiceSessionStart(tunnelUrl));
|
|
35692
|
+
writeContent(() => renderInfo(`Admin call URL (includes key): ${adminUrl}`));
|
|
35693
|
+
writeContent(() => renderInfo(`Public call URL (read-only): ${tunnelUrl}`));
|
|
34914
35694
|
if (voiceEngine.enabled && voiceEngine.ready) {
|
|
34915
35695
|
const session = voiceSession;
|
|
34916
35696
|
voiceEngine.onPCMOutput = (pcm, sampleRate) => {
|
|
@@ -34925,8 +35705,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
34925
35705
|
return tunnelUrl;
|
|
34926
35706
|
} catch (err) {
|
|
34927
35707
|
writeContent(() => renderWarning(`Voice session failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
34928
|
-
callState.
|
|
34929
|
-
|
|
35708
|
+
if (callState.sharedTranscriber) {
|
|
35709
|
+
callState.sharedTranscriber.stop();
|
|
35710
|
+
callState.sharedTranscriber = null;
|
|
35711
|
+
}
|
|
35712
|
+
for (const agent of callSubAgents.values())
|
|
35713
|
+
agent.dispose();
|
|
35714
|
+
callSubAgents.clear();
|
|
34930
35715
|
voiceSession = null;
|
|
34931
35716
|
return null;
|
|
34932
35717
|
}
|
|
@@ -34938,6 +35723,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
34938
35723
|
writeContent(() => renderVoiceSessionStop(runtime));
|
|
34939
35724
|
voiceSession = null;
|
|
34940
35725
|
voiceEngine.onPCMOutput = null;
|
|
35726
|
+
for (const agent of callSubAgents.values())
|
|
35727
|
+
agent.dispose();
|
|
35728
|
+
callSubAgents.clear();
|
|
34941
35729
|
}
|
|
34942
35730
|
},
|
|
34943
35731
|
isCallActive() {
|
|
@@ -35624,6 +36412,7 @@ var init_interactive = __esm({
|
|
|
35624
36412
|
init_dist();
|
|
35625
36413
|
init_listen();
|
|
35626
36414
|
init_voice_session();
|
|
36415
|
+
init_call_agent();
|
|
35627
36416
|
init_config();
|
|
35628
36417
|
init_updater();
|
|
35629
36418
|
init_commands();
|