very-happy-cli 0.2.125 → 0.2.127

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.
Files changed (47) hide show
  1. package/dist/{AcpBackend-DOQGItcS.mjs → AcpBackend-B9_vB_mY.mjs} +2 -2
  2. package/dist/{AcpBackend-ssQpTLks.cjs → AcpBackend-Cbykm5Pg.cjs} +2 -2
  3. package/dist/{AcpSessionManager-DHLc-D50.cjs → AcpSessionManager-DGCsNKRd.cjs} +1 -1
  4. package/dist/{AcpSessionManager-D4WkNsRs.mjs → AcpSessionManager-HsxKXreC.mjs} +1 -1
  5. package/dist/{agentGuidance-Cg9ZG1pP.cjs → agentGuidance-B-CazXmT.cjs} +64 -33
  6. package/dist/{agentGuidance-QpYwykb9.mjs → agentGuidance-CTyzeLCQ.mjs} +62 -35
  7. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  8. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  9. package/dist/{config-CZNIz3W0.mjs → config-DotNknpP.mjs} +4 -4
  10. package/dist/{config-BxHOGtEK.cjs → config-Dwt-15hE.cjs} +4 -4
  11. package/dist/{index-CrSifgJM.mjs → index-B1qzJIMw.mjs} +249 -28
  12. package/dist/{index-Jrk6ud3g.mjs → index-C2kblG8-.mjs} +13 -9
  13. package/dist/{index-D-BgvQi5.mjs → index-CWPgxeLD.mjs} +4 -4
  14. package/dist/{index-Do-kjc30.cjs → index-DgjzHewW.cjs} +254 -31
  15. package/dist/{index-D_Rm9dw9.cjs → index-DhCEmP3d.cjs} +4 -4
  16. package/dist/{index-CBj99SO6.cjs → index-DyvVjr8Y.cjs} +13 -9
  17. package/dist/index.cjs +4 -4
  18. package/dist/index.mjs +4 -4
  19. package/dist/{installTerminalHooks-CPsdeOM4.cjs → installTerminalHooks-DfBvxRdw.cjs} +4 -4
  20. package/dist/{installTerminalHooks-Z1Jb6yjb.mjs → installTerminalHooks-cpuDExTT.mjs} +4 -4
  21. package/dist/lib.cjs +2 -2
  22. package/dist/lib.d.cts +1 -0
  23. package/dist/lib.d.mts +1 -0
  24. package/dist/lib.mjs +2 -2
  25. package/dist/{limits-DViGHwSj.cjs → limits-BDG3QjIB.cjs} +7 -7
  26. package/dist/{limits-FjbPJPsF.mjs → limits-D2XM3dvN.mjs} +9 -9
  27. package/dist/{mcp-BbQ5FWcQ.cjs → mcp-BZ3iYnBc.cjs} +4 -4
  28. package/dist/{mcp-zqPJ94Bk.mjs → mcp-CpUrsnoC.mjs} +4 -4
  29. package/dist/{runGemini-BnHGYX-H.cjs → runGemini-BE_nghsj.cjs} +6 -6
  30. package/dist/{runGemini-Bu49s_bN.mjs → runGemini-BY7uA-Uk.mjs} +6 -6
  31. package/dist/{runOpenClaw-CznAYPCh.mjs → runOpenClaw-Be_U4DHZ.mjs} +5 -5
  32. package/dist/{runOpenClaw-3Ld1eoWV.cjs → runOpenClaw-Cqun9jar.cjs} +5 -5
  33. package/dist/{send-BevgS1mf.mjs → send-D2xX42zg.mjs} +4 -4
  34. package/dist/{send-DCzyBxLl.cjs → send-DbqRxLQW.cjs} +4 -4
  35. package/dist/{sessions-DSoaBHwA.cjs → sessions-CtrMbMBJ.cjs} +4 -4
  36. package/dist/{sessions-Ba2oRTmw.mjs → sessions-D06cLJ7f.mjs} +4 -4
  37. package/dist/{spawn-CqMLY6dE.cjs → spawn-Cu_kM761.cjs} +4 -4
  38. package/dist/{spawn-j9KBfj4e.mjs → spawn-DMx1JKXo.mjs} +4 -4
  39. package/dist/{teams-CmU3K9vB.cjs → teams-C2MfKWFe.cjs} +67 -7
  40. package/dist/{teams-C0ggJTJ-.mjs → teams-D7ubdfTY.mjs} +64 -4
  41. package/dist/todo-hKSIY23F.mjs +128 -0
  42. package/dist/todo-yvodzg_y.cjs +132 -0
  43. package/dist/{types-BGHnQXl5.cjs → types-BuxqyzYf.cjs} +329 -12
  44. package/dist/{types-DLDkfrTC.mjs → types-Df_vXvzD.mjs} +320 -6
  45. package/package.json +7 -7
  46. package/dist/resources-CVl7NdOB.cjs +0 -83
  47. package/dist/resources-D-mn7ptO.mjs +0 -80
@@ -3,13 +3,13 @@
3
3
  var chalk = require('chalk');
4
4
  var os = require('node:os');
5
5
  var node_crypto = require('node:crypto');
6
- var api = require('./types-BGHnQXl5.cjs');
7
- var persistence = require('./limits-DViGHwSj.cjs');
6
+ var api = require('./types-BuxqyzYf.cjs');
7
+ var persistence = require('./limits-BDG3QjIB.cjs');
8
8
  var spawn = require('cross-spawn');
9
9
  var path = require('node:path');
10
10
  var node_readline = require('node:readline');
11
11
  var node_fs = require('node:fs');
12
- var agentGuidance = require('./agentGuidance-Cg9ZG1pP.cjs');
12
+ var agentGuidance = require('./agentGuidance-B-CazXmT.cjs');
13
13
  var promises = require('node:fs/promises');
14
14
  var fs = require('fs/promises');
15
15
  var ink = require('ink');
@@ -669,7 +669,7 @@ function shouldIncludeCoAuthoredBy() {
669
669
 
670
670
  const BASE_SYSTEM_PROMPT = (() => agentGuidance.trimIdent(`
671
671
  ALWAYS when you start a new chat - you must call a tool "mcp__happy__change_title" to set a chat title. When you think chat title is not relevant anymore - call the tool again to change it. When chat name is too generic and you have a change to make it more specific - call the tool again to change it. This title is needed to easily find the chat in the future. Help human.
672
- `))() + "\n\n" + agentGuidance.AGENT_GUIDANCE;
672
+ `))() + "\n\n" + agentGuidance.AGENT_GUIDANCE + "\n\n" + api.BUILTIN_TODO_DISCOVERY;
673
673
  const CO_AUTHORED_CREDITS = (() => agentGuidance.trimIdent(`
674
674
  When making commit messages, instead of just giving co-credit to Claude, also give credit to Happy like so:
675
675
 
@@ -5853,7 +5853,8 @@ async function sendUserMessage(sessionId, persisted, text, client, options = {})
5853
5853
  text
5854
5854
  },
5855
5855
  meta: {
5856
- sentFrom: options.sentFrom ?? "cli"
5856
+ sentFrom: options.sentFrom ?? "cli",
5857
+ ...options.model ? { model: options.model } : {}
5857
5858
  }
5858
5859
  };
5859
5860
  const encrypted = persistence.encodeBase64(persistence.encrypt(
@@ -7675,7 +7676,7 @@ function parseJsonObject(text) {
7675
7676
  return null;
7676
7677
  }
7677
7678
  }
7678
- function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-Do-kjc30.cjs', document.baseURI).href))).resolve(s)) {
7679
+ function resolveSdkClaudeBinary(platform = process.platform, arch = process.arch, resolver = (s) => node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DgjzHewW.cjs', document.baseURI).href))).resolve(s)) {
7679
7680
  const platformArch = `${platform}-${arch}`;
7680
7681
  const candidates = [
7681
7682
  `@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
@@ -8822,6 +8823,100 @@ async function claimSessionOrExit(happySessionId, options) {
8822
8823
  process.on("exit", () => releaseSessionLock(happySessionId));
8823
8824
  }
8824
8825
 
8826
+ const TEAM_SKILL = `---
8827
+ name: very-happy-teams
8828
+ description: Coordinate coding agents through Very Happy teams: delegate tasks, exchange messages, review results, and recover interrupted work. Use when asked to organize or participate in an agent team.
8829
+ ---
8830
+
8831
+ # Very Happy Agent Teams
8832
+
8833
+ Use the team_* tools in a managed Very Happy session. If absent, explain that this host needs Very Happy Teams setup; reading this skill alone does not establish a connection.
8834
+
8835
+ Start with team_inspect if already assigned. Otherwise team_create or team_join connects the current session. A scoped worker cannot create another root identity or use account-wide tools to bypass its scope.
8836
+
8837
+ Work yourself when delegation would add needless overhead. Delegate independent work with a clear goal and acceptance criteria. When delegating within your assignment, pass its parentTaskId. Members may delegate further within their existing authority. After delegating child work, wait for those results instead of continuing parallel edits yourself. Waiting parents yield their execution slot to their children; the team limit counts progressing leaf assignments, not OS processes.
8838
+
8839
+ Name exactly one integrator for each team. Workers edit only their assigned worktrees; they must not merge main, publish releases, change global daemon or npm installations, or allocate shared backlog IDs. The integrator serializes these operations. Across teams, the owner coordinates shared resources: a worktree is not a global lock.
8840
+
8841
+ Use a unique requestId for each action and reuse it with identical arguments when the outcome is unknown. Inspect state before retrying; a timeout does not prove no action occurred. A delivered message is not proof its recipient processed it.
8842
+
8843
+ Inspect the current attemptId and goalVersion before team_submit. Include artifact locations and verification evidence. The owner reviews and accepts or returns the result. All children completing does not automatically satisfy the parent goal.
8844
+
8845
+ Acceptance and cleanup are separate. Never delete dirty worktrees, stop user-owned sessions, or bypass permissions to finish cleanup. Use team_cancel or team_handoff and inspect the resulting status. Keep summaries concise; do not repeatedly forward full descendant transcripts.
8846
+
8847
+ A root member may create a persistent schedule for itself with the schedule tools; team_inspect shows schedules. Timely delivery requires an online daemon. A scheduled delivery does not prove the model completed the work. Pause or cancel schedules explicitly when they are no longer needed.
8848
+
8849
+ On restart inspect authoritative state and messages before taking new actions. Do not invent completed work from a previous context. Scope credentials are runtime-owned; never read, print, or copy them into prompts.
8850
+ `;
8851
+ const PI_TEAMS_EXTENSION = `// Managed by Very Happy Agent Teams.
8852
+ export default async function(pi) {
8853
+ const endpoint = process.env.HAPPY_MCP_URL;
8854
+ if (!endpoint) return;
8855
+ const url = new URL(endpoint);
8856
+ if (!['127.0.0.1', 'localhost', '[::1]'].includes(url.hostname) || url.protocol !== 'http:') throw new Error('Very Happy MCP must be local');
8857
+ const {readFile} = await import('node:fs/promises');
8858
+ const {join} = await import('node:path');
8859
+ const {homedir} = await import('node:os');
8860
+ pi.on('tool_call', async (event, ctx) => {
8861
+ let mode = process.env.HAPPY_PERMISSION_MODE || 'default';
8862
+ const sid = process.env.HAPPY_SESSION_ID;
8863
+ if (sid && /^[a-zA-Z0-9_-]+$/.test(sid)) {
8864
+ try { mode = JSON.parse(await readFile(join(process.env.HAPPY_HOME_DIR || join(homedir(), '.happy'), 'session-modes', sid + '.json'), 'utf8')).permissionMode; }
8865
+ catch (error) { if (error.code !== 'ENOENT') mode = 'default'; }
8866
+ }
8867
+ if (mode === 'yolo') mode = 'bypassPermissions';
8868
+ if (!['default','plan','acceptEdits','bypassPermissions'].includes(mode)) mode = 'default';
8869
+ if (mode === 'bypassPermissions') return;
8870
+ if (['read','ls','find','grep','team_inspect','change_title','report_progress'].includes(event.toolName)) return;
8871
+ if (mode === 'plan') return {block:true,reason:'Plan mode allows read-only tools'};
8872
+ if (mode === 'acceptEdits' && ['write','edit'].includes(event.toolName)) return;
8873
+ try {
8874
+ const allowed = await ctx.ui.confirm('Allow ' + event.toolName + '?', JSON.stringify(event.input || {}).slice(0,4000));
8875
+ if (allowed === true) return;
8876
+ } catch {}
8877
+ return {block:true,reason:'Tool requires explicit approval'};
8878
+ });
8879
+ let nextId = 0;
8880
+ async function rpc(method, params) {
8881
+ const requestId = ++nextId;
8882
+ const response = await fetch(endpoint, { method: 'POST', redirect: 'error', headers: {'content-type':'application/json', accept:'application/json, text/event-stream'}, body: JSON.stringify({jsonrpc:'2.0',id:requestId,method,params}), signal: AbortSignal.timeout(30000) });
8883
+ if (!response.ok) throw new Error('Very Happy tools unavailable (HTTP ' + response.status + ')');
8884
+ const body = await response.text();
8885
+ let data;
8886
+ if ((response.headers.get('content-type') || '').includes('text/event-stream')) {
8887
+ for (const event of body.split(/\\r?\\n\\r?\\n/)) {
8888
+ const payload = event.split(/\\r?\\n/).filter(line => line.startsWith('data:')).map(line => line.slice(5).trimStart()).join('\\n');
8889
+ if (payload) { const candidate = JSON.parse(payload); if (candidate.id === requestId) data = candidate; }
8890
+ }
8891
+ } else data = JSON.parse(body);
8892
+ if (!data || data.error) throw new Error('Very Happy tool request failed');
8893
+ return data.result;
8894
+ }
8895
+ await rpc('initialize', {protocolVersion:'2024-11-05',capabilities:{},clientInfo:{name:'very-happy-pi-teams',version:'1'}});
8896
+ const available = await rpc('tools/list', {});
8897
+ for (const tool of available.tools || []) {
8898
+ pi.registerTool({name:tool.name,label:tool.name,description:tool.description || tool.name,parameters:tool.inputSchema,
8899
+ async execute(_id, args) { const result = await rpc('tools/call', {name:tool.name,arguments:args}); return {content:result.content,details:{isError:!!result.isError}}; }
8900
+ });
8901
+ }
8902
+ }
8903
+ `;
8904
+
8905
+ function teamInitialPrompt(goal, root, directory) {
8906
+ const role = root ? "You are the team lead. Inspect your assigned goal, arrange independent work when useful, review member results, integrate changes, and submit the final result for the user to accept. Delegate under your assigned goal using parentTaskId. You must not accept your own root goal." : "You are a team member. Inspect your assigned task and work in your assigned worktree. Delegate within your task when useful, then submit evidence for the lead to review.";
8907
+ return `${TEAM_SKILL}
8908
+
8909
+ ## Your role
8910
+ ${role}
8911
+
8912
+ ## Working directory
8913
+ ${directory ? JSON.stringify(directory) : "Use your current managed session working directory."}
8914
+ Delegate from this working directory unless a different repository was explicitly requested.
8915
+
8916
+ ## Assigned goal
8917
+ ${goal}`;
8918
+ }
8919
+
8825
8920
  const MAX_LINE_CHARS = 500;
8826
8921
  const MAX_ARGS_CHARS = 160;
8827
8922
  function truncateText(text, max = MAX_LINE_CHARS) {
@@ -9403,7 +9498,7 @@ function createTeamWorker(deps) {
9403
9498
  let knownSessionIds = /* @__PURE__ */ new Set();
9404
9499
  const action = async (teamId, requestId, value) => (await http.post(`/v1/teams/${encodeURIComponent(teamId)}/actions`, { requestId, action: value })).data;
9405
9500
  async function complete(op, receipt) {
9406
- await action(op.teamId, `complete-${op.id}`, { type: "complete-operation", operationId: op.id, machineId: deps.machineId, claimId: receipt.claimId, ...receipt.sessionId ? { sessionId: receipt.sessionId } : {} });
9501
+ await action(op.teamId, `complete-${op.id}`, { type: "complete-operation", operationId: op.id, machineId: deps.machineId, claimId: receipt.claimId, ...receipt.sessionId ? { sessionId: receipt.sessionId } : {}, ...op.type === "spawn" && receipt.directory ? { workingDirectory: receipt.directory } : {} });
9407
9502
  writeReceipt(home, { ...receipt, phase: "completed" });
9408
9503
  }
9409
9504
  async function execute(op) {
@@ -9416,7 +9511,7 @@ function createTeamWorker(deps) {
9416
9511
  }
9417
9512
  return;
9418
9513
  }
9419
- const claimed = await action(op.teamId, `claim-${op.id}`, { type: "claim-operation", operationId: op.id, machineId: deps.machineId });
9514
+ const claimed = await action(op.teamId, `claim-${op.id}`, { type: "claim-operation", operationId: op.id, machineId: deps.machineId, ...op.teamLaunchVersion === 1 ? { teamLaunchVersion: 1 } : {} });
9420
9515
  if (!claimed.operation?.claimId) throw new Error("Operation claim did not return a receipt");
9421
9516
  op = claimed.operation;
9422
9517
  credential = claimed.credential;
@@ -9427,7 +9522,7 @@ function createTeamWorker(deps) {
9427
9522
  try {
9428
9523
  if (op.type === "spawn") {
9429
9524
  if (receipt.phase === "prepared") {
9430
- if (!credential) credential = (await action(op.teamId, `claim-${op.id}`, { type: "claim-operation", operationId: op.id, machineId: deps.machineId })).credential;
9525
+ if (!credential) credential = (await action(op.teamId, `claim-${op.id}`, { type: "claim-operation", operationId: op.id, machineId: deps.machineId, ...op.teamLaunchVersion === 1 ? { teamLaunchVersion: 1 } : {} })).credential;
9431
9526
  if (!credential) throw new Error("No scoped credential for worker");
9432
9527
  const current = (await http.get(`/v1/teams/${encodeURIComponent(op.teamId)}`)).data.team;
9433
9528
  const task = current.tasks.find((t) => t.id === op.taskId);
@@ -9445,7 +9540,7 @@ function createTeamWorker(deps) {
9445
9540
  persistence.writePrivateFileSync(scopeFile, JSON.stringify({ serverUrl: server, scopeToken: credential.token, teamId: op.teamId, botId: op.botId, taskId: op.taskId, attemptId: op.attemptId }));
9446
9541
  receipt = { ...receipt, ...resource, scopeFile, phase: "spawning" };
9447
9542
  writeReceipt(home, receipt);
9448
- const spawned = await deps.spawn({ directory: resource.directory, agent: op.assistant === "pi-acp" ? "pi" : op.assistant, permissionMode: "default", spawnedBy: "teams", environmentVariables: { VH_TEAM_SCOPE_FILE: scopeFile, VH_TEAM_OPERATION_ID: op.id } });
9543
+ const spawned = await deps.spawn({ directory: resource.directory, agent: op.assistant === "pi-acp" ? "pi" : op.assistant, permissionMode: op.permissionMode === "bypassPermissions" ? "bypassPermissions" : "default", spawnedBy: "teams", environmentVariables: { VH_TEAM_SCOPE_FILE: scopeFile, VH_TEAM_OPERATION_ID: op.id } });
9449
9544
  if (spawned.type !== "success") throw new Error(spawned.type === "error" ? spawned.errorMessage : "Directory approval required");
9450
9545
  receipt = { ...receipt, sessionId: spawned.sessionId, phase: "spawned" };
9451
9546
  writeReceipt(home, receipt);
@@ -9467,7 +9562,7 @@ function createTeamWorker(deps) {
9467
9562
  return;
9468
9563
  }
9469
9564
  const key = await waitForSessionKey(receipt.sessionId, 1e4);
9470
- await sendUserMessage(receipt.sessionId, key, op.prompt, "teams", { localId: `teams-initial-${op.id}`, sentFrom: "team" });
9565
+ await sendUserMessage(receipt.sessionId, key, teamInitialPrompt(op.prompt, bot?.root === true, receipt.directory), "teams", { localId: `teams-initial-${op.id}`, sentFrom: "team", ...op.model ? { model: op.model } : {} });
9471
9566
  receipt = { ...receipt, phase: "delivered" };
9472
9567
  writeReceipt(home, receipt);
9473
9568
  }
@@ -9569,7 +9664,7 @@ Use the teams tools to inspect current task state before acting. This message is
9569
9664
  const status = axios.isAxiosError(error) ? error.response?.status : void 0;
9570
9665
  if (status !== 404) deps.log("Teams schedule advancement unavailable; regular reconciliation continues");
9571
9666
  }
9572
- const { data } = await http.get("/v1/teams/operations", { params: { machineId: deps.machineId, schedulesVersion: 1 } });
9667
+ const { data } = await http.get("/v1/teams/operations", { params: { machineId: deps.machineId, schedulesVersion: 1, teamLaunchVersion: 1 } });
9573
9668
  knownSessionIds = new Set((data.teams ?? []).flatMap((team) => team.bots.flatMap((bot) => bot.sessionId ? [bot.sessionId] : [])));
9574
9669
  for (const op of data.operations) {
9575
9670
  if (closed) break;
@@ -9613,6 +9708,7 @@ const hostSuffix = process.env.HAPPY_VARIANT === "dev" ? "-dev" : "";
9613
9708
  const startupCliAvailability = api.detectCLIAvailability();
9614
9709
  const initialMachineMetadata = {
9615
9710
  teamsVersion: 1,
9711
+ teamLaunchVersion: 1,
9616
9712
  host: os$1.hostname() + hostSuffix,
9617
9713
  platform: os$1.platform(),
9618
9714
  happyCliVersion: persistence.packageJson.version,
@@ -10883,7 +10979,8 @@ async function startDaemon() {
10883
10979
  });
10884
10980
  void apiMachine.updateMachineMetadata((current) => ({
10885
10981
  ...current ?? initialMachineMetadata,
10886
- teamsVersion: 1
10982
+ teamsVersion: 1,
10983
+ teamLaunchVersion: 1
10887
10984
  })).catch(() => persistence.logger.debug("[DAEMON RUN] Teams capability publication will retry on reconnect"));
10888
10985
  const cleanupAndShutdown = async (source, errorMessage) => {
10889
10986
  persistence.logger.debug(`[DAEMON RUN] Starting proper cleanup (source: ${source}, errorMessage: ${errorMessage})...`);
@@ -10922,6 +11019,113 @@ async function startDaemon() {
10922
11019
  }
10923
11020
  }
10924
11021
 
11022
+ const TEAMS_ADOPT_CAPABILITY = "teams-adopt-v1";
11023
+ const TeamAdoptSchema = z.z.object({
11024
+ requestId: z.z.string().min(1).max(128),
11025
+ name: z.z.string().trim().min(1).max(128),
11026
+ teamId: z.z.string().min(1).max(128).optional()
11027
+ }).strict();
11028
+ async function retainIntent(path$1, input) {
11029
+ await promises.mkdir(path.dirname(path$1), { recursive: true, mode: 448 });
11030
+ let file;
11031
+ try {
11032
+ file = await promises.open(path$1, node_fs.constants.O_WRONLY | node_fs.constants.O_CREAT | node_fs.constants.O_EXCL, 384);
11033
+ } catch (error) {
11034
+ if (error.code !== "EEXIST") throw new Error("Cannot retain team connection request");
11035
+ }
11036
+ if (file) {
11037
+ try {
11038
+ await file.writeFile(JSON.stringify(input));
11039
+ await file.sync();
11040
+ } finally {
11041
+ await file.close();
11042
+ }
11043
+ return { fresh: true };
11044
+ }
11045
+ const existing = await promises.open(path$1, node_fs.constants.O_RDONLY | (node_fs.constants.O_NOFOLLOW ?? 0));
11046
+ try {
11047
+ const stat = await existing.stat();
11048
+ if (!stat.isFile() || process.platform !== "win32" && (stat.mode & 63) !== 0 || typeof process.getuid === "function" && stat.uid !== process.getuid()) throw new Error("Unsafe team connection receipt");
11049
+ const stored = JSON.parse(await existing.readFile("utf8"));
11050
+ const { resolvedTeamId, guidanceDelivered, ...request } = stored;
11051
+ const previous = TeamAdoptSchema.parse(request);
11052
+ if (JSON.stringify(previous) !== JSON.stringify(input)) throw new Error("Another team connection request already exists; retry the original request");
11053
+ if (resolvedTeamId !== void 0 && (typeof resolvedTeamId !== "string" || !resolvedTeamId)) throw new Error("Invalid connection receipt");
11054
+ if (guidanceDelivered !== void 0 && typeof guidanceDelivered !== "boolean") throw new Error("Invalid guidance receipt");
11055
+ return { resolvedTeamId, guidanceDelivered };
11056
+ } finally {
11057
+ await existing.close();
11058
+ }
11059
+ }
11060
+ async function retainTeam(path, input, resolvedTeamId, guidanceDelivered = false) {
11061
+ const temporary = `${path}.${node_crypto.randomUUID()}.new`;
11062
+ const file = await promises.open(temporary, "wx", 384);
11063
+ try {
11064
+ await file.writeFile(JSON.stringify({ ...input, resolvedTeamId, guidanceDelivered }));
11065
+ await file.sync();
11066
+ } finally {
11067
+ await file.close();
11068
+ }
11069
+ try {
11070
+ await promises.rename(temporary, path);
11071
+ } finally {
11072
+ await promises.unlink(temporary).catch(() => {
11073
+ });
11074
+ }
11075
+ }
11076
+ function createTeamAdoption(sessionId) {
11077
+ const client = agentGuidance.createTeamsClient(sessionId);
11078
+ let current;
11079
+ return (raw) => {
11080
+ const parsed = TeamAdoptSchema.safeParse(raw);
11081
+ if (!parsed.success) return { error: "Invalid team connection request" };
11082
+ if (process.env.VH_TEAM_SCOPE_FILE) return { error: "Assigned team members cannot create or join another team" };
11083
+ let path;
11084
+ try {
11085
+ path = `${agentGuidance.teamScopePath(sessionId)}.adopt.json`;
11086
+ } catch {
11087
+ return { error: "A managed session identity is required" };
11088
+ }
11089
+ const input = parsed.data;
11090
+ const signature = JSON.stringify(input);
11091
+ if (current) {
11092
+ if (current.signature !== signature && current.safeToChange) current = void 0;
11093
+ else if (current.signature !== signature) return { error: "Another team connection request already exists; retry the original request" };
11094
+ }
11095
+ if (current) {
11096
+ const result = current.result;
11097
+ if (result && "error" in result) current = void 0;
11098
+ return result ?? { status: "pending", requestId: input.requestId };
11099
+ }
11100
+ const operation = { signature };
11101
+ current = operation;
11102
+ void (async () => {
11103
+ let intent;
11104
+ try {
11105
+ intent = await retainIntent(path, input);
11106
+ const connected = await client.initialize(input, { resumeAdoption: true, expectedTeamId: intent.resolvedTeamId, onTeamResolved: (teamId) => retainTeam(path, input, teamId, intent?.guidanceDelivered) });
11107
+ const instructions = `${TEAM_SKILL}
11108
+
11109
+ This session is now connected as the team lead. Call team_inspect to read the authoritative state before continuing the user's goal. Do not call team_create or team_join again.`;
11110
+ if (!intent.guidanceDelivered) {
11111
+ const key = await waitForSessionKey(sessionId, 1e4);
11112
+ await sendUserMessage(sessionId, key, instructions, "teams", { localId: `teams-adopt-${input.requestId}`, sentFrom: "team" });
11113
+ await retainTeam(path, input, connected.team.id, true);
11114
+ }
11115
+ operation.result = { status: "connected", teamId: connected.team.id, botId: connected.botId, instructions };
11116
+ } catch (error) {
11117
+ if (error instanceof agentGuidance.TeamConnectionPreflightError && intent?.fresh && !intent.resolvedTeamId) {
11118
+ await promises.unlink(path).catch(() => {
11119
+ });
11120
+ operation.safeToChange = true;
11121
+ }
11122
+ operation.result = { error: error instanceof Error ? error.message : "Team connection failed; retry the same request", ...operation.safeToChange ? { safeToChange: true } : {} };
11123
+ }
11124
+ })();
11125
+ return { status: "pending", requestId: input.requestId };
11126
+ };
11127
+ }
11128
+
10925
11129
  const PERSONAL_MEMORY_SOFT_LIMIT_CHARS = 2e3;
10926
11130
  function headingTitle(line) {
10927
11131
  const m = /^##(?!#)\s*(.*?)\s*$/.exec(line);
@@ -11565,6 +11769,11 @@ async function startHappyServer(client, options) {
11565
11769
  resolve(new URL(`http://127.0.0.1:${addr.port}`));
11566
11770
  });
11567
11771
  });
11772
+ const adoptionEnabled = !process.env.VH_TEAM_SCOPE_FILE;
11773
+ if (adoptionEnabled) {
11774
+ client.rpcHandlerManager.registerHandler("teams-adopt", createTeamAdoption(client.sessionId));
11775
+ client.updateMetadata((metadata) => ({ ...metadata, capabilities: [.../* @__PURE__ */ new Set([...metadata.capabilities ?? [], TEAMS_ADOPT_CAPABILITY])] }));
11776
+ }
11568
11777
  persistence.logger.debug(`[happyMCP] server:ready sessionId=${client.sessionId} url=${baseUrl.toString()}`);
11569
11778
  return {
11570
11779
  url: baseUrl.toString(),
@@ -11578,6 +11787,7 @@ async function startHappyServer(client, options) {
11578
11787
  ],
11579
11788
  stop: () => {
11580
11789
  persistence.logger.debug(`[happyMCP] server:stop sessionId=${client.sessionId}`);
11790
+ if (adoptionEnabled) client.rpcHandlerManager.unregisterHandler("teams-adopt");
11581
11791
  server.close();
11582
11792
  }
11583
11793
  };
@@ -11834,7 +12044,7 @@ function registerSideQuestionHandler(rpc, deps) {
11834
12044
  const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
11835
12045
  const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
11836
12046
  const run = deps.run ?? (async (input) => {
11837
- const { query } = await Promise.resolve().then(function () { return require('./index-D_Rm9dw9.cjs'); });
12047
+ const { query } = await Promise.resolve().then(function () { return require('./index-DhCEmP3d.cjs'); });
11838
12048
  return runSideQuestion(query, input);
11839
12049
  });
11840
12050
  const slots = /* @__PURE__ */ new Map();
@@ -11936,7 +12146,7 @@ const MAX_TITLE_CHARS = 60;
11936
12146
  const GENERATION_TIMEOUT_MS = 3e4;
11937
12147
  function resolveClaudeBinary() {
11938
12148
  try {
11939
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-Do-kjc30.cjs', document.baseURI).href)));
12149
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DgjzHewW.cjs', document.baseURI).href)));
11940
12150
  const utilsPath = path.resolve(path.join(api.projectPath(), "scripts", "claude_version_utils.cjs"));
11941
12151
  const { getClaudeCliPath } = require$1(utilsPath);
11942
12152
  const path$1 = getClaudeCliPath();
@@ -14154,9 +14364,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
14154
14364
  };
14155
14365
  }
14156
14366
 
14157
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-Do-kjc30.cjs', document.baseURI).href)));
14367
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DgjzHewW.cjs', document.baseURI).href)));
14158
14368
  const __dirname$1 = path.dirname(__filename$1);
14159
- const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-Do-kjc30.cjs', document.baseURI).href)));
14369
+ const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DgjzHewW.cjs', document.baseURI).href)));
14160
14370
  const PRISMA_QUERY_ENGINE_FILES = {
14161
14371
  "arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
14162
14372
  "x64-darwin": "libquery_engine-darwin.dylib.node",
@@ -15895,6 +16105,7 @@ function buildCodexTurnPrompt(opts) {
15895
16105
  parts.push(opts.message);
15896
16106
  if (opts.includeTitleInstruction) {
15897
16107
  parts.push(CHANGE_TITLE_INSTRUCTION);
16108
+ parts.push(api.BUILTIN_TODO_DISCOVERY);
15898
16109
  }
15899
16110
  return parts.join("\n\n");
15900
16111
  }
@@ -16787,7 +16998,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16787
16998
  process.exit(0);
16788
16999
  } else if (subcommand === "install-terminal-hooks") {
16789
17000
  try {
16790
- const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-CPsdeOM4.cjs'); });
17001
+ const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-DfBvxRdw.cjs'); });
16791
17002
  const command = parseTerminalHooksArgs(args.slice(1));
16792
17003
  if (command.action === "help") {
16793
17004
  console.log(TERMINAL_HOOKS_HELP);
@@ -16804,7 +17015,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16804
17015
  }
16805
17016
  } else if (subcommand === "spawn") {
16806
17017
  try {
16807
- const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-CqMLY6dE.cjs'); });
17018
+ const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-Cu_kM761.cjs'); });
16808
17019
  await handleSpawnCommand(args.slice(1));
16809
17020
  } catch (error) {
16810
17021
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -16816,7 +17027,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16816
17027
  return;
16817
17028
  } else if (subcommand === "sessions") {
16818
17029
  try {
16819
- const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-DSoaBHwA.cjs'); });
17030
+ const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-CtrMbMBJ.cjs'); });
16820
17031
  await handleSessionsCommand(args.slice(1));
16821
17032
  } catch (error) {
16822
17033
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -16828,7 +17039,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16828
17039
  return;
16829
17040
  } else if (subcommand === "send") {
16830
17041
  try {
16831
- const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DCzyBxLl.cjs'); });
17042
+ const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-DbqRxLQW.cjs'); });
16832
17043
  await handleSendCommand(args.slice(1));
16833
17044
  } catch (error) {
16834
17045
  console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
@@ -16934,9 +17145,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16934
17145
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
16935
17146
  const projectId = args[3];
16936
17147
  try {
16937
- const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-BxHOGtEK.cjs'); });
16938
- const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-DViGHwSj.cjs'); }).then(function (n) { return n.persistence; });
16939
- const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-BGHnQXl5.cjs'); }).then(function (n) { return n.api; });
17148
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Dwt-15hE.cjs'); });
17149
+ const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-BDG3QjIB.cjs'); }).then(function (n) { return n.persistence; });
17150
+ const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-BuxqyzYf.cjs'); }).then(function (n) { return n.api; });
16940
17151
  let userEmail = void 0;
16941
17152
  try {
16942
17153
  const credentials = await readCredentialsForConfiguredRelay2();
@@ -16967,7 +17178,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
16967
17178
  }
16968
17179
  if (geminiSubcommand === "project" && args[2] === "get") {
16969
17180
  try {
16970
- const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-BxHOGtEK.cjs'); });
17181
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Dwt-15hE.cjs'); });
16971
17182
  const config = readGeminiLocalConfig();
16972
17183
  if (config.googleCloudProject) {
16973
17184
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -17007,7 +17218,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17007
17218
  process.exit(0);
17008
17219
  }
17009
17220
  try {
17010
- const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-BnHGYX-H.cjs'); });
17221
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-BE_nghsj.cjs'); });
17011
17222
  let startedBy = void 0;
17012
17223
  for (let i = 1; i < args.length; i++) {
17013
17224
  if (args[i] === "--started-by") {
@@ -17037,7 +17248,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17037
17248
  }
17038
17249
  };
17039
17250
  try {
17040
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-CBj99SO6.cjs'); });
17251
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-DyvVjr8Y.cjs'); });
17041
17252
  const parsed = parsePiRunnerArgs(args.slice(1));
17042
17253
  const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
17043
17254
  const { credentials } = await authAndSetupMachineIfNeeded();
@@ -17064,7 +17275,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17064
17275
  return;
17065
17276
  } else if (subcommand === "acp") {
17066
17277
  try {
17067
- const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-CBj99SO6.cjs'); });
17278
+ const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-DyvVjr8Y.cjs'); });
17068
17279
  let startedBy = void 0;
17069
17280
  let verbose = false;
17070
17281
  const acpArgs = [];
@@ -17104,7 +17315,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17104
17315
  return;
17105
17316
  } else if (subcommand === "openclaw") {
17106
17317
  try {
17107
- const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-3Ld1eoWV.cjs'); });
17318
+ const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-Cqun9jar.cjs'); });
17108
17319
  let startedBy = void 0;
17109
17320
  let verbose = false;
17110
17321
  let gatewayUrl;
@@ -17153,9 +17364,18 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17153
17364
  process.exit(1);
17154
17365
  }
17155
17366
  return;
17367
+ } else if (subcommand === "todo") {
17368
+ try {
17369
+ const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-yvodzg_y.cjs'); });
17370
+ await handleTodoCommand(args.slice(1));
17371
+ } catch (error) {
17372
+ console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
17373
+ process.exitCode = 1;
17374
+ }
17375
+ return;
17156
17376
  } else if (subcommand === "teams") {
17157
17377
  try {
17158
- const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-CmU3K9vB.cjs'); });
17378
+ const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-C2MfKWFe.cjs'); });
17159
17379
  await handleTeamsCommand(args.slice(1));
17160
17380
  } catch (error) {
17161
17381
  console.error(error instanceof Error ? error.message : "Teams command failed");
@@ -17164,7 +17384,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
17164
17384
  return;
17165
17385
  } else if (subcommand === "mcp" && args.length === 1) {
17166
17386
  try {
17167
- const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-BbQ5FWcQ.cjs'); });
17387
+ const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-BZ3iYnBc.cjs'); });
17168
17388
  await handleMcpCommand();
17169
17389
  } catch (error) {
17170
17390
  process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
@@ -17391,6 +17611,7 @@ ${chalk.bold("Usage:")}
17391
17611
  Install optional Claude terminal mirror hooks
17392
17612
  (add --remove to uninstall them)
17393
17613
  very-happy connect Connect AI vendor API keys
17614
+ very-happy todo Built-in Todos and official agent skill (todo --help)
17394
17615
  very-happy sandbox Configure and manage OS-level sandboxing
17395
17616
  very-happy notify Send push notification
17396
17617
  very-happy mcp Stdio MCP server exposing copy_to_clipboard for a
@@ -17537,8 +17758,10 @@ exports.GOOGLE_API_KEY_ENV = GOOGLE_API_KEY_ENV;
17537
17758
  exports.MAX_READ_LIMIT = MAX_READ_LIMIT;
17538
17759
  exports.MessageBuffer = MessageBuffer;
17539
17760
  exports.MessageQueue2 = MessageQueue2;
17761
+ exports.PI_TEAMS_EXTENSION = PI_TEAMS_EXTENSION;
17540
17762
  exports.SPAWN_AGENTS = SPAWN_AGENTS;
17541
17763
  exports.StreamRelay = StreamRelay;
17764
+ exports.TEAM_SKILL = TEAM_SKILL;
17542
17765
  exports.TitleGenerator = TitleGenerator;
17543
17766
  exports.archiveSession = archiveSession;
17544
17767
  exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-Do-kjc30.cjs');
3
+ var index = require('./index-DgjzHewW.cjs');
4
4
  var claudeAgentSdk = require('@anthropic-ai/claude-agent-sdk');
5
5
  require('chalk');
6
6
  require('node:os');
7
7
  require('node:crypto');
8
- require('./types-BGHnQXl5.cjs');
8
+ require('./types-BuxqyzYf.cjs');
9
9
  require('axios');
10
- require('./limits-DViGHwSj.cjs');
10
+ require('./limits-BDG3QjIB.cjs');
11
11
  require('node:fs/promises');
12
12
  require('node:fs');
13
13
  require('node:path');
@@ -31,7 +31,7 @@ require('fs');
31
31
  require('node:readline');
32
32
  require('@anthropic-ai/sandbox-runtime');
33
33
  require('expo-server-sdk');
34
- require('./agentGuidance-Cg9ZG1pP.cjs');
34
+ require('./agentGuidance-B-CazXmT.cjs');
35
35
  require('ink');
36
36
  require('react');
37
37
  require('ps-list');
@@ -1,14 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var AcpBackend = require('./AcpBackend-ssQpTLks.cjs');
4
- var persistence = require('./limits-DViGHwSj.cjs');
5
- var AcpSessionManager = require('./AcpSessionManager-DHLc-D50.cjs');
3
+ var AcpBackend = require('./AcpBackend-Cbykm5Pg.cjs');
4
+ var persistence = require('./limits-BDG3QjIB.cjs');
5
+ var AcpSessionManager = require('./AcpSessionManager-DGCsNKRd.cjs');
6
+ var api = require('./types-BuxqyzYf.cjs');
6
7
  var promises = require('node:fs/promises');
7
8
  var node_crypto = require('node:crypto');
8
9
  var path = require('node:path');
9
- var resources = require('./resources-CVl7NdOB.cjs');
10
- var api = require('./types-BGHnQXl5.cjs');
11
- var index = require('./index-Do-kjc30.cjs');
10
+ var index = require('./index-DgjzHewW.cjs');
12
11
  require('node:child_process');
13
12
  require('@agentclientprotocol/sdk');
14
13
  require('node:fs');
@@ -34,7 +33,7 @@ require('fs');
34
33
  require('node:readline');
35
34
  require('@anthropic-ai/sandbox-runtime');
36
35
  require('expo-server-sdk');
37
- require('./agentGuidance-Cg9ZG1pP.cjs');
36
+ require('./agentGuidance-B-CazXmT.cjs');
38
37
  require('ink');
39
38
  require('react');
40
39
  require('@anthropic-ai/claude-agent-sdk');
@@ -75,7 +74,7 @@ async function preparePiTeamsRuntime() {
75
74
  const directory = path.join(persistence.configuration.happyHomeDir, "teams", "pi-runtime");
76
75
  await promises.mkdir(directory, { recursive: true, mode: 448 });
77
76
  const extension = path.join(directory, "very-happy-teams.mjs");
78
- await publish(extension, resources.PI_TEAMS_EXTENSION, 384);
77
+ await publish(extension, index.PI_TEAMS_EXTENSION, 384);
79
78
  const launcher = path.join(directory, "pi-teams.mjs");
80
79
  const script = `#!${process.execPath}
81
80
  import { spawn } from 'node:child_process';
@@ -1075,6 +1074,7 @@ async function runAcp(opts) {
1075
1074
  logAcp("muted", `Outgoing models from ${opts.agentName}: not reported yet`);
1076
1075
  }
1077
1076
  }
1077
+ let todoDiscoverySent = false;
1078
1078
  while (!shouldExit) {
1079
1079
  const waitSignal = abortController.signal;
1080
1080
  const batch = await messageQueue.waitForMessagesAndGetAsString(waitSignal);
@@ -1101,7 +1101,11 @@ async function runAcp(opts) {
1101
1101
  if (typeof batch.mode.model === "string" && batch.mode.model.length > 0) {
1102
1102
  await switchModelIfRequested(batch.mode.model);
1103
1103
  }
1104
- await backend.sendPrompt(acpSessionId, batch.message);
1104
+ const prompt = todoDiscoverySent ? batch.message : `${batch.message}
1105
+
1106
+ ${api.BUILTIN_TODO_DISCOVERY}`;
1107
+ await backend.sendPrompt(acpSessionId, prompt);
1108
+ todoDiscoverySent = true;
1105
1109
  await turnEnded;
1106
1110
  sendEnvelopes(sessionManager.endTurn("completed"));
1107
1111
  streamRelay.endTurn();
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-Do-kjc30.cjs');
5
- require('./limits-DViGHwSj.cjs');
4
+ require('./index-DgjzHewW.cjs');
5
+ require('./limits-BDG3QjIB.cjs');
6
6
  require('zod');
7
- require('./types-BGHnQXl5.cjs');
7
+ require('./types-BuxqyzYf.cjs');
8
8
  require('node:child_process');
9
9
  require('node:os');
10
10
  require('node:crypto');
@@ -12,7 +12,7 @@ require('cross-spawn');
12
12
  require('node:path');
13
13
  require('node:readline');
14
14
  require('node:fs');
15
- require('./agentGuidance-Cg9ZG1pP.cjs');
15
+ require('./agentGuidance-B-CazXmT.cjs');
16
16
  require('node:fs/promises');
17
17
  require('fs/promises');
18
18
  require('ink');