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.
- package/dist/{AcpBackend-DOQGItcS.mjs → AcpBackend-B9_vB_mY.mjs} +2 -2
- package/dist/{AcpBackend-ssQpTLks.cjs → AcpBackend-Cbykm5Pg.cjs} +2 -2
- package/dist/{AcpSessionManager-DHLc-D50.cjs → AcpSessionManager-DGCsNKRd.cjs} +1 -1
- package/dist/{AcpSessionManager-D4WkNsRs.mjs → AcpSessionManager-HsxKXreC.mjs} +1 -1
- package/dist/{agentGuidance-Cg9ZG1pP.cjs → agentGuidance-B-CazXmT.cjs} +64 -33
- package/dist/{agentGuidance-QpYwykb9.mjs → agentGuidance-CTyzeLCQ.mjs} +62 -35
- package/dist/codex/happyMcpStdioBridge.cjs +2 -2
- package/dist/codex/happyMcpStdioBridge.mjs +2 -2
- package/dist/{config-CZNIz3W0.mjs → config-DotNknpP.mjs} +4 -4
- package/dist/{config-BxHOGtEK.cjs → config-Dwt-15hE.cjs} +4 -4
- package/dist/{index-CrSifgJM.mjs → index-B1qzJIMw.mjs} +249 -28
- package/dist/{index-Jrk6ud3g.mjs → index-C2kblG8-.mjs} +13 -9
- package/dist/{index-D-BgvQi5.mjs → index-CWPgxeLD.mjs} +4 -4
- package/dist/{index-Do-kjc30.cjs → index-DgjzHewW.cjs} +254 -31
- package/dist/{index-D_Rm9dw9.cjs → index-DhCEmP3d.cjs} +4 -4
- package/dist/{index-CBj99SO6.cjs → index-DyvVjr8Y.cjs} +13 -9
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/{installTerminalHooks-CPsdeOM4.cjs → installTerminalHooks-DfBvxRdw.cjs} +4 -4
- package/dist/{installTerminalHooks-Z1Jb6yjb.mjs → installTerminalHooks-cpuDExTT.mjs} +4 -4
- package/dist/lib.cjs +2 -2
- package/dist/lib.d.cts +1 -0
- package/dist/lib.d.mts +1 -0
- package/dist/lib.mjs +2 -2
- package/dist/{limits-DViGHwSj.cjs → limits-BDG3QjIB.cjs} +7 -7
- package/dist/{limits-FjbPJPsF.mjs → limits-D2XM3dvN.mjs} +9 -9
- package/dist/{mcp-BbQ5FWcQ.cjs → mcp-BZ3iYnBc.cjs} +4 -4
- package/dist/{mcp-zqPJ94Bk.mjs → mcp-CpUrsnoC.mjs} +4 -4
- package/dist/{runGemini-BnHGYX-H.cjs → runGemini-BE_nghsj.cjs} +6 -6
- package/dist/{runGemini-Bu49s_bN.mjs → runGemini-BY7uA-Uk.mjs} +6 -6
- package/dist/{runOpenClaw-CznAYPCh.mjs → runOpenClaw-Be_U4DHZ.mjs} +5 -5
- package/dist/{runOpenClaw-3Ld1eoWV.cjs → runOpenClaw-Cqun9jar.cjs} +5 -5
- package/dist/{send-BevgS1mf.mjs → send-D2xX42zg.mjs} +4 -4
- package/dist/{send-DCzyBxLl.cjs → send-DbqRxLQW.cjs} +4 -4
- package/dist/{sessions-DSoaBHwA.cjs → sessions-CtrMbMBJ.cjs} +4 -4
- package/dist/{sessions-Ba2oRTmw.mjs → sessions-D06cLJ7f.mjs} +4 -4
- package/dist/{spawn-CqMLY6dE.cjs → spawn-Cu_kM761.cjs} +4 -4
- package/dist/{spawn-j9KBfj4e.mjs → spawn-DMx1JKXo.mjs} +4 -4
- package/dist/{teams-CmU3K9vB.cjs → teams-C2MfKWFe.cjs} +67 -7
- package/dist/{teams-C0ggJTJ-.mjs → teams-D7ubdfTY.mjs} +64 -4
- package/dist/todo-hKSIY23F.mjs +128 -0
- package/dist/todo-yvodzg_y.cjs +132 -0
- package/dist/{types-BGHnQXl5.cjs → types-BuxqyzYf.cjs} +329 -12
- package/dist/{types-DLDkfrTC.mjs → types-Df_vXvzD.mjs} +320 -6
- package/package.json +7 -7
- package/dist/resources-CVl7NdOB.cjs +0 -83
- package/dist/resources-D-mn7ptO.mjs +0 -80
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
|
|
2
2
|
import os, { homedir, userInfo, tmpdir } from 'node:os';
|
|
3
3
|
import { randomUUID, randomBytes, createHash as createHash$1, timingSafeEqual } from 'node:crypto';
|
|
4
|
-
import {
|
|
5
|
-
import { z as readDaemonState, l as logger, c as configuration, A as clearDaemonState, B as ensurePrivateDirectory, D as hardenPrivateFile, p as packageJson,
|
|
4
|
+
import { j as getProjectPath, h as BUILTIN_TODO_DISCOVERY, p as projectPath, k as initializeSandbox, w as wrapCommand, d as contentLogMetadata, I as InvalidateSync, R as RawJSONLinesSchema, f as delay, l as AsyncLock, S as STREAM_DELTA_MAX_CHARS, M as MAX_CHAT_ATTACHMENT_SOURCE_BYTES, m as commandOnPath, n as deriveLocalCliUpdateSummary, o as isClaudeSessionId, q as getLocalHappyAgentCredentialPath, r as readLocalHappyAgentCredentials, t as parseExactVersion, u as compareExactVersions, v as extractCompleteLines, x as decideBackfill, y as parseTerminalHookPayload, z as tmuxArgs, C as scrubTmuxClientEnv, D as decideMirrorBinding, E as MIRROR_BACKFILL_LINES_DEFAULT, F as mirrorLineKey, G as mirrorLocalId, H as detectCLIAvailability, J as detectResumeSupport, K as summarizeSpawnSessionForLog, L as shellescape, A as ApiClient, N as fetchCliUpdateState, O as resolveCliUpdateCheckInterval, P as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS, i as isValidSessionId, Q as listVhTerminals, T as isValidTerminalId, U as readVhTerminal, V as sendToVhTerminal, W as TITLE_PROMPT_PREFIX, X as BOARD_ANALYZER_PROMPT_PREFIX, g as connectionState, Y as startOfflineReconnection, c as createEnvelope, Z as CodexAppServerClient } from './types-Df_vXvzD.mjs';
|
|
5
|
+
import { z as readDaemonState, l as logger, c as configuration, A as clearDaemonState, B as ensurePrivateDirectory, D as hardenPrivateFile, p as packageJson, g as readSettings, E as readCredentials, s as credentialRelayProblem, i as encodeBase64, F as readSettingsOutcome, G as updateSettings, H as encodeBase64Url, m as decodeBase64, I as writeCredentialsLegacy, J as writeCredentialsDataKey, d as readCredentialsForConfiguredRelay, j as encrypt, r as readPersistedSessions, w as writePrivateFileSync, K as decryptWithDataKey, L as decryptLegacy, M as persistSession, k as decrypt, f as ensurePrivateDirectorySync, N as acquireDaemonLock, O as deletePersistedSessions, P as writeDaemonState, Q as writeSettings, R as releaseDaemonLock, C as CLIPBOARD_TOOL_NAME, a as CLIPBOARD_TOOL_TITLE, b as CLIPBOARD_TOOL_DESCRIPTION, e as CLIPBOARD_MAX_BYTES, S as clearCredentials, T as clearMachineId, U as SandboxConfigSchema, V as getLatestDaemonLog } from './limits-D2XM3dvN.mjs';
|
|
6
6
|
import spawn$1, { spawn } from 'cross-spawn';
|
|
7
7
|
import path, { join, resolve, basename, isAbsolute, dirname, sep, delimiter, normalize } from 'node:path';
|
|
8
8
|
import { createInterface } from 'node:readline';
|
|
9
9
|
import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, unlinkSync, renameSync, writeFileSync, accessSync, constants, openSync, fsyncSync, closeSync, rmSync as rmSync$1, chmodSync as chmodSync$1 } from 'node:fs';
|
|
10
|
-
import {
|
|
10
|
+
import { f as trimIdent, A as AGENT_GUIDANCE, t as teamScopePath, T as TeamConnectionPreflightError, e as createTeamsClient, P as PREVIEW_TOOL_NAME, R as REPORT_PROGRESS_TOOL_NAME, g as TEAM_TOOL_NAMES, r as registerTeamsTools, a as PREVIEW_TOOL_TITLE, b as PREVIEW_TOOL_DESCRIPTION, h as REPORT_PROGRESS_TOOL_TITLE, i as REPORT_PROGRESS_TOOL_DESCRIPTION } from './agentGuidance-CTyzeLCQ.mjs';
|
|
11
11
|
import { readFile, writeFile, rename, unlink, mkdir, symlink, rm, readlink, lstat, stat, open as open$1, appendFile } from 'node:fs/promises';
|
|
12
12
|
import fs, { watch, access } from 'fs/promises';
|
|
13
13
|
import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
@@ -647,7 +647,7 @@ function shouldIncludeCoAuthoredBy() {
|
|
|
647
647
|
|
|
648
648
|
const BASE_SYSTEM_PROMPT = (() => trimIdent(`
|
|
649
649
|
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.
|
|
650
|
-
`))() + "\n\n" + AGENT_GUIDANCE;
|
|
650
|
+
`))() + "\n\n" + AGENT_GUIDANCE + "\n\n" + BUILTIN_TODO_DISCOVERY;
|
|
651
651
|
const CO_AUTHORED_CREDITS = (() => trimIdent(`
|
|
652
652
|
When making commit messages, instead of just giving co-credit to Claude, also give credit to Happy like so:
|
|
653
653
|
|
|
@@ -5831,7 +5831,8 @@ async function sendUserMessage(sessionId, persisted, text, client, options = {})
|
|
|
5831
5831
|
text
|
|
5832
5832
|
},
|
|
5833
5833
|
meta: {
|
|
5834
|
-
sentFrom: options.sentFrom ?? "cli"
|
|
5834
|
+
sentFrom: options.sentFrom ?? "cli",
|
|
5835
|
+
...options.model ? { model: options.model } : {}
|
|
5835
5836
|
}
|
|
5836
5837
|
};
|
|
5837
5838
|
const encrypted = encodeBase64(encrypt(
|
|
@@ -8800,6 +8801,100 @@ async function claimSessionOrExit(happySessionId, options) {
|
|
|
8800
8801
|
process.on("exit", () => releaseSessionLock(happySessionId));
|
|
8801
8802
|
}
|
|
8802
8803
|
|
|
8804
|
+
const TEAM_SKILL = `---
|
|
8805
|
+
name: very-happy-teams
|
|
8806
|
+
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.
|
|
8807
|
+
---
|
|
8808
|
+
|
|
8809
|
+
# Very Happy Agent Teams
|
|
8810
|
+
|
|
8811
|
+
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.
|
|
8812
|
+
|
|
8813
|
+
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.
|
|
8814
|
+
|
|
8815
|
+
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.
|
|
8816
|
+
|
|
8817
|
+
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.
|
|
8818
|
+
|
|
8819
|
+
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.
|
|
8820
|
+
|
|
8821
|
+
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.
|
|
8822
|
+
|
|
8823
|
+
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.
|
|
8824
|
+
|
|
8825
|
+
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.
|
|
8826
|
+
|
|
8827
|
+
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.
|
|
8828
|
+
`;
|
|
8829
|
+
const PI_TEAMS_EXTENSION = `// Managed by Very Happy Agent Teams.
|
|
8830
|
+
export default async function(pi) {
|
|
8831
|
+
const endpoint = process.env.HAPPY_MCP_URL;
|
|
8832
|
+
if (!endpoint) return;
|
|
8833
|
+
const url = new URL(endpoint);
|
|
8834
|
+
if (!['127.0.0.1', 'localhost', '[::1]'].includes(url.hostname) || url.protocol !== 'http:') throw new Error('Very Happy MCP must be local');
|
|
8835
|
+
const {readFile} = await import('node:fs/promises');
|
|
8836
|
+
const {join} = await import('node:path');
|
|
8837
|
+
const {homedir} = await import('node:os');
|
|
8838
|
+
pi.on('tool_call', async (event, ctx) => {
|
|
8839
|
+
let mode = process.env.HAPPY_PERMISSION_MODE || 'default';
|
|
8840
|
+
const sid = process.env.HAPPY_SESSION_ID;
|
|
8841
|
+
if (sid && /^[a-zA-Z0-9_-]+$/.test(sid)) {
|
|
8842
|
+
try { mode = JSON.parse(await readFile(join(process.env.HAPPY_HOME_DIR || join(homedir(), '.happy'), 'session-modes', sid + '.json'), 'utf8')).permissionMode; }
|
|
8843
|
+
catch (error) { if (error.code !== 'ENOENT') mode = 'default'; }
|
|
8844
|
+
}
|
|
8845
|
+
if (mode === 'yolo') mode = 'bypassPermissions';
|
|
8846
|
+
if (!['default','plan','acceptEdits','bypassPermissions'].includes(mode)) mode = 'default';
|
|
8847
|
+
if (mode === 'bypassPermissions') return;
|
|
8848
|
+
if (['read','ls','find','grep','team_inspect','change_title','report_progress'].includes(event.toolName)) return;
|
|
8849
|
+
if (mode === 'plan') return {block:true,reason:'Plan mode allows read-only tools'};
|
|
8850
|
+
if (mode === 'acceptEdits' && ['write','edit'].includes(event.toolName)) return;
|
|
8851
|
+
try {
|
|
8852
|
+
const allowed = await ctx.ui.confirm('Allow ' + event.toolName + '?', JSON.stringify(event.input || {}).slice(0,4000));
|
|
8853
|
+
if (allowed === true) return;
|
|
8854
|
+
} catch {}
|
|
8855
|
+
return {block:true,reason:'Tool requires explicit approval'};
|
|
8856
|
+
});
|
|
8857
|
+
let nextId = 0;
|
|
8858
|
+
async function rpc(method, params) {
|
|
8859
|
+
const requestId = ++nextId;
|
|
8860
|
+
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) });
|
|
8861
|
+
if (!response.ok) throw new Error('Very Happy tools unavailable (HTTP ' + response.status + ')');
|
|
8862
|
+
const body = await response.text();
|
|
8863
|
+
let data;
|
|
8864
|
+
if ((response.headers.get('content-type') || '').includes('text/event-stream')) {
|
|
8865
|
+
for (const event of body.split(/\\r?\\n\\r?\\n/)) {
|
|
8866
|
+
const payload = event.split(/\\r?\\n/).filter(line => line.startsWith('data:')).map(line => line.slice(5).trimStart()).join('\\n');
|
|
8867
|
+
if (payload) { const candidate = JSON.parse(payload); if (candidate.id === requestId) data = candidate; }
|
|
8868
|
+
}
|
|
8869
|
+
} else data = JSON.parse(body);
|
|
8870
|
+
if (!data || data.error) throw new Error('Very Happy tool request failed');
|
|
8871
|
+
return data.result;
|
|
8872
|
+
}
|
|
8873
|
+
await rpc('initialize', {protocolVersion:'2024-11-05',capabilities:{},clientInfo:{name:'very-happy-pi-teams',version:'1'}});
|
|
8874
|
+
const available = await rpc('tools/list', {});
|
|
8875
|
+
for (const tool of available.tools || []) {
|
|
8876
|
+
pi.registerTool({name:tool.name,label:tool.name,description:tool.description || tool.name,parameters:tool.inputSchema,
|
|
8877
|
+
async execute(_id, args) { const result = await rpc('tools/call', {name:tool.name,arguments:args}); return {content:result.content,details:{isError:!!result.isError}}; }
|
|
8878
|
+
});
|
|
8879
|
+
}
|
|
8880
|
+
}
|
|
8881
|
+
`;
|
|
8882
|
+
|
|
8883
|
+
function teamInitialPrompt(goal, root, directory) {
|
|
8884
|
+
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.";
|
|
8885
|
+
return `${TEAM_SKILL}
|
|
8886
|
+
|
|
8887
|
+
## Your role
|
|
8888
|
+
${role}
|
|
8889
|
+
|
|
8890
|
+
## Working directory
|
|
8891
|
+
${directory ? JSON.stringify(directory) : "Use your current managed session working directory."}
|
|
8892
|
+
Delegate from this working directory unless a different repository was explicitly requested.
|
|
8893
|
+
|
|
8894
|
+
## Assigned goal
|
|
8895
|
+
${goal}`;
|
|
8896
|
+
}
|
|
8897
|
+
|
|
8803
8898
|
const MAX_LINE_CHARS = 500;
|
|
8804
8899
|
const MAX_ARGS_CHARS = 160;
|
|
8805
8900
|
function truncateText(text, max = MAX_LINE_CHARS) {
|
|
@@ -9381,7 +9476,7 @@ function createTeamWorker(deps) {
|
|
|
9381
9476
|
let knownSessionIds = /* @__PURE__ */ new Set();
|
|
9382
9477
|
const action = async (teamId, requestId, value) => (await http.post(`/v1/teams/${encodeURIComponent(teamId)}/actions`, { requestId, action: value })).data;
|
|
9383
9478
|
async function complete(op, receipt) {
|
|
9384
|
-
await action(op.teamId, `complete-${op.id}`, { type: "complete-operation", operationId: op.id, machineId: deps.machineId, claimId: receipt.claimId, ...receipt.sessionId ? { sessionId: receipt.sessionId } : {} });
|
|
9479
|
+
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 } : {} });
|
|
9385
9480
|
writeReceipt(home, { ...receipt, phase: "completed" });
|
|
9386
9481
|
}
|
|
9387
9482
|
async function execute(op) {
|
|
@@ -9394,7 +9489,7 @@ function createTeamWorker(deps) {
|
|
|
9394
9489
|
}
|
|
9395
9490
|
return;
|
|
9396
9491
|
}
|
|
9397
|
-
const claimed = await action(op.teamId, `claim-${op.id}`, { type: "claim-operation", operationId: op.id, machineId: deps.machineId });
|
|
9492
|
+
const claimed = await action(op.teamId, `claim-${op.id}`, { type: "claim-operation", operationId: op.id, machineId: deps.machineId, ...op.teamLaunchVersion === 1 ? { teamLaunchVersion: 1 } : {} });
|
|
9398
9493
|
if (!claimed.operation?.claimId) throw new Error("Operation claim did not return a receipt");
|
|
9399
9494
|
op = claimed.operation;
|
|
9400
9495
|
credential = claimed.credential;
|
|
@@ -9405,7 +9500,7 @@ function createTeamWorker(deps) {
|
|
|
9405
9500
|
try {
|
|
9406
9501
|
if (op.type === "spawn") {
|
|
9407
9502
|
if (receipt.phase === "prepared") {
|
|
9408
|
-
if (!credential) credential = (await action(op.teamId, `claim-${op.id}`, { type: "claim-operation", operationId: op.id, machineId: deps.machineId })).credential;
|
|
9503
|
+
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;
|
|
9409
9504
|
if (!credential) throw new Error("No scoped credential for worker");
|
|
9410
9505
|
const current = (await http.get(`/v1/teams/${encodeURIComponent(op.teamId)}`)).data.team;
|
|
9411
9506
|
const task = current.tasks.find((t) => t.id === op.taskId);
|
|
@@ -9423,7 +9518,7 @@ function createTeamWorker(deps) {
|
|
|
9423
9518
|
writePrivateFileSync(scopeFile, JSON.stringify({ serverUrl: server, scopeToken: credential.token, teamId: op.teamId, botId: op.botId, taskId: op.taskId, attemptId: op.attemptId }));
|
|
9424
9519
|
receipt = { ...receipt, ...resource, scopeFile, phase: "spawning" };
|
|
9425
9520
|
writeReceipt(home, receipt);
|
|
9426
|
-
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 } });
|
|
9521
|
+
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 } });
|
|
9427
9522
|
if (spawned.type !== "success") throw new Error(spawned.type === "error" ? spawned.errorMessage : "Directory approval required");
|
|
9428
9523
|
receipt = { ...receipt, sessionId: spawned.sessionId, phase: "spawned" };
|
|
9429
9524
|
writeReceipt(home, receipt);
|
|
@@ -9445,7 +9540,7 @@ function createTeamWorker(deps) {
|
|
|
9445
9540
|
return;
|
|
9446
9541
|
}
|
|
9447
9542
|
const key = await waitForSessionKey(receipt.sessionId, 1e4);
|
|
9448
|
-
await sendUserMessage(receipt.sessionId, key, op.prompt, "teams", { localId: `teams-initial-${op.id}`, sentFrom: "team" });
|
|
9543
|
+
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 } : {} });
|
|
9449
9544
|
receipt = { ...receipt, phase: "delivered" };
|
|
9450
9545
|
writeReceipt(home, receipt);
|
|
9451
9546
|
}
|
|
@@ -9547,7 +9642,7 @@ Use the teams tools to inspect current task state before acting. This message is
|
|
|
9547
9642
|
const status = axios.isAxiosError(error) ? error.response?.status : void 0;
|
|
9548
9643
|
if (status !== 404) deps.log("Teams schedule advancement unavailable; regular reconciliation continues");
|
|
9549
9644
|
}
|
|
9550
|
-
const { data } = await http.get("/v1/teams/operations", { params: { machineId: deps.machineId, schedulesVersion: 1 } });
|
|
9645
|
+
const { data } = await http.get("/v1/teams/operations", { params: { machineId: deps.machineId, schedulesVersion: 1, teamLaunchVersion: 1 } });
|
|
9551
9646
|
knownSessionIds = new Set((data.teams ?? []).flatMap((team) => team.bots.flatMap((bot) => bot.sessionId ? [bot.sessionId] : [])));
|
|
9552
9647
|
for (const op of data.operations) {
|
|
9553
9648
|
if (closed) break;
|
|
@@ -9591,6 +9686,7 @@ const hostSuffix = process.env.HAPPY_VARIANT === "dev" ? "-dev" : "";
|
|
|
9591
9686
|
const startupCliAvailability = detectCLIAvailability();
|
|
9592
9687
|
const initialMachineMetadata = {
|
|
9593
9688
|
teamsVersion: 1,
|
|
9689
|
+
teamLaunchVersion: 1,
|
|
9594
9690
|
host: os$1.hostname() + hostSuffix,
|
|
9595
9691
|
platform: os$1.platform(),
|
|
9596
9692
|
happyCliVersion: packageJson.version,
|
|
@@ -10861,7 +10957,8 @@ async function startDaemon() {
|
|
|
10861
10957
|
});
|
|
10862
10958
|
void apiMachine.updateMachineMetadata((current) => ({
|
|
10863
10959
|
...current ?? initialMachineMetadata,
|
|
10864
|
-
teamsVersion: 1
|
|
10960
|
+
teamsVersion: 1,
|
|
10961
|
+
teamLaunchVersion: 1
|
|
10865
10962
|
})).catch(() => logger.debug("[DAEMON RUN] Teams capability publication will retry on reconnect"));
|
|
10866
10963
|
const cleanupAndShutdown = async (source, errorMessage) => {
|
|
10867
10964
|
logger.debug(`[DAEMON RUN] Starting proper cleanup (source: ${source}, errorMessage: ${errorMessage})...`);
|
|
@@ -10900,6 +10997,113 @@ async function startDaemon() {
|
|
|
10900
10997
|
}
|
|
10901
10998
|
}
|
|
10902
10999
|
|
|
11000
|
+
const TEAMS_ADOPT_CAPABILITY = "teams-adopt-v1";
|
|
11001
|
+
const TeamAdoptSchema = z.object({
|
|
11002
|
+
requestId: z.string().min(1).max(128),
|
|
11003
|
+
name: z.string().trim().min(1).max(128),
|
|
11004
|
+
teamId: z.string().min(1).max(128).optional()
|
|
11005
|
+
}).strict();
|
|
11006
|
+
async function retainIntent(path, input) {
|
|
11007
|
+
await mkdir(dirname(path), { recursive: true, mode: 448 });
|
|
11008
|
+
let file;
|
|
11009
|
+
try {
|
|
11010
|
+
file = await open$1(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 384);
|
|
11011
|
+
} catch (error) {
|
|
11012
|
+
if (error.code !== "EEXIST") throw new Error("Cannot retain team connection request");
|
|
11013
|
+
}
|
|
11014
|
+
if (file) {
|
|
11015
|
+
try {
|
|
11016
|
+
await file.writeFile(JSON.stringify(input));
|
|
11017
|
+
await file.sync();
|
|
11018
|
+
} finally {
|
|
11019
|
+
await file.close();
|
|
11020
|
+
}
|
|
11021
|
+
return { fresh: true };
|
|
11022
|
+
}
|
|
11023
|
+
const existing = await open$1(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
11024
|
+
try {
|
|
11025
|
+
const stat = await existing.stat();
|
|
11026
|
+
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");
|
|
11027
|
+
const stored = JSON.parse(await existing.readFile("utf8"));
|
|
11028
|
+
const { resolvedTeamId, guidanceDelivered, ...request } = stored;
|
|
11029
|
+
const previous = TeamAdoptSchema.parse(request);
|
|
11030
|
+
if (JSON.stringify(previous) !== JSON.stringify(input)) throw new Error("Another team connection request already exists; retry the original request");
|
|
11031
|
+
if (resolvedTeamId !== void 0 && (typeof resolvedTeamId !== "string" || !resolvedTeamId)) throw new Error("Invalid connection receipt");
|
|
11032
|
+
if (guidanceDelivered !== void 0 && typeof guidanceDelivered !== "boolean") throw new Error("Invalid guidance receipt");
|
|
11033
|
+
return { resolvedTeamId, guidanceDelivered };
|
|
11034
|
+
} finally {
|
|
11035
|
+
await existing.close();
|
|
11036
|
+
}
|
|
11037
|
+
}
|
|
11038
|
+
async function retainTeam(path, input, resolvedTeamId, guidanceDelivered = false) {
|
|
11039
|
+
const temporary = `${path}.${randomUUID()}.new`;
|
|
11040
|
+
const file = await open$1(temporary, "wx", 384);
|
|
11041
|
+
try {
|
|
11042
|
+
await file.writeFile(JSON.stringify({ ...input, resolvedTeamId, guidanceDelivered }));
|
|
11043
|
+
await file.sync();
|
|
11044
|
+
} finally {
|
|
11045
|
+
await file.close();
|
|
11046
|
+
}
|
|
11047
|
+
try {
|
|
11048
|
+
await rename(temporary, path);
|
|
11049
|
+
} finally {
|
|
11050
|
+
await unlink(temporary).catch(() => {
|
|
11051
|
+
});
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
function createTeamAdoption(sessionId) {
|
|
11055
|
+
const client = createTeamsClient(sessionId);
|
|
11056
|
+
let current;
|
|
11057
|
+
return (raw) => {
|
|
11058
|
+
const parsed = TeamAdoptSchema.safeParse(raw);
|
|
11059
|
+
if (!parsed.success) return { error: "Invalid team connection request" };
|
|
11060
|
+
if (process.env.VH_TEAM_SCOPE_FILE) return { error: "Assigned team members cannot create or join another team" };
|
|
11061
|
+
let path;
|
|
11062
|
+
try {
|
|
11063
|
+
path = `${teamScopePath(sessionId)}.adopt.json`;
|
|
11064
|
+
} catch {
|
|
11065
|
+
return { error: "A managed session identity is required" };
|
|
11066
|
+
}
|
|
11067
|
+
const input = parsed.data;
|
|
11068
|
+
const signature = JSON.stringify(input);
|
|
11069
|
+
if (current) {
|
|
11070
|
+
if (current.signature !== signature && current.safeToChange) current = void 0;
|
|
11071
|
+
else if (current.signature !== signature) return { error: "Another team connection request already exists; retry the original request" };
|
|
11072
|
+
}
|
|
11073
|
+
if (current) {
|
|
11074
|
+
const result = current.result;
|
|
11075
|
+
if (result && "error" in result) current = void 0;
|
|
11076
|
+
return result ?? { status: "pending", requestId: input.requestId };
|
|
11077
|
+
}
|
|
11078
|
+
const operation = { signature };
|
|
11079
|
+
current = operation;
|
|
11080
|
+
void (async () => {
|
|
11081
|
+
let intent;
|
|
11082
|
+
try {
|
|
11083
|
+
intent = await retainIntent(path, input);
|
|
11084
|
+
const connected = await client.initialize(input, { resumeAdoption: true, expectedTeamId: intent.resolvedTeamId, onTeamResolved: (teamId) => retainTeam(path, input, teamId, intent?.guidanceDelivered) });
|
|
11085
|
+
const instructions = `${TEAM_SKILL}
|
|
11086
|
+
|
|
11087
|
+
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.`;
|
|
11088
|
+
if (!intent.guidanceDelivered) {
|
|
11089
|
+
const key = await waitForSessionKey(sessionId, 1e4);
|
|
11090
|
+
await sendUserMessage(sessionId, key, instructions, "teams", { localId: `teams-adopt-${input.requestId}`, sentFrom: "team" });
|
|
11091
|
+
await retainTeam(path, input, connected.team.id, true);
|
|
11092
|
+
}
|
|
11093
|
+
operation.result = { status: "connected", teamId: connected.team.id, botId: connected.botId, instructions };
|
|
11094
|
+
} catch (error) {
|
|
11095
|
+
if (error instanceof TeamConnectionPreflightError && intent?.fresh && !intent.resolvedTeamId) {
|
|
11096
|
+
await unlink(path).catch(() => {
|
|
11097
|
+
});
|
|
11098
|
+
operation.safeToChange = true;
|
|
11099
|
+
}
|
|
11100
|
+
operation.result = { error: error instanceof Error ? error.message : "Team connection failed; retry the same request", ...operation.safeToChange ? { safeToChange: true } : {} };
|
|
11101
|
+
}
|
|
11102
|
+
})();
|
|
11103
|
+
return { status: "pending", requestId: input.requestId };
|
|
11104
|
+
};
|
|
11105
|
+
}
|
|
11106
|
+
|
|
10903
11107
|
const PERSONAL_MEMORY_SOFT_LIMIT_CHARS = 2e3;
|
|
10904
11108
|
function headingTitle(line) {
|
|
10905
11109
|
const m = /^##(?!#)\s*(.*?)\s*$/.exec(line);
|
|
@@ -11543,6 +11747,11 @@ async function startHappyServer(client, options) {
|
|
|
11543
11747
|
resolve(new URL(`http://127.0.0.1:${addr.port}`));
|
|
11544
11748
|
});
|
|
11545
11749
|
});
|
|
11750
|
+
const adoptionEnabled = !process.env.VH_TEAM_SCOPE_FILE;
|
|
11751
|
+
if (adoptionEnabled) {
|
|
11752
|
+
client.rpcHandlerManager.registerHandler("teams-adopt", createTeamAdoption(client.sessionId));
|
|
11753
|
+
client.updateMetadata((metadata) => ({ ...metadata, capabilities: [.../* @__PURE__ */ new Set([...metadata.capabilities ?? [], TEAMS_ADOPT_CAPABILITY])] }));
|
|
11754
|
+
}
|
|
11546
11755
|
logger.debug(`[happyMCP] server:ready sessionId=${client.sessionId} url=${baseUrl.toString()}`);
|
|
11547
11756
|
return {
|
|
11548
11757
|
url: baseUrl.toString(),
|
|
@@ -11556,6 +11765,7 @@ async function startHappyServer(client, options) {
|
|
|
11556
11765
|
],
|
|
11557
11766
|
stop: () => {
|
|
11558
11767
|
logger.debug(`[happyMCP] server:stop sessionId=${client.sessionId}`);
|
|
11768
|
+
if (adoptionEnabled) client.rpcHandlerManager.unregisterHandler("teams-adopt");
|
|
11559
11769
|
server.close();
|
|
11560
11770
|
}
|
|
11561
11771
|
};
|
|
@@ -11812,7 +12022,7 @@ function registerSideQuestionHandler(rpc, deps) {
|
|
|
11812
12022
|
const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
|
|
11813
12023
|
const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
|
|
11814
12024
|
const run = deps.run ?? (async (input) => {
|
|
11815
|
-
const { query } = await import('./index-
|
|
12025
|
+
const { query } = await import('./index-CWPgxeLD.mjs');
|
|
11816
12026
|
return runSideQuestion(query, input);
|
|
11817
12027
|
});
|
|
11818
12028
|
const slots = /* @__PURE__ */ new Map();
|
|
@@ -15873,6 +16083,7 @@ function buildCodexTurnPrompt(opts) {
|
|
|
15873
16083
|
parts.push(opts.message);
|
|
15874
16084
|
if (opts.includeTitleInstruction) {
|
|
15875
16085
|
parts.push(CHANGE_TITLE_INSTRUCTION);
|
|
16086
|
+
parts.push(BUILTIN_TODO_DISCOVERY);
|
|
15876
16087
|
}
|
|
15877
16088
|
return parts.join("\n\n");
|
|
15878
16089
|
}
|
|
@@ -16765,7 +16976,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
16765
16976
|
process.exit(0);
|
|
16766
16977
|
} else if (subcommand === "install-terminal-hooks") {
|
|
16767
16978
|
try {
|
|
16768
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-
|
|
16979
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await import('./installTerminalHooks-cpuDExTT.mjs');
|
|
16769
16980
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
16770
16981
|
if (command.action === "help") {
|
|
16771
16982
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -16782,7 +16993,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
16782
16993
|
}
|
|
16783
16994
|
} else if (subcommand === "spawn") {
|
|
16784
16995
|
try {
|
|
16785
|
-
const { handleSpawnCommand } = await import('./spawn-
|
|
16996
|
+
const { handleSpawnCommand } = await import('./spawn-DMx1JKXo.mjs');
|
|
16786
16997
|
await handleSpawnCommand(args.slice(1));
|
|
16787
16998
|
} catch (error) {
|
|
16788
16999
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -16794,7 +17005,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
16794
17005
|
return;
|
|
16795
17006
|
} else if (subcommand === "sessions") {
|
|
16796
17007
|
try {
|
|
16797
|
-
const { handleSessionsCommand } = await import('./sessions-
|
|
17008
|
+
const { handleSessionsCommand } = await import('./sessions-D06cLJ7f.mjs');
|
|
16798
17009
|
await handleSessionsCommand(args.slice(1));
|
|
16799
17010
|
} catch (error) {
|
|
16800
17011
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -16806,7 +17017,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
16806
17017
|
return;
|
|
16807
17018
|
} else if (subcommand === "send") {
|
|
16808
17019
|
try {
|
|
16809
|
-
const { handleSendCommand } = await import('./send-
|
|
17020
|
+
const { handleSendCommand } = await import('./send-D2xX42zg.mjs');
|
|
16810
17021
|
await handleSendCommand(args.slice(1));
|
|
16811
17022
|
} catch (error) {
|
|
16812
17023
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -16912,9 +17123,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
16912
17123
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
16913
17124
|
const projectId = args[3];
|
|
16914
17125
|
try {
|
|
16915
|
-
const { saveGoogleCloudProjectToConfig } = await import('./config-
|
|
16916
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./limits-
|
|
16917
|
-
const { ApiClient: ApiClient2 } = await import('./types-
|
|
17126
|
+
const { saveGoogleCloudProjectToConfig } = await import('./config-DotNknpP.mjs');
|
|
17127
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await import('./limits-D2XM3dvN.mjs').then(function (n) { return n.W; });
|
|
17128
|
+
const { ApiClient: ApiClient2 } = await import('./types-Df_vXvzD.mjs').then(function (n) { return n._; });
|
|
16918
17129
|
let userEmail = void 0;
|
|
16919
17130
|
try {
|
|
16920
17131
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -16945,7 +17156,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
16945
17156
|
}
|
|
16946
17157
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
16947
17158
|
try {
|
|
16948
|
-
const { readGeminiLocalConfig } = await import('./config-
|
|
17159
|
+
const { readGeminiLocalConfig } = await import('./config-DotNknpP.mjs');
|
|
16949
17160
|
const config = readGeminiLocalConfig();
|
|
16950
17161
|
if (config.googleCloudProject) {
|
|
16951
17162
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -16985,7 +17196,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
16985
17196
|
process.exit(0);
|
|
16986
17197
|
}
|
|
16987
17198
|
try {
|
|
16988
|
-
const { runGemini } = await import('./runGemini-
|
|
17199
|
+
const { runGemini } = await import('./runGemini-BY7uA-Uk.mjs');
|
|
16989
17200
|
let startedBy = void 0;
|
|
16990
17201
|
for (let i = 1; i < args.length; i++) {
|
|
16991
17202
|
if (args[i] === "--started-by") {
|
|
@@ -17015,7 +17226,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17015
17226
|
}
|
|
17016
17227
|
};
|
|
17017
17228
|
try {
|
|
17018
|
-
const { runAcp, resolveAcpAgentConfig } = await import('./index-
|
|
17229
|
+
const { runAcp, resolveAcpAgentConfig } = await import('./index-C2kblG8-.mjs');
|
|
17019
17230
|
const parsed = parsePiRunnerArgs(args.slice(1));
|
|
17020
17231
|
const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
|
|
17021
17232
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
@@ -17042,7 +17253,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17042
17253
|
return;
|
|
17043
17254
|
} else if (subcommand === "acp") {
|
|
17044
17255
|
try {
|
|
17045
|
-
const { runAcp, resolveAcpAgentConfig } = await import('./index-
|
|
17256
|
+
const { runAcp, resolveAcpAgentConfig } = await import('./index-C2kblG8-.mjs');
|
|
17046
17257
|
let startedBy = void 0;
|
|
17047
17258
|
let verbose = false;
|
|
17048
17259
|
const acpArgs = [];
|
|
@@ -17082,7 +17293,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17082
17293
|
return;
|
|
17083
17294
|
} else if (subcommand === "openclaw") {
|
|
17084
17295
|
try {
|
|
17085
|
-
const { runOpenClaw } = await import('./runOpenClaw-
|
|
17296
|
+
const { runOpenClaw } = await import('./runOpenClaw-Be_U4DHZ.mjs');
|
|
17086
17297
|
let startedBy = void 0;
|
|
17087
17298
|
let verbose = false;
|
|
17088
17299
|
let gatewayUrl;
|
|
@@ -17131,9 +17342,18 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17131
17342
|
process.exit(1);
|
|
17132
17343
|
}
|
|
17133
17344
|
return;
|
|
17345
|
+
} else if (subcommand === "todo") {
|
|
17346
|
+
try {
|
|
17347
|
+
const { handleTodoCommand } = await import('./todo-hKSIY23F.mjs');
|
|
17348
|
+
await handleTodoCommand(args.slice(1));
|
|
17349
|
+
} catch (error) {
|
|
17350
|
+
console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
|
|
17351
|
+
process.exitCode = 1;
|
|
17352
|
+
}
|
|
17353
|
+
return;
|
|
17134
17354
|
} else if (subcommand === "teams") {
|
|
17135
17355
|
try {
|
|
17136
|
-
const { handleTeamsCommand } = await import('./teams-
|
|
17356
|
+
const { handleTeamsCommand } = await import('./teams-D7ubdfTY.mjs');
|
|
17137
17357
|
await handleTeamsCommand(args.slice(1));
|
|
17138
17358
|
} catch (error) {
|
|
17139
17359
|
console.error(error instanceof Error ? error.message : "Teams command failed");
|
|
@@ -17142,7 +17362,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
17142
17362
|
return;
|
|
17143
17363
|
} else if (subcommand === "mcp" && args.length === 1) {
|
|
17144
17364
|
try {
|
|
17145
|
-
const { handleMcpCommand } = await import('./mcp-
|
|
17365
|
+
const { handleMcpCommand } = await import('./mcp-CpUrsnoC.mjs');
|
|
17146
17366
|
await handleMcpCommand();
|
|
17147
17367
|
} catch (error) {
|
|
17148
17368
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -17369,6 +17589,7 @@ ${chalk.bold("Usage:")}
|
|
|
17369
17589
|
Install optional Claude terminal mirror hooks
|
|
17370
17590
|
(add --remove to uninstall them)
|
|
17371
17591
|
very-happy connect Connect AI vendor API keys
|
|
17592
|
+
very-happy todo Built-in Todos and official agent skill (todo --help)
|
|
17372
17593
|
very-happy sandbox Configure and manage OS-level sandboxing
|
|
17373
17594
|
very-happy notify Send push notification
|
|
17374
17595
|
very-happy mcp Stdio MCP server exposing copy_to_clipboard for a
|
|
@@ -17503,4 +17724,4 @@ ${chalk.bold("Examples:")}
|
|
|
17503
17724
|
}
|
|
17504
17725
|
}
|
|
17505
17726
|
|
|
17506
|
-
export { ALLOWED_SPAWN_PERMISSION_MODES as A, hashObject as B, startHappyServer as C, DEFAULT_RECENT_LIMIT as D,
|
|
17727
|
+
export { ALLOWED_SPAWN_PERMISSION_MODES as A, hashObject as B, startHappyServer as C, DEFAULT_RECENT_LIMIT as D, TitleGenerator as E, BasePermissionHandler as F, GEMINI_MODEL_ENV as G, writeSessionModeFile as H, normalizeAcpPermissionMode as I, removeSessionModeFile as J, GEMINI_API_KEY_ENV as K, GOOGLE_API_KEY_ENV as L, MAX_READ_LIMIT as M, BaseReasoningProcessor as N, MessageBuffer as O, PI_TEAMS_EXTENSION as P, CHANGE_TITLE_INSTRUCTION as Q, SPAWN_AGENTS as S, TEAM_SKILL as T, sessionWebUrl as a, sanitizeSpawnPermissionMode as b, checkIfDaemonRunningAndCleanupStaleState as c, sendUserMessage as d, listSessions as e, stopSession as f, resolvePermissionRequest as g, archiveSession as h, isValidSpawnOrigin as i, DEFAULT_GEMINI_MODEL as j, setTerminalTitleViaDaemon as k, listAccountSessions as l, registerAssistantSessionTools as m, initialMachineMetadata as n, createSessionMetadata as o, pushClipboardViaDaemon as p, query as q, readSessionTranscript as r, spawnDaemonSession as s, tmuxSupportsSessionEnv as t, setupOfflineReconnection as u, notifyDaemonSessionStarted as v, waitForSessionKey as w, MessageQueue2 as x, registerKillSessionHandler as y, StreamRelay as z };
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-
|
|
2
|
-
export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-
|
|
3
|
-
import { c as configuration,
|
|
4
|
-
import { A as AcpSessionManager } from './AcpSessionManager-
|
|
1
|
+
import { D as DefaultTransport, A as AcpBackend } from './AcpBackend-B9_vB_mY.mjs';
|
|
2
|
+
export { a as DEFAULT_IDLE_TIMEOUT_MS, b as DEFAULT_TOOL_CALL_TIMEOUT_MS, e as extractErrorDetail, f as formatDuration, c as formatDurationMinutes, h as handleAgentMessageChunk, d as handleAgentThoughtChunk, g as handleLegacyMessageChunk, i as handlePlanUpdate, j as handleThinkingUpdate, k as handleToolCall, l as handleToolCallUpdate, p as parseArgsFromContent } from './AcpBackend-B9_vB_mY.mjs';
|
|
3
|
+
import { c as configuration, g as readSettings, i as encodeBase64, l as logger } from './limits-D2XM3dvN.mjs';
|
|
4
|
+
import { A as AcpSessionManager } from './AcpSessionManager-HsxKXreC.mjs';
|
|
5
|
+
import { g as connectionState, A as ApiClient, p as projectPath, h as BUILTIN_TODO_DISCOVERY } from './types-Df_vXvzD.mjs';
|
|
5
6
|
import { mkdir, chmod, writeFile, rename } from 'node:fs/promises';
|
|
6
7
|
import { randomUUID } from 'node:crypto';
|
|
7
8
|
import { join } from 'node:path';
|
|
8
|
-
import { P as PI_TEAMS_EXTENSION } from './
|
|
9
|
-
import { f as connectionState, A as ApiClient, p as projectPath } from './types-DLDkfrTC.mjs';
|
|
10
|
-
import { n as initialMachineMetadata, o as createSessionMetadata, u as setupOfflineReconnection, v as notifyDaemonSessionStarted, z as StreamRelay, x as MessageQueue2, B as hashObject, C as startHappyServer, T as TitleGenerator, y as registerKillSessionHandler, E as BasePermissionHandler, F as writeSessionModeFile, H as normalizeAcpPermissionMode, I as removeSessionModeFile } from './index-CrSifgJM.mjs';
|
|
9
|
+
import { P as PI_TEAMS_EXTENSION, n as initialMachineMetadata, o as createSessionMetadata, u as setupOfflineReconnection, v as notifyDaemonSessionStarted, z as StreamRelay, x as MessageQueue2, B as hashObject, C as startHappyServer, E as TitleGenerator, y as registerKillSessionHandler, F as BasePermissionHandler, H as writeSessionModeFile, I as normalizeAcpPermissionMode, J as removeSessionModeFile } from './index-B1qzJIMw.mjs';
|
|
11
10
|
import 'node:child_process';
|
|
12
11
|
import '@agentclientprotocol/sdk';
|
|
13
12
|
import 'node:fs';
|
|
@@ -33,7 +32,7 @@ import 'fs';
|
|
|
33
32
|
import 'node:readline';
|
|
34
33
|
import '@anthropic-ai/sandbox-runtime';
|
|
35
34
|
import 'expo-server-sdk';
|
|
36
|
-
import './agentGuidance-
|
|
35
|
+
import './agentGuidance-CTyzeLCQ.mjs';
|
|
37
36
|
import 'ink';
|
|
38
37
|
import 'react';
|
|
39
38
|
import '@anthropic-ai/claude-agent-sdk';
|
|
@@ -1074,6 +1073,7 @@ async function runAcp(opts) {
|
|
|
1074
1073
|
logAcp("muted", `Outgoing models from ${opts.agentName}: not reported yet`);
|
|
1075
1074
|
}
|
|
1076
1075
|
}
|
|
1076
|
+
let todoDiscoverySent = false;
|
|
1077
1077
|
while (!shouldExit) {
|
|
1078
1078
|
const waitSignal = abortController.signal;
|
|
1079
1079
|
const batch = await messageQueue.waitForMessagesAndGetAsString(waitSignal);
|
|
@@ -1100,7 +1100,11 @@ async function runAcp(opts) {
|
|
|
1100
1100
|
if (typeof batch.mode.model === "string" && batch.mode.model.length > 0) {
|
|
1101
1101
|
await switchModelIfRequested(batch.mode.model);
|
|
1102
1102
|
}
|
|
1103
|
-
|
|
1103
|
+
const prompt = todoDiscoverySent ? batch.message : `${batch.message}
|
|
1104
|
+
|
|
1105
|
+
${BUILTIN_TODO_DISCOVERY}`;
|
|
1106
|
+
await backend.sendPrompt(acpSessionId, prompt);
|
|
1107
|
+
todoDiscoverySent = true;
|
|
1104
1108
|
await turnEnded;
|
|
1105
1109
|
sendEnvelopes(sessionManager.endTurn("completed"));
|
|
1106
1110
|
streamRelay.endTurn();
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { q as query } from './index-
|
|
1
|
+
import { q as query } from './index-B1qzJIMw.mjs';
|
|
2
2
|
export { AbortError } from '@anthropic-ai/claude-agent-sdk';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'node:os';
|
|
5
5
|
import 'node:crypto';
|
|
6
|
-
import './types-
|
|
6
|
+
import './types-Df_vXvzD.mjs';
|
|
7
7
|
import 'axios';
|
|
8
|
-
import './limits-
|
|
8
|
+
import './limits-D2XM3dvN.mjs';
|
|
9
9
|
import 'node:fs/promises';
|
|
10
10
|
import 'node:fs';
|
|
11
11
|
import 'node:path';
|
|
@@ -29,7 +29,7 @@ import 'fs';
|
|
|
29
29
|
import 'node:readline';
|
|
30
30
|
import '@anthropic-ai/sandbox-runtime';
|
|
31
31
|
import 'expo-server-sdk';
|
|
32
|
-
import './agentGuidance-
|
|
32
|
+
import './agentGuidance-CTyzeLCQ.mjs';
|
|
33
33
|
import 'ink';
|
|
34
34
|
import 'react';
|
|
35
35
|
import 'ps-list';
|