0agent 1.0.83 → 1.0.84
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/bin/0agent.js +63 -1
- package/dist/daemon.mjs +100 -124
- package/package.json +1 -1
package/bin/0agent.js
CHANGED
|
@@ -307,14 +307,75 @@ async function runInit() {
|
|
|
307
307
|
], 0);
|
|
308
308
|
const seedName = seedIdx === 0 ? 'software-engineering' : null;
|
|
309
309
|
|
|
310
|
+
// ── Step 7: Chat channels ─────────────────────────────────────────────────
|
|
311
|
+
console.log('\n \x1b[1mChat channels\x1b[0m');
|
|
312
|
+
console.log(' \x1b[2mConnect messaging apps so you can chat with your agent from anywhere.\x1b[0m');
|
|
313
|
+
console.log(' \x1b[2mYou can add more later in ~/.0agent/config.yaml\x1b[0m\n');
|
|
314
|
+
|
|
315
|
+
let tgToken = '', slackBotToken = '', slackAppToken = '', slackSecret = '';
|
|
316
|
+
let waProvider = '', waAccountSid = '', waAuthToken = '', waFromNumber = '';
|
|
317
|
+
const channelChoices = [
|
|
318
|
+
'Telegram bot',
|
|
319
|
+
'Slack bot',
|
|
320
|
+
'WhatsApp (via Twilio)',
|
|
321
|
+
'Skip — set up later',
|
|
322
|
+
];
|
|
323
|
+
const channelIdx = await arrowSelect('Connect a chat channel?', channelChoices, 3);
|
|
324
|
+
|
|
325
|
+
if (channelIdx === 0) {
|
|
326
|
+
// Telegram
|
|
327
|
+
console.log('\n \x1b[2m1. Open @BotFather on Telegram\x1b[0m');
|
|
328
|
+
console.log(' \x1b[2m2. Send /newbot and follow the prompts\x1b[0m');
|
|
329
|
+
console.log(' \x1b[2m3. Copy the token below\x1b[0m\n');
|
|
330
|
+
tgToken = await arrowPassword('Telegram bot token');
|
|
331
|
+
tgToken = tgToken.trim();
|
|
332
|
+
if (tgToken) {
|
|
333
|
+
console.log(' \x1b[32m✓\x1b[0m Telegram connected. Message your bot to chat with 0agent.');
|
|
334
|
+
}
|
|
335
|
+
} else if (channelIdx === 1) {
|
|
336
|
+
// Slack
|
|
337
|
+
console.log('\n \x1b[2m1. Create a Slack app at api.slack.com/apps\x1b[0m');
|
|
338
|
+
console.log(' \x1b[2m2. Enable Socket Mode + Event Subscriptions\x1b[0m');
|
|
339
|
+
console.log(' \x1b[2m3. Add bot scopes: chat:write, app_mentions:read, im:history\x1b[0m\n');
|
|
340
|
+
slackBotToken = (await arrowPassword('Slack bot token (xoxb-...)')).trim();
|
|
341
|
+
slackAppToken = (await arrowPassword('Slack app token (xapp-...)')).trim();
|
|
342
|
+
slackSecret = (await arrowPassword('Slack signing secret')).trim();
|
|
343
|
+
if (slackBotToken && slackAppToken) {
|
|
344
|
+
console.log(' \x1b[32m✓\x1b[0m Slack connected. @mention your bot or DM it.');
|
|
345
|
+
}
|
|
346
|
+
} else if (channelIdx === 2) {
|
|
347
|
+
// WhatsApp via Twilio
|
|
348
|
+
console.log('\n \x1b[2m1. Sign up at twilio.com\x1b[0m');
|
|
349
|
+
console.log(' \x1b[2m2. Enable WhatsApp sandbox or a production number\x1b[0m\n');
|
|
350
|
+
waProvider = 'twilio';
|
|
351
|
+
waAccountSid = (await arrowInput('Twilio Account SID')).trim();
|
|
352
|
+
waAuthToken = (await arrowPassword('Twilio Auth Token')).trim();
|
|
353
|
+
waFromNumber = (await arrowInput('WhatsApp from number (whatsapp:+1...)')).trim();
|
|
354
|
+
if (waAccountSid && waAuthToken) {
|
|
355
|
+
console.log(' \x1b[32m✓\x1b[0m WhatsApp connected via Twilio.');
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Build surfaces config YAML section
|
|
360
|
+
let surfacesYaml = '';
|
|
361
|
+
if (tgToken) {
|
|
362
|
+
surfacesYaml += `\nsurfaces:\n telegram:\n token: "${tgToken}"`;
|
|
363
|
+
} else if (slackBotToken && slackAppToken) {
|
|
364
|
+
surfacesYaml += `\nsurfaces:\n slack:\n bot_token: "${slackBotToken}"\n app_token: "${slackAppToken}"\n signing_secret: "${slackSecret}"`;
|
|
365
|
+
} else if (waAccountSid && waAuthToken) {
|
|
366
|
+
surfacesYaml += `\nsurfaces:\n whatsapp:\n provider: "twilio"\n account_sid: "${waAccountSid}"\n auth_token: "${waAuthToken}"\n from_number: "${waFromNumber}"`;
|
|
367
|
+
}
|
|
368
|
+
|
|
310
369
|
// ── Summary ───────────────────────────────────────────────────────────────
|
|
370
|
+
const channelLabel = tgToken ? 'Telegram' : (slackBotToken ? 'Slack' : (waAccountSid ? 'WhatsApp' : 'none'));
|
|
311
371
|
console.log('\n \x1b[1mReady to launch\x1b[0m\n');
|
|
312
372
|
console.log(` LLM: \x1b[36m${providerKey}/${model}\x1b[0m`);
|
|
313
373
|
console.log(` API Key: ${apiKey ? '\x1b[32m✓ set\x1b[0m (' + apiKey.slice(0, 8) + '••••)' : '\x1b[33mnot set\x1b[0m'}`);
|
|
314
374
|
console.log(` Memory: ${ghToken ? `\x1b[32mgithub.com/${ghOwner}/0agent-memory\x1b[0m` : '\x1b[2mlocal only\x1b[0m'}`);
|
|
315
375
|
console.log(` Workspace: \x1b[36m${workspacePath}\x1b[0m`);
|
|
316
376
|
console.log(` Sandbox: \x1b[36m${sandboxChoice}\x1b[0m`);
|
|
317
|
-
console.log(` Seed: \x1b[36m${seedName ?? 'scratch'}\x1b[0m
|
|
377
|
+
console.log(` Seed: \x1b[36m${seedName ?? 'scratch'}\x1b[0m`);
|
|
378
|
+
console.log(` Channel: \x1b[36m${channelLabel}\x1b[0m\n`);
|
|
318
379
|
|
|
319
380
|
// Write config
|
|
320
381
|
const dbPath = resolve(AGENT_DIR, 'graph.db');
|
|
@@ -354,6 +415,7 @@ graph:
|
|
|
354
415
|
object_store_path: "${objPath}"
|
|
355
416
|
${seedName ? `\nseed: "${seedName}"` : ''}
|
|
356
417
|
${ghToken && ghOwner ? `\ngithub_memory:\n enabled: true\n token: "${ghToken}"\n owner: "${ghOwner}"\n repo: "${ghRepo}"` : ''}
|
|
418
|
+
${surfacesYaml}
|
|
357
419
|
`;
|
|
358
420
|
|
|
359
421
|
writeFileSync(CONFIG_PATH, config, 'utf8');
|
package/dist/daemon.mjs
CHANGED
|
@@ -2866,7 +2866,7 @@ var init_FileCapability = __esm({
|
|
|
2866
2866
|
const rel = String(input.path ?? ".");
|
|
2867
2867
|
const safe = resolve2(cwd, rel);
|
|
2868
2868
|
const start = Date.now();
|
|
2869
|
-
if (!safe.startsWith(cwd)) {
|
|
2869
|
+
if (!safe.startsWith(cwd + "/") && safe !== cwd) {
|
|
2870
2870
|
return { success: false, output: "Path outside working directory", duration_ms: 0 };
|
|
2871
2871
|
}
|
|
2872
2872
|
try {
|
|
@@ -4858,13 +4858,9 @@ var init_CredentialVaultCapability = __esm({
|
|
|
4858
4858
|
}
|
|
4859
4859
|
case "destroy": {
|
|
4860
4860
|
const prefix = `${sessionId}:`;
|
|
4861
|
-
|
|
4862
|
-
for (const k of credStore.
|
|
4863
|
-
|
|
4864
|
-
credStore.delete(k);
|
|
4865
|
-
count++;
|
|
4866
|
-
}
|
|
4867
|
-
}
|
|
4861
|
+
const keysToDelete = [...credStore.keys()].filter((k) => k.startsWith(prefix));
|
|
4862
|
+
for (const k of keysToDelete) credStore.delete(k);
|
|
4863
|
+
const count = keysToDelete.length;
|
|
4868
4864
|
sessionKeys.delete(sessionId);
|
|
4869
4865
|
return {
|
|
4870
4866
|
success: true,
|
|
@@ -5100,17 +5096,21 @@ var init_SessionSearchCapability = __esm({
|
|
|
5100
5096
|
try {
|
|
5101
5097
|
const Database2 = (await import("better-sqlite3")).default;
|
|
5102
5098
|
const db = new Database2(this.getDbPath());
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5099
|
+
let rows;
|
|
5100
|
+
try {
|
|
5101
|
+
const keywords = query.split(/\s+/).filter((w) => w.length > 2);
|
|
5102
|
+
const likeClause = keywords.map(() => `content LIKE ?`).join(" OR ");
|
|
5103
|
+
const likeParams = keywords.map((k) => `%${k.replace(/%/g, "\\%").replace(/_/g, "\\_")}%`);
|
|
5104
|
+
rows = db.prepare(`
|
|
5105
|
+
SELECT session_id, role, content, created_at
|
|
5106
|
+
FROM conversations
|
|
5107
|
+
WHERE ${likeClause || "1=1"}
|
|
5108
|
+
ORDER BY created_at DESC
|
|
5109
|
+
LIMIT ?
|
|
5110
|
+
`).all(...likeParams, maxResults * 3);
|
|
5111
|
+
} finally {
|
|
5112
|
+
db.close();
|
|
5113
|
+
}
|
|
5114
5114
|
if (!rows.length) {
|
|
5115
5115
|
return {
|
|
5116
5116
|
success: true,
|
|
@@ -5294,6 +5294,9 @@ ${lines.join("\n")}`,
|
|
|
5294
5294
|
import { execSync as execSync5 } from "node:child_process";
|
|
5295
5295
|
import { readFileSync as readFileSync4, existsSync as existsSync6 } from "node:fs";
|
|
5296
5296
|
import { resolve as resolve6, extname } from "node:path";
|
|
5297
|
+
function shellSafe(s) {
|
|
5298
|
+
return s.replace(/[^a-zA-Z0-9_.$ \-\/]/g, "");
|
|
5299
|
+
}
|
|
5297
5300
|
var LSPCapability;
|
|
5298
5301
|
var init_LSPCapability = __esm({
|
|
5299
5302
|
"packages/daemon/src/tools/LSPCapability.ts"() {
|
|
@@ -5364,7 +5367,7 @@ var init_LSPCapability = __esm({
|
|
|
5364
5367
|
for (const pattern of defPatterns) {
|
|
5365
5368
|
try {
|
|
5366
5369
|
const grep = execSync5(
|
|
5367
|
-
`rg -n "${pattern}" --type ts --type js "${cwd}" 2>/dev/null | head -10`,
|
|
5370
|
+
`rg -n "${shellSafe(pattern)}" --type ts --type js "${cwd}" 2>/dev/null | head -10`,
|
|
5368
5371
|
{ encoding: "utf8", timeout: 5e3 }
|
|
5369
5372
|
).trim();
|
|
5370
5373
|
if (grep) results.push(grep);
|
|
@@ -5388,7 +5391,7 @@ ${results.join("\n")}`,
|
|
|
5388
5391
|
if (!word) return { success: false, output: "No symbol at that position", duration_ms: Date.now() - start };
|
|
5389
5392
|
try {
|
|
5390
5393
|
const grep = execSync5(
|
|
5391
|
-
`rg -n "\\b${word}\\b" --type ts --type js "${cwd}" 2>/dev/null | head -20`,
|
|
5394
|
+
`rg -n "\\b${shellSafe(word)}\\b" --type ts --type js "${cwd}" 2>/dev/null | head -20`,
|
|
5392
5395
|
{ encoding: "utf8", timeout: 5e3 }
|
|
5393
5396
|
).trim();
|
|
5394
5397
|
const refCount = grep.split("\n").filter(Boolean).length;
|
|
@@ -5447,7 +5450,7 @@ ${grep || "(no symbols found)"}`,
|
|
|
5447
5450
|
if (!word) return { success: false, output: "No symbol to search for", duration_ms: 0 };
|
|
5448
5451
|
try {
|
|
5449
5452
|
const grep = execSync5(
|
|
5450
|
-
`rg -n "\\b${word}\\b" "${cwd}" 2>/dev/null | head -20`,
|
|
5453
|
+
`rg -n "\\b${shellSafe(word)}\\b" "${cwd}" 2>/dev/null | head -20`,
|
|
5451
5454
|
{ encoding: "utf8", timeout: 5e3 }
|
|
5452
5455
|
).trim();
|
|
5453
5456
|
return {
|
|
@@ -5992,7 +5995,7 @@ var init_StreamingToolExecutor = __esm({
|
|
|
5992
5995
|
});
|
|
5993
5996
|
|
|
5994
5997
|
// packages/daemon/src/AgentExecutor.ts
|
|
5995
|
-
import { spawn as
|
|
5998
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
5996
5999
|
import { writeFileSync as writeFileSync4, readFileSync as readFileSync5, readdirSync as readdirSync2, mkdirSync as mkdirSync3, existsSync as existsSync7 } from "node:fs";
|
|
5997
6000
|
import { resolve as resolve7, dirname as dirname2, relative } from "node:path";
|
|
5998
6001
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -6118,8 +6121,9 @@ var init_AgentExecutor = __esm({
|
|
|
6118
6121
|
await new Promise((r) => setTimeout(r, waitMs));
|
|
6119
6122
|
continue;
|
|
6120
6123
|
}
|
|
6121
|
-
if (this._isContextOverflow(msg) && messages.length > 3) {
|
|
6122
|
-
|
|
6124
|
+
if (this._isContextOverflow(msg) && messages.length > 3 && llmRetry < 2) {
|
|
6125
|
+
llmRetry++;
|
|
6126
|
+
this.onStep(`Context limit hit \u2014 compacting history (attempt ${llmRetry}/2)\u2026`);
|
|
6123
6127
|
this._compactHistory(messages);
|
|
6124
6128
|
continue;
|
|
6125
6129
|
}
|
|
@@ -6197,40 +6201,11 @@ var init_AgentExecutor = __esm({
|
|
|
6197
6201
|
iterations: messages.filter((m) => m.role === "assistant").length
|
|
6198
6202
|
};
|
|
6199
6203
|
}
|
|
6200
|
-
// ───
|
|
6201
|
-
async executeTool(name, input) {
|
|
6202
|
-
switch (name) {
|
|
6203
|
-
case "shell_exec":
|
|
6204
|
-
return this.shellExec(
|
|
6205
|
-
String(input.command ?? ""),
|
|
6206
|
-
Number(input.timeout_ms ?? this.maxCommandMs)
|
|
6207
|
-
);
|
|
6208
|
-
case "write_file":
|
|
6209
|
-
return this.writeFile(String(input.path ?? ""), String(input.content ?? ""));
|
|
6210
|
-
case "read_file":
|
|
6211
|
-
return this.readFile(String(input.path ?? ""));
|
|
6212
|
-
case "list_dir":
|
|
6213
|
-
return this.listDir(input.path ? String(input.path) : void 0);
|
|
6214
|
-
case "web_search":
|
|
6215
|
-
return this.webSearch(
|
|
6216
|
-
String(input.query ?? ""),
|
|
6217
|
-
Math.min(10, Number(input.num_results ?? 5))
|
|
6218
|
-
);
|
|
6219
|
-
case "scrape_url":
|
|
6220
|
-
return this.scrapeUrl(
|
|
6221
|
-
String(input.url ?? ""),
|
|
6222
|
-
String(input.mode ?? "text"),
|
|
6223
|
-
input.selector ? String(input.selector) : void 0,
|
|
6224
|
-
Number(input.wait_ms ?? 0)
|
|
6225
|
-
);
|
|
6226
|
-
default:
|
|
6227
|
-
return `Unknown tool: ${name}`;
|
|
6228
|
-
}
|
|
6229
|
-
}
|
|
6204
|
+
// ─── Legacy tool execution (used by built-in tools, not capabilities) ──────
|
|
6230
6205
|
shellExec(command, timeoutMs) {
|
|
6231
6206
|
return new Promise((resolve19) => {
|
|
6232
6207
|
const chunks = [];
|
|
6233
|
-
const proc =
|
|
6208
|
+
const proc = spawn5("bash", ["-c", command], {
|
|
6234
6209
|
cwd: this.cwd,
|
|
6235
6210
|
env: { ...process.env, TERM: "dumb" },
|
|
6236
6211
|
timeout: timeoutMs
|
|
@@ -6360,7 +6335,7 @@ content = element.text if element else page.get_all_text()` : `content = page.ge
|
|
|
6360
6335
|
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
6361
6336
|
safePath(p) {
|
|
6362
6337
|
const resolved = resolve7(this.cwd, p);
|
|
6363
|
-
return resolved.startsWith(this.cwd) ? resolved : null;
|
|
6338
|
+
return resolved.startsWith(this.cwd + "/") || resolved === this.cwd ? resolved : null;
|
|
6364
6339
|
}
|
|
6365
6340
|
buildSystemPrompt(extra, task) {
|
|
6366
6341
|
const isSelfMod = !!(task && SELF_MOD_PATTERN.test(task));
|
|
@@ -6764,7 +6739,7 @@ var init_ExecutionVerifier = __esm({
|
|
|
6764
6739
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync10 } from "node:fs";
|
|
6765
6740
|
import { resolve as resolve9, dirname as dirname3 } from "node:path";
|
|
6766
6741
|
import { fileURLToPath } from "node:url";
|
|
6767
|
-
import { execSync as execSync7, spawn as
|
|
6742
|
+
import { execSync as execSync7, spawn as spawn6 } from "node:child_process";
|
|
6768
6743
|
function isRuntimeBug(error) {
|
|
6769
6744
|
if (TASK_FAILURE_PATTERNS.some((p) => p.test(error))) return false;
|
|
6770
6745
|
return RUNTIME_BUG_PATTERNS.some((p) => p.test(error));
|
|
@@ -6999,7 +6974,7 @@ Rules:
|
|
|
6999
6974
|
restartDaemon() {
|
|
7000
6975
|
const bundlePath = resolve9(this.projectRoot, "dist", "daemon.mjs");
|
|
7001
6976
|
if (existsSync10(bundlePath)) {
|
|
7002
|
-
const child =
|
|
6977
|
+
const child = spawn6(process.execPath, [bundlePath], {
|
|
7003
6978
|
detached: true,
|
|
7004
6979
|
stdio: "ignore",
|
|
7005
6980
|
env: process.env
|
|
@@ -7920,12 +7895,6 @@ function getFastModelId(provider, _currentModel) {
|
|
|
7920
7895
|
|
|
7921
7896
|
// packages/daemon/src/services/AutoMemoryExtractor.ts
|
|
7922
7897
|
init_src();
|
|
7923
|
-
var state = {
|
|
7924
|
-
lastMessageIndex: 0,
|
|
7925
|
-
inProgress: false,
|
|
7926
|
-
pendingRun: false,
|
|
7927
|
-
turnsSinceExtraction: 0
|
|
7928
|
-
};
|
|
7929
7898
|
var MIN_TURNS_BETWEEN = 3;
|
|
7930
7899
|
var MAX_MESSAGES_PER_RUN = 20;
|
|
7931
7900
|
var AutoMemoryExtractor = class {
|
|
@@ -7934,6 +7903,13 @@ var AutoMemoryExtractor = class {
|
|
|
7934
7903
|
this.graph = graph;
|
|
7935
7904
|
this.entityNodeId = entityNodeId;
|
|
7936
7905
|
}
|
|
7906
|
+
// Instance-scoped state (not module-level — prevents cross-session contamination)
|
|
7907
|
+
state = {
|
|
7908
|
+
lastMessageIndex: 0,
|
|
7909
|
+
inProgress: false,
|
|
7910
|
+
pendingRun: false,
|
|
7911
|
+
turnsSinceExtraction: 0
|
|
7912
|
+
};
|
|
7937
7913
|
/**
|
|
7938
7914
|
* Called after each session turn. Decides whether to extract memories
|
|
7939
7915
|
* and runs extraction in the background if needed.
|
|
@@ -7941,30 +7917,30 @@ var AutoMemoryExtractor = class {
|
|
|
7941
7917
|
* Fire-and-forget — never blocks the main session.
|
|
7942
7918
|
*/
|
|
7943
7919
|
async maybeExtract(messages, memoryWritesSinceLast) {
|
|
7944
|
-
state.turnsSinceExtraction++;
|
|
7920
|
+
this.state.turnsSinceExtraction++;
|
|
7945
7921
|
if (memoryWritesSinceLast) {
|
|
7946
|
-
state.turnsSinceExtraction = 0;
|
|
7922
|
+
this.state.turnsSinceExtraction = 0;
|
|
7947
7923
|
return;
|
|
7948
7924
|
}
|
|
7949
|
-
if (state.turnsSinceExtraction < MIN_TURNS_BETWEEN) return;
|
|
7950
|
-
if (messages.length <= state.lastMessageIndex) return;
|
|
7951
|
-
if (state.inProgress) {
|
|
7952
|
-
state.pendingRun = true;
|
|
7925
|
+
if (this.state.turnsSinceExtraction < MIN_TURNS_BETWEEN) return;
|
|
7926
|
+
if (messages.length <= this.state.lastMessageIndex) return;
|
|
7927
|
+
if (this.state.inProgress) {
|
|
7928
|
+
this.state.pendingRun = true;
|
|
7953
7929
|
return;
|
|
7954
7930
|
}
|
|
7955
7931
|
await this._runExtraction(messages);
|
|
7956
|
-
if (state.pendingRun) {
|
|
7957
|
-
state.pendingRun = false;
|
|
7932
|
+
if (this.state.pendingRun) {
|
|
7933
|
+
this.state.pendingRun = false;
|
|
7958
7934
|
await this._runExtraction(messages);
|
|
7959
7935
|
}
|
|
7960
7936
|
}
|
|
7961
7937
|
async _runExtraction(messages) {
|
|
7962
7938
|
if (!this.llm?.isConfigured) return;
|
|
7963
|
-
state.inProgress = true;
|
|
7939
|
+
this.state.inProgress = true;
|
|
7964
7940
|
try {
|
|
7965
7941
|
const newMessages = messages.slice(
|
|
7966
|
-
state.lastMessageIndex,
|
|
7967
|
-
state.lastMessageIndex + MAX_MESSAGES_PER_RUN
|
|
7942
|
+
this.state.lastMessageIndex,
|
|
7943
|
+
this.state.lastMessageIndex + MAX_MESSAGES_PER_RUN
|
|
7968
7944
|
);
|
|
7969
7945
|
if (newMessages.length === 0) return;
|
|
7970
7946
|
const conversationText = newMessages.filter((m) => m.role === "user" || m.role === "assistant" && !m.tool_calls).map((m) => `${m.role}: ${m.content.slice(0, 500)}`).join("\n");
|
|
@@ -8023,19 +7999,19 @@ var AutoMemoryExtractor = class {
|
|
|
8023
7999
|
this.graph.addNode(node);
|
|
8024
8000
|
}
|
|
8025
8001
|
}
|
|
8026
|
-
state.lastMessageIndex = messages.length;
|
|
8027
|
-
state.turnsSinceExtraction = 0;
|
|
8002
|
+
this.state.lastMessageIndex = messages.length;
|
|
8003
|
+
this.state.turnsSinceExtraction = 0;
|
|
8028
8004
|
} catch {
|
|
8029
8005
|
} finally {
|
|
8030
|
-
state.inProgress = false;
|
|
8006
|
+
this.state.inProgress = false;
|
|
8031
8007
|
}
|
|
8032
8008
|
}
|
|
8033
8009
|
/** Reset state (e.g., on new session). */
|
|
8034
8010
|
reset() {
|
|
8035
|
-
state.lastMessageIndex = 0;
|
|
8036
|
-
state.inProgress = false;
|
|
8037
|
-
state.pendingRun = false;
|
|
8038
|
-
state.turnsSinceExtraction = 0;
|
|
8011
|
+
this.state.lastMessageIndex = 0;
|
|
8012
|
+
this.state.inProgress = false;
|
|
8013
|
+
this.state.pendingRun = false;
|
|
8014
|
+
this.state.turnsSinceExtraction = 0;
|
|
8039
8015
|
}
|
|
8040
8016
|
};
|
|
8041
8017
|
|
|
@@ -10513,7 +10489,7 @@ git checkout <commit> graph/ # restore graph files
|
|
|
10513
10489
|
};
|
|
10514
10490
|
|
|
10515
10491
|
// packages/daemon/src/services/CodespaceManager.ts
|
|
10516
|
-
import { execSync as execSync8, spawn as
|
|
10492
|
+
import { execSync as execSync8, spawn as spawn7 } from "node:child_process";
|
|
10517
10493
|
var BROWSER_PORT_REMOTE = 3e3;
|
|
10518
10494
|
var BROWSER_PORT_LOCAL = 3001;
|
|
10519
10495
|
var DISPLAY_NAME = "0agent-browser";
|
|
@@ -10608,7 +10584,7 @@ var CodespaceManager = class {
|
|
|
10608
10584
|
async openTunnel(name) {
|
|
10609
10585
|
this.closeTunnel();
|
|
10610
10586
|
console.log(`[Codespace] Opening tunnel port ${BROWSER_PORT_REMOTE} \u2192 localhost:${BROWSER_PORT_LOCAL}...`);
|
|
10611
|
-
this.forwardProcess =
|
|
10587
|
+
this.forwardProcess = spawn7(
|
|
10612
10588
|
"gh",
|
|
10613
10589
|
["codespace", "ports", "forward", `${BROWSER_PORT_REMOTE}:${BROWSER_PORT_LOCAL}`, "--codespace", name],
|
|
10614
10590
|
{ stdio: ["ignore", "ignore", "ignore"] }
|
|
@@ -10997,52 +10973,52 @@ var SurfaceRouter = class {
|
|
|
10997
10973
|
}
|
|
10998
10974
|
_handleDaemonEvent(event) {
|
|
10999
10975
|
const sessionId = String(event.session_id ?? "");
|
|
11000
|
-
const
|
|
11001
|
-
if (!
|
|
11002
|
-
const adapter = this.adapters.get(
|
|
10976
|
+
const state = this.activeSessions.get(sessionId);
|
|
10977
|
+
if (!state) return;
|
|
10978
|
+
const adapter = this.adapters.get(state.surface);
|
|
11003
10979
|
if (!adapter) return;
|
|
11004
10980
|
if (event.type === "session.token") {
|
|
11005
|
-
|
|
11006
|
-
if (
|
|
11007
|
-
|
|
11008
|
-
if (!
|
|
10981
|
+
state.tokenBuffer += String(event.token ?? "");
|
|
10982
|
+
if (state.streamTimer) clearTimeout(state.streamTimer);
|
|
10983
|
+
state.streamTimer = setTimeout(() => {
|
|
10984
|
+
if (!state.tokenBuffer) return;
|
|
11009
10985
|
adapter.send({
|
|
11010
|
-
surface_channel_id:
|
|
11011
|
-
text:
|
|
10986
|
+
surface_channel_id: state.channelId,
|
|
10987
|
+
text: state.tokenBuffer,
|
|
11012
10988
|
format: "markdown",
|
|
11013
10989
|
is_progress: true,
|
|
11014
|
-
thread_id:
|
|
10990
|
+
thread_id: state.threadId
|
|
11015
10991
|
}).catch(() => {
|
|
11016
10992
|
});
|
|
11017
10993
|
}, 400);
|
|
11018
10994
|
} else if (event.type === "session.completed") {
|
|
11019
|
-
if (
|
|
11020
|
-
clearTimeout(
|
|
11021
|
-
|
|
10995
|
+
if (state.streamTimer) {
|
|
10996
|
+
clearTimeout(state.streamTimer);
|
|
10997
|
+
state.streamTimer = null;
|
|
11022
10998
|
}
|
|
11023
10999
|
const result = event.result;
|
|
11024
11000
|
const output = String(result?.output ?? "").trim();
|
|
11025
11001
|
if (output && output !== "(no output)") {
|
|
11026
11002
|
adapter.send({
|
|
11027
|
-
surface_channel_id:
|
|
11003
|
+
surface_channel_id: state.channelId,
|
|
11028
11004
|
text: output,
|
|
11029
11005
|
format: "markdown",
|
|
11030
11006
|
is_progress: false,
|
|
11031
|
-
thread_id:
|
|
11007
|
+
thread_id: state.threadId
|
|
11032
11008
|
}).catch(() => {
|
|
11033
11009
|
});
|
|
11034
11010
|
}
|
|
11035
11011
|
this.activeSessions.delete(sessionId);
|
|
11036
11012
|
} else if (event.type === "session.failed") {
|
|
11037
|
-
if (
|
|
11038
|
-
clearTimeout(
|
|
11039
|
-
|
|
11013
|
+
if (state.streamTimer) {
|
|
11014
|
+
clearTimeout(state.streamTimer);
|
|
11015
|
+
state.streamTimer = null;
|
|
11040
11016
|
}
|
|
11041
11017
|
adapter.send({
|
|
11042
|
-
surface_channel_id:
|
|
11018
|
+
surface_channel_id: state.channelId,
|
|
11043
11019
|
text: `\u26A0\uFE0F ${String(event.error ?? "Task failed")}`,
|
|
11044
11020
|
format: "prose",
|
|
11045
|
-
thread_id:
|
|
11021
|
+
thread_id: state.threadId
|
|
11046
11022
|
}).catch(() => {
|
|
11047
11023
|
});
|
|
11048
11024
|
this.activeSessions.delete(sessionId);
|
|
@@ -11107,13 +11083,13 @@ var TelegramAdapter = class {
|
|
|
11107
11083
|
async send(msg) {
|
|
11108
11084
|
const chatId = Number(msg.surface_channel_id);
|
|
11109
11085
|
if (!chatId) return;
|
|
11110
|
-
const
|
|
11111
|
-
if (msg.is_progress &&
|
|
11112
|
-
|
|
11113
|
-
await this._editMessage(chatId,
|
|
11086
|
+
const state = this.streamingState.get(chatId);
|
|
11087
|
+
if (msg.is_progress && state) {
|
|
11088
|
+
state.accumulatedText = msg.text;
|
|
11089
|
+
await this._editMessage(chatId, state.workingMsgId, `\u23F3 ${this._truncate(msg.text, 3800)}`);
|
|
11114
11090
|
} else {
|
|
11115
|
-
if (
|
|
11116
|
-
await this._editMessage(chatId,
|
|
11091
|
+
if (state) {
|
|
11092
|
+
await this._editMessage(chatId, state.workingMsgId, msg.text);
|
|
11117
11093
|
this.streamingState.delete(chatId);
|
|
11118
11094
|
} else {
|
|
11119
11095
|
await this._sendMessage(chatId, msg.text);
|
|
@@ -11451,24 +11427,24 @@ var SlackAdapter = class {
|
|
|
11451
11427
|
if (!this.app) return;
|
|
11452
11428
|
const client = this.app["client"];
|
|
11453
11429
|
const stateKey = `${msg.surface_channel_id}:${msg.thread_id ?? ""}`;
|
|
11454
|
-
const
|
|
11455
|
-
if (msg.is_progress &&
|
|
11430
|
+
const state = this.streamingState.get(stateKey);
|
|
11431
|
+
if (msg.is_progress && state) {
|
|
11456
11432
|
try {
|
|
11457
11433
|
await client["chat.update"]({
|
|
11458
|
-
channel:
|
|
11459
|
-
ts:
|
|
11434
|
+
channel: state.channelId,
|
|
11435
|
+
ts: state.ts,
|
|
11460
11436
|
text: `\u23F3 ${this._truncate(msg.text, 3e3)}`
|
|
11461
11437
|
});
|
|
11462
11438
|
} catch {
|
|
11463
11439
|
}
|
|
11464
11440
|
} else {
|
|
11465
|
-
if (
|
|
11441
|
+
if (state) {
|
|
11466
11442
|
try {
|
|
11467
11443
|
await client["chat.update"]({
|
|
11468
|
-
channel:
|
|
11469
|
-
ts:
|
|
11444
|
+
channel: state.channelId,
|
|
11445
|
+
ts: state.ts,
|
|
11470
11446
|
text: msg.text,
|
|
11471
|
-
thread_ts:
|
|
11447
|
+
thread_ts: state.threadTs || void 0
|
|
11472
11448
|
});
|
|
11473
11449
|
} catch {
|
|
11474
11450
|
await this._postMessage(client, msg.surface_channel_id, msg.text, msg.thread_id);
|
|
@@ -11810,7 +11786,7 @@ async function recordAudio(durationSeconds) {
|
|
|
11810
11786
|
}
|
|
11811
11787
|
|
|
11812
11788
|
// packages/daemon/src/surfaces/NativeTTS.ts
|
|
11813
|
-
import { spawnSync as spawnSync6, spawn as
|
|
11789
|
+
import { spawnSync as spawnSync6, spawn as spawn8 } from "node:child_process";
|
|
11814
11790
|
var NativeTTS = class _NativeTTS {
|
|
11815
11791
|
engine;
|
|
11816
11792
|
voice;
|
|
@@ -11836,7 +11812,7 @@ var NativeTTS = class _NativeTTS {
|
|
|
11836
11812
|
if (!cleaned) return;
|
|
11837
11813
|
return new Promise((resolve19) => {
|
|
11838
11814
|
const args = this._buildArgs(this.resolvedEngine, cleaned);
|
|
11839
|
-
const proc =
|
|
11815
|
+
const proc = spawn8(this.resolvedEngine, args, { stdio: "ignore" });
|
|
11840
11816
|
proc.on("close", () => resolve19());
|
|
11841
11817
|
proc.on("error", () => resolve19());
|
|
11842
11818
|
});
|
|
@@ -11896,7 +11872,7 @@ var NativeTTS = class _NativeTTS {
|
|
|
11896
11872
|
}
|
|
11897
11873
|
_speakWith(engine, text) {
|
|
11898
11874
|
const args = this._buildArgs(engine, text);
|
|
11899
|
-
const proc =
|
|
11875
|
+
const proc = spawn8(engine, args, { stdio: "ignore", detached: true });
|
|
11900
11876
|
proc.unref();
|
|
11901
11877
|
}
|
|
11902
11878
|
/** Remove markdown/ANSI and control chars before speaking */
|
|
@@ -12024,7 +12000,7 @@ var VoiceAdapter = class {
|
|
|
12024
12000
|
import { existsSync as existsSync19, mkdirSync as mkdirSync9, writeFileSync as writeFileSync11 } from "node:fs";
|
|
12025
12001
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
12026
12002
|
import { join as join6 } from "node:path";
|
|
12027
|
-
import { spawn as
|
|
12003
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
12028
12004
|
var MeetingAdapter = class {
|
|
12029
12005
|
name = "meeting";
|
|
12030
12006
|
messageHandler = null;
|
|
@@ -12166,7 +12142,7 @@ ${msg.text}
|
|
|
12166
12142
|
resolve19(false);
|
|
12167
12143
|
return;
|
|
12168
12144
|
}
|
|
12169
|
-
const proc =
|
|
12145
|
+
const proc = spawn9("ffmpeg", args, { stdio: "pipe" });
|
|
12170
12146
|
this.ffmpegProcess = proc;
|
|
12171
12147
|
proc.on("close", (code) => {
|
|
12172
12148
|
this.ffmpegProcess = null;
|