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 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\n`);
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
- let count = 0;
4862
- for (const k of credStore.keys()) {
4863
- if (k.startsWith(prefix)) {
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
- const keywords = query.split(/\s+/).filter((w) => w.length > 2);
5104
- const likeClause = keywords.map(() => `content LIKE ?`).join(" OR ");
5105
- const likeParams = keywords.map((k) => `%${k}%`);
5106
- const rows = db.prepare(`
5107
- SELECT session_id, role, content, created_at
5108
- FROM conversations
5109
- WHERE ${likeClause || "1=1"}
5110
- ORDER BY created_at DESC
5111
- LIMIT ?
5112
- `).all(...likeParams, maxResults * 3);
5113
- db.close();
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 spawn6 } from "node:child_process";
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
- this.onStep("Context limit hit \u2014 compacting history\u2026");
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
- // ─── Tool execution ────────────────────────────────────────────────────────
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 = spawn6("bash", ["-c", command], {
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 spawn7 } from "node:child_process";
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 = spawn7(process.execPath, [bundlePath], {
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 spawn8 } from "node:child_process";
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 = spawn8(
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 state2 = this.activeSessions.get(sessionId);
11001
- if (!state2) return;
11002
- const adapter = this.adapters.get(state2.surface);
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
- state2.tokenBuffer += String(event.token ?? "");
11006
- if (state2.streamTimer) clearTimeout(state2.streamTimer);
11007
- state2.streamTimer = setTimeout(() => {
11008
- if (!state2.tokenBuffer) return;
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: state2.channelId,
11011
- text: state2.tokenBuffer,
10986
+ surface_channel_id: state.channelId,
10987
+ text: state.tokenBuffer,
11012
10988
  format: "markdown",
11013
10989
  is_progress: true,
11014
- thread_id: state2.threadId
10990
+ thread_id: state.threadId
11015
10991
  }).catch(() => {
11016
10992
  });
11017
10993
  }, 400);
11018
10994
  } else if (event.type === "session.completed") {
11019
- if (state2.streamTimer) {
11020
- clearTimeout(state2.streamTimer);
11021
- state2.streamTimer = null;
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: state2.channelId,
11003
+ surface_channel_id: state.channelId,
11028
11004
  text: output,
11029
11005
  format: "markdown",
11030
11006
  is_progress: false,
11031
- thread_id: state2.threadId
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 (state2.streamTimer) {
11038
- clearTimeout(state2.streamTimer);
11039
- state2.streamTimer = null;
11013
+ if (state.streamTimer) {
11014
+ clearTimeout(state.streamTimer);
11015
+ state.streamTimer = null;
11040
11016
  }
11041
11017
  adapter.send({
11042
- surface_channel_id: state2.channelId,
11018
+ surface_channel_id: state.channelId,
11043
11019
  text: `\u26A0\uFE0F ${String(event.error ?? "Task failed")}`,
11044
11020
  format: "prose",
11045
- thread_id: state2.threadId
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 state2 = this.streamingState.get(chatId);
11111
- if (msg.is_progress && state2) {
11112
- state2.accumulatedText = msg.text;
11113
- await this._editMessage(chatId, state2.workingMsgId, `\u23F3 ${this._truncate(msg.text, 3800)}`);
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 (state2) {
11116
- await this._editMessage(chatId, state2.workingMsgId, msg.text);
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 state2 = this.streamingState.get(stateKey);
11455
- if (msg.is_progress && state2) {
11430
+ const state = this.streamingState.get(stateKey);
11431
+ if (msg.is_progress && state) {
11456
11432
  try {
11457
11433
  await client["chat.update"]({
11458
- channel: state2.channelId,
11459
- ts: state2.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 (state2) {
11441
+ if (state) {
11466
11442
  try {
11467
11443
  await client["chat.update"]({
11468
- channel: state2.channelId,
11469
- ts: state2.ts,
11444
+ channel: state.channelId,
11445
+ ts: state.ts,
11470
11446
  text: msg.text,
11471
- thread_ts: state2.threadTs || void 0
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 spawn9 } from "node:child_process";
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 = spawn9(this.resolvedEngine, args, { stdio: "ignore" });
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 = spawn9(engine, args, { stdio: "ignore", detached: true });
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 spawn10 } from "node:child_process";
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 = spawn10("ffmpeg", args, { stdio: "pipe" });
12145
+ const proc = spawn9("ffmpeg", args, { stdio: "pipe" });
12170
12146
  this.ffmpegProcess = proc;
12171
12147
  proc.on("close", (code) => {
12172
12148
  this.ffmpegProcess = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0agent",
3
- "version": "1.0.83",
3
+ "version": "1.0.84",
4
4
  "description": "A persistent, learning AI agent that runs on your machine. An agent that learns.",
5
5
  "private": false,
6
6
  "license": "Apache-2.0",