open-agents-ai 0.187.440 → 0.187.442

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 CHANGED
@@ -526120,6 +526120,8 @@ var init_listen = __esm({
526120
526120
  liveTranscriber = null;
526121
526121
  // TranscribeLive from transcribe-cli or WhisperFallbackTranscriber
526122
526122
  active = false;
526123
+ paused = false;
526124
+ // Pause state for voicechat (stops mic but keeps transcriber)
526123
526125
  silenceTimer = null;
526124
526126
  countdownInterval = null;
526125
526127
  lastTranscriptTime = 0;
@@ -526141,6 +526143,9 @@ var init_listen = __esm({
526141
526143
  get isBlinking() {
526142
526144
  return this.active && this.blinkState;
526143
526145
  }
526146
+ get isPaused() {
526147
+ return this.paused;
526148
+ }
526144
526149
  get currentModel() {
526145
526150
  return this.config.model;
526146
526151
  }
@@ -526367,7 +526372,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
526367
526372
  env: { ...process.env }
526368
526373
  });
526369
526374
  this.micProcess.stdout?.on("data", (chunk) => {
526370
- if (this.active && this.liveTranscriber) {
526375
+ if (this.active && !this.paused && this.liveTranscriber) {
526371
526376
  this.liveTranscriber.write(chunk);
526372
526377
  }
526373
526378
  });
@@ -526443,6 +526448,67 @@ transcribe-cli error: ${transcribeCliError}` : "";
526443
526448
  this.pendingText = "";
526444
526449
  return text;
526445
526450
  }
526451
+ /**
526452
+ * Pause microphone capture (for voicechat during TTS output).
526453
+ * Keeps transcriber alive but stops feeding it audio.
526454
+ */
526455
+ pause() {
526456
+ if (!this.active || this.paused) return;
526457
+ this.paused = true;
526458
+ if (this.blinkTimer) {
526459
+ clearInterval(this.blinkTimer);
526460
+ this.blinkTimer = null;
526461
+ }
526462
+ this.blinkState = false;
526463
+ if (this.micProcess) {
526464
+ try {
526465
+ this.micProcess.kill("SIGTERM");
526466
+ } catch {
526467
+ }
526468
+ this.micProcess = null;
526469
+ }
526470
+ this.emit("paused");
526471
+ this.emit("recording", false);
526472
+ }
526473
+ /**
526474
+ * Resume microphone capture after pause.
526475
+ */
526476
+ async resume() {
526477
+ if (!this.active || !this.paused) return "Not paused.";
526478
+ this.paused = false;
526479
+ const micCmd = findMicCaptureCommand();
526480
+ if (!micCmd) {
526481
+ return "No microphone capture tool found.";
526482
+ }
526483
+ this.micProcess = spawn18(micCmd.cmd, micCmd.args, {
526484
+ stdio: ["pipe", "pipe", "pipe"],
526485
+ env: { ...process.env }
526486
+ });
526487
+ this.micProcess.stdout?.on("data", (chunk) => {
526488
+ if (this.active && !this.paused && this.liveTranscriber) {
526489
+ this.liveTranscriber.write(chunk);
526490
+ }
526491
+ });
526492
+ this.micProcess.stderr?.on("data", () => {
526493
+ });
526494
+ onChildError(this.micProcess, (err) => {
526495
+ this.emit("error", new Error(`Mic capture failed: ${err.message}`));
526496
+ this.stop();
526497
+ });
526498
+ onChildClose(this.micProcess, () => {
526499
+ if (this.active && !this.paused) {
526500
+ this.stop();
526501
+ }
526502
+ });
526503
+ this.blinkState = true;
526504
+ this.blinkTimer = setInterval(() => {
526505
+ this.blinkState = !this.blinkState;
526506
+ this.emit("recording", this.blinkState);
526507
+ }, 500);
526508
+ this.emit("resumed");
526509
+ this.emit("recording", true);
526510
+ return "Resumed listening.";
526511
+ }
526446
526512
  /**
526447
526513
  * Create a standalone transcriber for call sessions.
526448
526514
  * No microphone capture — just an ASR engine you feed PCM chunks to.
@@ -531118,7 +531184,9 @@ var oa_directory_exports = {};
531118
531184
  __export(oa_directory_exports, {
531119
531185
  OA_DIR: () => OA_DIR,
531120
531186
  buildContextRestorePrompt: () => buildContextRestorePrompt,
531187
+ buildHandoffPrompt: () => buildHandoffPrompt,
531121
531188
  cleanPromptForDiary: () => cleanPromptForDiary,
531189
+ clearTaskHandoff: () => clearTaskHandoff,
531122
531190
  deleteSession: () => deleteSession,
531123
531191
  deleteUsageRecord: () => deleteUsageRecord,
531124
531192
  discoverContextFiles: () => discoverContextFiles,
@@ -531136,6 +531204,7 @@ __export(oa_directory_exports, {
531136
531204
  loadUsageHistory: () => loadUsageHistory,
531137
531205
  readIndexData: () => readIndexData,
531138
531206
  readIndexMeta: () => readIndexMeta,
531207
+ readTaskHandoff: () => readTaskHandoff,
531139
531208
  recordUsage: () => recordUsage,
531140
531209
  renderSessionDiary: () => renderSessionDiary,
531141
531210
  resolveSettings: () => resolveSettings,
@@ -531146,7 +531215,8 @@ __export(oa_directory_exports, {
531146
531215
  saveSessionContext: () => saveSessionContext,
531147
531216
  saveSessionHistory: () => saveSessionHistory,
531148
531217
  writeIndexData: () => writeIndexData,
531149
- writeIndexMeta: () => writeIndexMeta
531218
+ writeIndexMeta: () => writeIndexMeta,
531219
+ writeTaskHandoff: () => writeTaskHandoff
531150
531220
  });
531151
531221
  import { existsSync as existsSync59, mkdirSync as mkdirSync34, readFileSync as readFileSync46, writeFileSync as writeFileSync31, readdirSync as readdirSync15, statSync as statSync17, unlinkSync as unlinkSync14, openSync as openSync2, closeSync as closeSync2, renameSync as renameSync3 } from "node:fs";
531152
531222
  import { join as join77, relative as relative6, basename as basename13, dirname as dirname22 } from "node:path";
@@ -531430,6 +531500,91 @@ function loadPendingTask(repoRoot) {
531430
531500
  return null;
531431
531501
  }
531432
531502
  }
531503
+ function writeTaskHandoff(repoRoot, handoff) {
531504
+ const contextDir = join77(repoRoot, OA_DIR, "context");
531505
+ mkdirSync34(contextDir, { recursive: true });
531506
+ const filePath = join77(contextDir, HANDOFF_FILE);
531507
+ const tempPath = filePath + ".tmp";
531508
+ writeFileSync31(tempPath, JSON.stringify(handoff, null, 2) + "\n", "utf-8");
531509
+ try {
531510
+ renameSync3(tempPath, filePath);
531511
+ } catch {
531512
+ writeFileSync31(filePath, JSON.stringify(handoff, null, 2) + "\n", "utf-8");
531513
+ try {
531514
+ unlinkSync14(tempPath);
531515
+ } catch {
531516
+ }
531517
+ }
531518
+ }
531519
+ function readTaskHandoff(repoRoot) {
531520
+ const filePath = join77(repoRoot, OA_DIR, "context", HANDOFF_FILE);
531521
+ try {
531522
+ if (!existsSync59(filePath)) return null;
531523
+ const data = JSON.parse(readFileSync46(filePath, "utf-8"));
531524
+ const handoffTime = new Date(data.handoffAt).getTime();
531525
+ const now = Date.now();
531526
+ const ageMs = now - handoffTime;
531527
+ const maxAgeMs = 24 * 60 * 60 * 1e3;
531528
+ if (ageMs > maxAgeMs) {
531529
+ return null;
531530
+ }
531531
+ return data;
531532
+ } catch {
531533
+ return null;
531534
+ }
531535
+ }
531536
+ function clearTaskHandoff(repoRoot) {
531537
+ const filePath = join77(repoRoot, OA_DIR, "context", HANDOFF_FILE);
531538
+ try {
531539
+ if (existsSync59(filePath)) {
531540
+ unlinkSync14(filePath);
531541
+ }
531542
+ } catch {
531543
+ }
531544
+ }
531545
+ function buildHandoffPrompt(repoRoot) {
531546
+ const handoff = readTaskHandoff(repoRoot);
531547
+ if (!handoff || !handoff.eligible) return null;
531548
+ const lines = ["<task-handoff>", ""];
531549
+ lines.push(`## Previous Task: ${handoff.base.task.slice(0, 100)}...`);
531550
+ lines.push("");
531551
+ if (handoff.accomplishments.length > 0) {
531552
+ lines.push("### Accomplished:");
531553
+ for (const a2 of handoff.accomplishments.slice(0, 5)) {
531554
+ lines.push(`- ${a2}`);
531555
+ }
531556
+ lines.push("");
531557
+ }
531558
+ if (handoff.files.length > 0) {
531559
+ lines.push("### Files Modified:");
531560
+ for (const f2 of handoff.files.slice(0, 5)) {
531561
+ const op = f2.operation;
531562
+ const anchors = f2.anchors?.length ? ` (${f2.anchors.slice(0, 3).join(", ")})` : "";
531563
+ lines.push(`- [${op}] ${f2.path}${anchors}`);
531564
+ }
531565
+ lines.push("");
531566
+ }
531567
+ if (handoff.findings.length > 0) {
531568
+ lines.push("### Critical Findings:");
531569
+ for (const f2 of handoff.findings.slice(0, 5)) {
531570
+ lines.push(`- ${f2}`);
531571
+ }
531572
+ lines.push("");
531573
+ }
531574
+ if (handoff.memories.length > 0) {
531575
+ lines.push("### Memories Used:");
531576
+ for (const m2 of handoff.memories.slice(0, 3)) {
531577
+ lines.push(`- [${m2.topic}/${m2.key}]: ${m2.relevance}`);
531578
+ }
531579
+ lines.push("");
531580
+ }
531581
+ lines.push("### Validation:");
531582
+ lines.push(`- Tests: ${handoff.validation.testsRan ? handoff.validation.testsPassed ? "✓ passed" : "✗ failed" : "not run"}`);
531583
+ lines.push(`- Build: ${handoff.validation.buildSucceeded ? "✓ succeeded" : "✗ failed"}`);
531584
+ lines.push("");
531585
+ lines.push("</task-handoff>");
531586
+ return lines.join("\n");
531587
+ }
531433
531588
  function computeDedupeHash(task, savedAt) {
531434
531589
  return createHash8("sha256").update(`${task}|${savedAt}`).digest("hex").slice(0, 16);
531435
531590
  }
@@ -531716,6 +531871,17 @@ function loadSessionContext(repoRoot) {
531716
531871
  }
531717
531872
  function buildContextRestorePrompt(repoRoot) {
531718
531873
  const ctx3 = loadSessionContext(repoRoot);
531874
+ const handoffPrompt = buildHandoffPrompt(repoRoot);
531875
+ if (handoffPrompt) {
531876
+ const baseCtx = ctx3 && ctx3.entries.length > 0 ? `
531877
+
531878
+ <session-recap>
531879
+ Recent tasks: ${ctx3.entries.slice(-3).map(
531880
+ (e2) => `[${e2.completed ? "done" : "partial"}] ${normalizeSessionText(e2.summary || e2.task, 80)}`
531881
+ ).join(", ")}
531882
+ </session-recap>` : "";
531883
+ return handoffPrompt + baseCtx;
531884
+ }
531719
531885
  if (!ctx3 || ctx3.entries.length === 0) return null;
531720
531886
  const recent = ctx3.entries.slice(-5);
531721
531887
  const chronology = recent.map((e2) => {
@@ -532032,7 +532198,7 @@ function deleteUsageRecord(kind, value2, repoRoot) {
532032
532198
  remove(join77(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
532033
532199
  }
532034
532200
  }
532035
- var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS2, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
532201
+ var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, HANDOFF_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS2, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
532036
532202
  var init_oa_directory = __esm({
532037
532203
  "packages/cli/src/tui/oa-directory.ts"() {
532038
532204
  "use strict";
@@ -532049,6 +532215,7 @@ var init_oa_directory = __esm({
532049
532215
  "AGENTS.md"
532050
532216
  ];
532051
532217
  PENDING_TASK_FILE = "pending-task.json";
532218
+ HANDOFF_FILE = "task-handoff.json";
532052
532219
  CONTEXT_SAVE_FILE = "session-context.json";
532053
532220
  MAX_CONTEXT_ENTRIES = 20;
532054
532221
  SAME_TASK_REPLACE_WINDOW_MS = 12 * 60 * 60 * 1e3;
@@ -582988,6 +583155,10 @@ ${toolOutput}` });
582988
583155
  this.context.push({ role: "assistant", content: finalSpoken });
582989
583156
  this.setState("SPEAKING");
582990
583157
  this.onAgentSpeech(finalSpoken);
583158
+ try {
583159
+ this.listen.pause();
583160
+ } catch {
583161
+ }
582991
583162
  this.voice.speak(finalSpoken);
582992
583163
  this.voiceTranscript.push({ role: "assistant", content: finalSpoken, ts: Date.now() });
582993
583164
  this.voiceTranscript.push({ role: "assistant", content: response.trim(), ts: Date.now() });
@@ -583014,6 +583185,10 @@ ${toolOutput}` });
583014
583185
  this.abortController = null;
583015
583186
  }
583016
583187
  if (this.active) {
583188
+ try {
583189
+ await this.listen.resume();
583190
+ } catch {
583191
+ }
583017
583192
  this.setState("LISTENING");
583018
583193
  if (this.verbose) this.onStatus("LISTENING...");
583019
583194
  }
@@ -585103,6 +585278,42 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
585103
585278
  });
585104
585279
  } catch {
585105
585280
  }
585281
+ try {
585282
+ const handoff = {
585283
+ base: {
585284
+ savedAt: (/* @__PURE__ */ new Date()).toISOString(),
585285
+ task: cleanPromptForDiary(task).slice(0, 500),
585286
+ summary: result.summary.slice(0, 500),
585287
+ assistantResponse: cleanForStorage(lastAssistantText || result.summary).slice(0, 1200),
585288
+ filesModified: Array.from(filesTouched).slice(0, 30),
585289
+ toolCalls: result.toolCalls,
585290
+ completed: result.completed,
585291
+ model: config.model,
585292
+ source: "task_complete"
585293
+ },
585294
+ accomplishments: [],
585295
+ // Populated by agent if it provides structured output
585296
+ files: Array.from(filesTouched).slice(0, 20).map((f2) => ({
585297
+ path: f2,
585298
+ operation: "modified"
585299
+ })),
585300
+ memories: [],
585301
+ // Populated from memory recalls during task
585302
+ findings: [],
585303
+ // Populated by agent
585304
+ validation: {
585305
+ testsRan: false,
585306
+ // Would need to track during task
585307
+ testsPassed: false,
585308
+ buildSucceeded: true
585309
+ // Assume success if task completed
585310
+ },
585311
+ eligible: result.completed,
585312
+ handoffAt: (/* @__PURE__ */ new Date()).toISOString()
585313
+ };
585314
+ writeTaskHandoff(repoRoot, handoff);
585315
+ } catch {
585316
+ }
585106
585317
  try {
585107
585318
  const sessionId2 = `session-${Date.now().toString(36)}`;
585108
585319
  const contentLines = statusBar?._contentLines ?? [];
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.440",
3
+ "version": "0.187.442",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "open-agents-ai",
9
- "version": "0.187.440",
9
+ "version": "0.187.442",
10
10
  "hasInstallScript": true,
11
11
  "license": "CC-BY-NC-4.0",
12
12
  "dependencies": {
@@ -2630,9 +2630,9 @@
2630
2630
  }
2631
2631
  },
2632
2632
  "node_modules/ajv": {
2633
- "version": "8.18.0",
2634
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
2635
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
2633
+ "version": "8.20.0",
2634
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
2635
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
2636
2636
  "license": "MIT",
2637
2637
  "dependencies": {
2638
2638
  "fast-deep-equal": "^3.1.3",
@@ -4207,9 +4207,9 @@
4207
4207
  }
4208
4208
  },
4209
4209
  "node_modules/express-rate-limit": {
4210
- "version": "8.4.0",
4211
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.4.0.tgz",
4212
- "integrity": "sha512-gDK8yiqKxrGta+3WtON59arrrw6GLmadA1qoFgYXzdcch8fmKDID2XqO8itsi3f1wufXYPT51387dN6cvVBS3Q==",
4210
+ "version": "8.4.1",
4211
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.4.1.tgz",
4212
+ "integrity": "sha512-NGVYwQSAyEQgzxX1iCM978PP9AdO/hW93gMcF6ZwQCm+rFvLsBH6w4xcXWTcliS8La5EPRN3p9wzItqBwJrfNw==",
4213
4213
  "license": "MIT",
4214
4214
  "dependencies": {
4215
4215
  "ip-address": "10.1.0"
@@ -4794,9 +4794,9 @@
4794
4794
  }
4795
4795
  },
4796
4796
  "node_modules/hono": {
4797
- "version": "4.12.14",
4798
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.14.tgz",
4799
- "integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==",
4797
+ "version": "4.12.15",
4798
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.15.tgz",
4799
+ "integrity": "sha512-qM0jDhFEaCBb4TxoW7f53Qrpv9RBiayUHo0S52JudprkhvpjIrGoU1mnnr29Fvd1U335ZFPZQY1wlkqgfGXyLg==",
4800
4800
  "license": "MIT",
4801
4801
  "engines": {
4802
4802
  "node": ">=16.9.0"
@@ -8622,9 +8622,9 @@
8622
8622
  }
8623
8623
  },
8624
8624
  "node_modules/terser": {
8625
- "version": "5.46.1",
8626
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.1.tgz",
8627
- "integrity": "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==",
8625
+ "version": "5.46.2",
8626
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.2.tgz",
8627
+ "integrity": "sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==",
8628
8628
  "license": "BSD-2-Clause",
8629
8629
  "peer": true,
8630
8630
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.440",
3
+ "version": "0.187.442",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",