very-happy-cli 0.2.151 → 0.2.152
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-BjTA5gUB.mjs → AcpBackend-Bs3wwYbt.mjs} +2 -2
- package/dist/{AcpBackend-blE9IEod.cjs → AcpBackend-CogiKCng.cjs} +2 -2
- package/dist/{AcpSessionManager-D-9mrp40.mjs → AcpSessionManager-BT8PJMEm.mjs} +1 -1
- package/dist/{AcpSessionManager-bF8PYu_B.cjs → AcpSessionManager-BazkBuFo.cjs} +9 -9
- package/dist/agentGuidance-CqBn77AI.cjs +553 -0
- package/dist/agentGuidance-Daxn5Nvj.mjs +529 -0
- package/dist/{agentHome-CeFDNzvq.mjs → agentHome-CCYfs8Ec.mjs} +3 -3
- package/dist/{agentHome-D6MSfwnp.cjs → agentHome-CpJjrQZc.cjs} +3 -3
- package/dist/auto-DV5emt1-.mjs +466 -0
- package/dist/auto-DncmTDvw.cjs +472 -0
- package/dist/codex/happyMcpStdioBridge.cjs +4 -2
- package/dist/codex/happyMcpStdioBridge.mjs +4 -2
- package/dist/{config-C-A1XF62.mjs → config-DbKpQpdL.mjs} +5 -5
- package/dist/{config-Cadw1sAk.cjs → config-DeJgSMh-.cjs} +5 -5
- package/dist/{index-CIyjJy8D.mjs → index-BauTv2jB.mjs} +712 -39
- package/dist/{index-DYQgcgL2.mjs → index-CN7OF2cU.mjs} +5 -5
- package/dist/{index-vyRqLjDv.cjs → index-CRaJ9k2p.cjs} +5 -5
- package/dist/{index-DEp6CmmS.mjs → index-DahaLbu4.mjs} +19 -19
- package/dist/{index-CqtfRzug.cjs → index-ZIW1jrYm.cjs} +750 -71
- package/dist/{index-BKGspSWk.cjs → index-imt4mC41.cjs} +19 -19
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/install-C1K3nrxF.mjs +114 -0
- package/dist/install-CDR3qBhs.cjs +118 -0
- package/dist/{installTerminalHooks-Bf_adbl3.cjs → installTerminalHooks-BoDxpaBO.cjs} +5 -5
- package/dist/{installTerminalHooks-Ch_yTtEA.mjs → installTerminalHooks-VvmlO6Ue.mjs} +5 -5
- package/dist/lib.cjs +3 -3
- package/dist/lib.mjs +3 -3
- package/dist/limits-BNTWyUaZ.cjs +2175 -0
- package/dist/limits-CKR_HJnO.mjs +2080 -0
- package/dist/{mcp-CMxEZ6-0.cjs → mcp-CCKCKL6l.cjs} +5 -5
- package/dist/{mcp-zu8n8TkR.mjs → mcp-D4dAo5BQ.mjs} +5 -5
- package/dist/{piRuntime-D3ny0mVg.cjs → piRuntime-Bn5ypbjH.cjs} +2 -2
- package/dist/{piRuntime-Cu6cXZ6N.mjs → piRuntime-CW-XA4rz.mjs} +2 -2
- package/dist/{piTerminal-kDSd_r9X.cjs → piTerminal-B7K75aXB.cjs} +6 -6
- package/dist/{piTerminal-M677UP7y.mjs → piTerminal-BLSXK1u2.mjs} +6 -6
- package/dist/{runGemini-DuwdVV1O.cjs → runGemini-Bgg1BzDK.cjs} +7 -7
- package/dist/{runGemini-DvJwQVGp.mjs → runGemini-D5N11LxO.mjs} +7 -7
- package/dist/{runOpenClaw-BsvtCE_H.cjs → runOpenClaw-B9qWHybc.cjs} +6 -6
- package/dist/{runOpenClaw-BG82bF18.mjs → runOpenClaw-CCpyKbrn.mjs} +6 -6
- package/dist/{send-o6WM-1G8.mjs → send-C44kcXz5.mjs} +5 -5
- package/dist/{send-aUkjhey7.cjs → send-wl9ei8yG.cjs} +5 -5
- package/dist/{sessions-DlU3foY_.mjs → sessions-DXJEcUg6.mjs} +5 -5
- package/dist/{sessions-B3vP18kz.cjs → sessions-Tad8elmy.cjs} +5 -5
- package/dist/{spawn-DxHIIqhi.mjs → spawn-BOlb5y1_.mjs} +6 -31
- package/dist/{spawn-DH6_p4-f.cjs → spawn-DA8WAFmm.cjs} +7 -32
- package/dist/{teams-DoAA_CcN.mjs → teams-Bs8lI887.mjs} +15 -72
- package/dist/{teams-BW8D1n3o.cjs → teams-qVLrFcdd.cjs} +13 -70
- package/dist/{todo-Bcc2XxGh.cjs → todo-mCMoGjJk.cjs} +4 -23
- package/dist/{todo-BhJbG5eq.mjs → todo-nzsqGZqp.mjs} +2 -21
- package/dist/{types-CPubg05Z.cjs → types-CN28qJl7.cjs} +31 -856
- package/dist/{types-BN3eiipi.mjs → types-xKrxbCRv.mjs} +204 -1017
- package/package.json +7 -7
- package/dist/agentGuidance-BXa9ikrZ.cjs +0 -267
- package/dist/agentGuidance-Dvo3cZMW.mjs +0 -251
- package/dist/limits-DS-bnYYp.mjs +0 -1165
- package/dist/limits-DwcY3kyi.cjs +0 -1236
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var os = require('node:os');
|
|
5
5
|
var node_crypto = require('node:crypto');
|
|
6
|
-
var index = require('./types-
|
|
7
|
-
var persistence = require('./limits-
|
|
6
|
+
var index = require('./types-CN28qJl7.cjs');
|
|
7
|
+
var persistence = require('./limits-BNTWyUaZ.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
12
|
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
13
|
-
var agentGuidance = require('./agentGuidance-
|
|
13
|
+
var agentGuidance = require('./agentGuidance-CqBn77AI.cjs');
|
|
14
14
|
var promises = require('node:fs/promises');
|
|
15
15
|
var fs = require('fs/promises');
|
|
16
16
|
var ink = require('ink');
|
|
@@ -492,7 +492,7 @@ function shouldIncludeCoAuthoredBy() {
|
|
|
492
492
|
|
|
493
493
|
const BASE_SYSTEM_PROMPT = (() => agentGuidance.trimIdent(`
|
|
494
494
|
This chat is titled automatically from the user's first message. Call "mcp__happy__change_title" only when the topic has clearly moved on or the current title is too generic to find this chat later. Do not call it as a ritual at the start of a chat, and not for a quick question you can just answer.
|
|
495
|
-
`))() + "\n\n" + agentGuidance.AGENT_GUIDANCE + "\n\n" +
|
|
495
|
+
`))() + "\n\n" + agentGuidance.AGENT_GUIDANCE + "\n\n" + persistence.BUILTIN_TODO_DISCOVERY;
|
|
496
496
|
const CO_AUTHORED_CREDITS = (() => agentGuidance.trimIdent(`
|
|
497
497
|
When you yourself create a git commit, instead of just giving co-credit to Claude, also give credit to Happy like so:
|
|
498
498
|
|
|
@@ -3507,7 +3507,7 @@ class StreamRelay {
|
|
|
3507
3507
|
}
|
|
3508
3508
|
this.pending.text += text;
|
|
3509
3509
|
this.pending.bytes += Buffer.byteLength(text, "utf8");
|
|
3510
|
-
if (this.pending.bytes >= STREAM_FLUSH_MAX_BYTES || this.pending.text.length >=
|
|
3510
|
+
if (this.pending.bytes >= STREAM_FLUSH_MAX_BYTES || this.pending.text.length >= persistence.STREAM_DELTA_MAX_CHARS) {
|
|
3511
3511
|
this.flushPending();
|
|
3512
3512
|
return;
|
|
3513
3513
|
}
|
|
@@ -5402,8 +5402,8 @@ ${typeLabels[type] || type}:`));
|
|
|
5402
5402
|
}
|
|
5403
5403
|
console.log(chalk.gray(" An external claude command is only needed for native terminal/mirror use."));
|
|
5404
5404
|
try {
|
|
5405
|
-
const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-
|
|
5406
|
-
const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-
|
|
5405
|
+
const { resolveAgentHomesForCli } = await Promise.resolve().then(function () { return require('./agentHome-CpJjrQZc.cjs'); });
|
|
5406
|
+
const { describeAgentHome } = await Promise.resolve().then(function () { return require('./types-CN28qJl7.cjs'); }).then(function (n) { return n.index; });
|
|
5407
5407
|
const homes = await resolveAgentHomesForCli();
|
|
5408
5408
|
console.log(chalk.green(`\u2713 Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}`));
|
|
5409
5409
|
console.log(chalk.green(`\u2713 Codex home: ${describeAgentHome(homes.codexHome)}`));
|
|
@@ -5514,7 +5514,7 @@ async function registryVersion(name) {
|
|
|
5514
5514
|
return typeof data.version === "string" ? stableVersion(data.version) : null;
|
|
5515
5515
|
}
|
|
5516
5516
|
async function detectAgentVersions(deps = { probe: probeAgentVersion, registryVersion }, now = Date.now()) {
|
|
5517
|
-
const agents = await Promise.all(
|
|
5517
|
+
const agents = await Promise.all(persistence.AGENT_VERSION_SOURCES.map(async (source) => {
|
|
5518
5518
|
const local = source.command ? await deps.probe(source.command).catch(() => ({ version: null, missing: false })) : { version: stableVersion(persistence.packageJson.dependencies["@anthropic-ai/claude-agent-sdk"]), missing: false };
|
|
5519
5519
|
if (local.missing) return { id: source.id, installed: null, latest: null, status: "not-installed" };
|
|
5520
5520
|
const latest = await deps.registryVersion(source.package).catch(() => null);
|
|
@@ -6230,7 +6230,7 @@ const DENIED_BASENAME_PATTERNS = [
|
|
|
6230
6230
|
const DENIED_PATH_SUFFIXES = [
|
|
6231
6231
|
`${path.sep}.git${path.sep}config`
|
|
6232
6232
|
];
|
|
6233
|
-
function expandHome(input, home) {
|
|
6233
|
+
function expandHome$1(input, home) {
|
|
6234
6234
|
if (input === "~") return home;
|
|
6235
6235
|
if (input.startsWith(`~${path.sep}`) || input.startsWith("~/")) {
|
|
6236
6236
|
return path.resolve(home, input.slice(2));
|
|
@@ -6253,7 +6253,7 @@ function checkPreviewPath(input, opts) {
|
|
|
6253
6253
|
if (input.includes("\0")) {
|
|
6254
6254
|
return { resolved: "", deniedReason: "path contains a NUL byte" };
|
|
6255
6255
|
}
|
|
6256
|
-
const expanded = expandHome(input.trim(), home);
|
|
6256
|
+
const expanded = expandHome$1(input.trim(), home);
|
|
6257
6257
|
const resolved = path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(cwd, expanded);
|
|
6258
6258
|
for (const dir of DENIED_HOME_DIRS) {
|
|
6259
6259
|
if (isUnder(resolved, path.resolve(home, dir))) {
|
|
@@ -8144,7 +8144,7 @@ function parseJsonObject(text) {
|
|
|
8144
8144
|
return null;
|
|
8145
8145
|
}
|
|
8146
8146
|
}
|
|
8147
|
-
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-
|
|
8147
|
+
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-ZIW1jrYm.cjs', document.baseURI).href))).resolve(s)) {
|
|
8148
8148
|
const platformArch = `${platform}-${arch}`;
|
|
8149
8149
|
const candidates = [
|
|
8150
8150
|
`@anthropic-ai/claude-agent-sdk-${platformArch}/claude`,
|
|
@@ -9539,11 +9539,14 @@ function agentPiece(body) {
|
|
|
9539
9539
|
}
|
|
9540
9540
|
return null;
|
|
9541
9541
|
}
|
|
9542
|
-
function
|
|
9542
|
+
function userPromptText(body) {
|
|
9543
|
+
return isUserPrompt(body) ? body.content.text : null;
|
|
9544
|
+
}
|
|
9545
|
+
function analyzeLatestTurn(entries, options = {}) {
|
|
9543
9546
|
const lastSeq = entries.length > 0 ? entries[entries.length - 1].seq : 0;
|
|
9544
9547
|
let userIndex = -1;
|
|
9545
9548
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
9546
|
-
if (isUserPrompt(entries[i].body)) {
|
|
9549
|
+
if (isUserPrompt(entries[i].body) && (!options.anchor || options.anchor(entries[i].body))) {
|
|
9547
9550
|
userIndex = i;
|
|
9548
9551
|
break;
|
|
9549
9552
|
}
|
|
@@ -9557,6 +9560,10 @@ function analyzeLatestTurn(entries) {
|
|
|
9557
9560
|
const emitsStarts = entries.some((entry) => sessionEnvelope(entry.body)?.ev?.t === "turn-start");
|
|
9558
9561
|
for (let i = userIndex + 1; i < entries.length; i++) {
|
|
9559
9562
|
const body = entries[i].body;
|
|
9563
|
+
if (options.anchor && isUserPrompt(body)) {
|
|
9564
|
+
if (ended) break;
|
|
9565
|
+
continue;
|
|
9566
|
+
}
|
|
9560
9567
|
const env = sessionEnvelope(body);
|
|
9561
9568
|
if (env?.ev?.t === "turn-start") {
|
|
9562
9569
|
lastMarker = "start";
|
|
@@ -10049,7 +10056,7 @@ function readReceipt(home, id) {
|
|
|
10049
10056
|
throw error;
|
|
10050
10057
|
}
|
|
10051
10058
|
}
|
|
10052
|
-
function writeReceipt(home, receipt) {
|
|
10059
|
+
function writeReceipt$1(home, receipt) {
|
|
10053
10060
|
persistence.ensurePrivateDirectorySync(path.join(home, "teams", "effects"));
|
|
10054
10061
|
const target = receiptPath(home, receipt.operationId);
|
|
10055
10062
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
@@ -10126,7 +10133,7 @@ function createTeamWorker(deps) {
|
|
|
10126
10133
|
const action = async (teamId, requestId, value) => (await http.post(`/v1/teams/${encodeURIComponent(teamId)}/actions`, { requestId, action: value })).data;
|
|
10127
10134
|
async function complete(op, receipt) {
|
|
10128
10135
|
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 } : {} });
|
|
10129
|
-
writeReceipt(home, { ...receipt, phase: "completed" });
|
|
10136
|
+
writeReceipt$1(home, { ...receipt, phase: "completed" });
|
|
10130
10137
|
}
|
|
10131
10138
|
async function execute(op) {
|
|
10132
10139
|
let receipt = readReceipt(home, op.id);
|
|
@@ -10143,7 +10150,7 @@ function createTeamWorker(deps) {
|
|
|
10143
10150
|
op = claimed.operation;
|
|
10144
10151
|
credential = claimed.credential;
|
|
10145
10152
|
receipt = { operationId: op.id, teamId: op.teamId, claimId: op.claimId, phase: "prepared" };
|
|
10146
|
-
writeReceipt(home, receipt);
|
|
10153
|
+
writeReceipt$1(home, receipt);
|
|
10147
10154
|
}
|
|
10148
10155
|
if (receipt.phase === "completed") return;
|
|
10149
10156
|
try {
|
|
@@ -10156,7 +10163,7 @@ function createTeamWorker(deps) {
|
|
|
10156
10163
|
if (!task) throw new Error("Task state unavailable; refusing to start");
|
|
10157
10164
|
if (task.currentAttemptId !== op.attemptId || ["done", "cancelled"].includes(task.status)) {
|
|
10158
10165
|
await action(op.teamId, `cancelled-before-spawn-${op.id}`, { type: "fail-operation", operationId: op.id, machineId: deps.machineId, claimId: receipt.claimId, error: "task_closed_before_spawn" });
|
|
10159
|
-
writeReceipt(home, { ...receipt, phase: "completed" });
|
|
10166
|
+
writeReceipt$1(home, { ...receipt, phase: "completed" });
|
|
10160
10167
|
return;
|
|
10161
10168
|
}
|
|
10162
10169
|
if (!op.directory) throw new Error("No repository selected for worker");
|
|
@@ -10166,17 +10173,17 @@ function createTeamWorker(deps) {
|
|
|
10166
10173
|
const scopeFile = path.join(scopes, `${op.id}.json`);
|
|
10167
10174
|
persistence.writePrivateFileSync(scopeFile, JSON.stringify({ serverUrl: server, scopeToken: credential.token, teamId: op.teamId, botId: op.botId, taskId: op.taskId, attemptId: op.attemptId }));
|
|
10168
10175
|
receipt = { ...receipt, ...resource, scopeFile, phase: "spawning" };
|
|
10169
|
-
writeReceipt(home, receipt);
|
|
10176
|
+
writeReceipt$1(home, receipt);
|
|
10170
10177
|
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 } });
|
|
10171
10178
|
if (spawned.type !== "success") throw new Error(spawned.type === "error" ? spawned.errorMessage : "Directory approval required");
|
|
10172
10179
|
receipt = { ...receipt, sessionId: spawned.sessionId, phase: "spawned" };
|
|
10173
|
-
writeReceipt(home, receipt);
|
|
10180
|
+
writeReceipt$1(home, receipt);
|
|
10174
10181
|
}
|
|
10175
10182
|
if (receipt.phase === "spawning") {
|
|
10176
10183
|
const matches = Object.entries(persistence.readPersistedSessions()).filter(([, entry]) => entry.metadata?.teamOperationId === op.id);
|
|
10177
10184
|
if (matches.length !== 1) throw new Error("Spawn outcome unknown; reconcile the worker before retrying");
|
|
10178
10185
|
receipt = { ...receipt, sessionId: matches[0][0], phase: "spawned" };
|
|
10179
|
-
writeReceipt(home, receipt);
|
|
10186
|
+
writeReceipt$1(home, receipt);
|
|
10180
10187
|
}
|
|
10181
10188
|
if (receipt.phase === "spawned") {
|
|
10182
10189
|
const current = (await http.get(`/v1/teams/${encodeURIComponent(op.teamId)}`)).data.team;
|
|
@@ -10191,14 +10198,14 @@ function createTeamWorker(deps) {
|
|
|
10191
10198
|
const key = await waitForSessionKey(receipt.sessionId, 1e4);
|
|
10192
10199
|
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 } : {} });
|
|
10193
10200
|
receipt = { ...receipt, phase: "delivered" };
|
|
10194
|
-
writeReceipt(home, receipt);
|
|
10201
|
+
writeReceipt$1(home, receipt);
|
|
10195
10202
|
}
|
|
10196
10203
|
await complete(op, receipt);
|
|
10197
10204
|
} else {
|
|
10198
10205
|
const team = (await http.get(`/v1/teams/${encodeURIComponent(op.teamId)}`)).data.team;
|
|
10199
10206
|
const latest = team.operations.find((candidate) => candidate.id === op.id);
|
|
10200
10207
|
if (latest?.status === "completed") {
|
|
10201
|
-
writeReceipt(home, { ...receipt, phase: "completed" });
|
|
10208
|
+
writeReceipt$1(home, { ...receipt, phase: "completed" });
|
|
10202
10209
|
return;
|
|
10203
10210
|
}
|
|
10204
10211
|
const bot = team.bots.find((candidate) => candidate.id === op.botId);
|
|
@@ -10328,6 +10335,643 @@ Use the teams tools to inspect current task state before acting. This message is
|
|
|
10328
10335
|
} };
|
|
10329
10336
|
}
|
|
10330
10337
|
|
|
10338
|
+
function resolveSpawnPermissionMode(agent, explicit) {
|
|
10339
|
+
return explicit ?? persistence.getAgentCodeDefaults(agent ?? "claude").permissionMode;
|
|
10340
|
+
}
|
|
10341
|
+
function outboundPermissionMode(agent, mode) {
|
|
10342
|
+
const key = persistence.normalizeAgentKey(agent ?? "claude");
|
|
10343
|
+
if ((key === "claude" || key === "pi") && mode === "yolo") return "bypassPermissions";
|
|
10344
|
+
return mode;
|
|
10345
|
+
}
|
|
10346
|
+
function resolveFirstMessageMeta(input) {
|
|
10347
|
+
const meta = {
|
|
10348
|
+
permissionMode: outboundPermissionMode(input.agent, input.permissionMode)
|
|
10349
|
+
};
|
|
10350
|
+
if (input.explicitModel !== void 0) {
|
|
10351
|
+
meta.model = input.explicitModel === "default" ? null : input.explicitModel;
|
|
10352
|
+
}
|
|
10353
|
+
if (persistence.normalizeAgentKey(input.agent ?? "claude") !== "claude") return meta;
|
|
10354
|
+
if (meta.model === void 0) {
|
|
10355
|
+
const model = persistence.getAgentCodeDefaults("claude").modelMode;
|
|
10356
|
+
const runnable = !persistence.isClaudeOpus55Model(model) || persistence.supportsClaudeOpus55({ capabilities: input.capabilities ?? null });
|
|
10357
|
+
meta.model = runnable && model !== "default" ? model : null;
|
|
10358
|
+
}
|
|
10359
|
+
meta.effort = null;
|
|
10360
|
+
return meta;
|
|
10361
|
+
}
|
|
10362
|
+
|
|
10363
|
+
function payloadJson(payload) {
|
|
10364
|
+
if (!payload) return void 0;
|
|
10365
|
+
try {
|
|
10366
|
+
return JSON.parse(payload);
|
|
10367
|
+
} catch {
|
|
10368
|
+
return void 0;
|
|
10369
|
+
}
|
|
10370
|
+
}
|
|
10371
|
+
function lookupPath(root, path) {
|
|
10372
|
+
let current = root;
|
|
10373
|
+
for (const segment of path) {
|
|
10374
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
10375
|
+
current = current[segment];
|
|
10376
|
+
}
|
|
10377
|
+
return current;
|
|
10378
|
+
}
|
|
10379
|
+
function scalar(value) {
|
|
10380
|
+
if (value === void 0 || value === null) return "";
|
|
10381
|
+
if (typeof value === "string") return value;
|
|
10382
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
10383
|
+
try {
|
|
10384
|
+
return JSON.stringify(value);
|
|
10385
|
+
} catch {
|
|
10386
|
+
return "";
|
|
10387
|
+
}
|
|
10388
|
+
}
|
|
10389
|
+
function formatNow(now, tz) {
|
|
10390
|
+
if (!tz) return new Date(now).toISOString();
|
|
10391
|
+
try {
|
|
10392
|
+
const parts = new Intl.DateTimeFormat("en-CA", { timeZone: tz, hourCycle: "h23", year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", timeZoneName: "longOffset" }).formatToParts(new Date(now));
|
|
10393
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
10394
|
+
const offset = get("timeZoneName").replace(/^GMT$/, "+00:00").replace(/^GMT/, "");
|
|
10395
|
+
return `${get("year")}-${get("month")}-${get("day")}T${get("hour")}:${get("minute")}:${get("second")}${offset || "Z"}`;
|
|
10396
|
+
} catch {
|
|
10397
|
+
return new Date(now).toISOString();
|
|
10398
|
+
}
|
|
10399
|
+
}
|
|
10400
|
+
function renderTemplate(text, context) {
|
|
10401
|
+
const json = payloadJson(context.payload);
|
|
10402
|
+
return text.replace(/\{\{\s*([a-zA-Z_][a-zA-Z0-9_.-]*)\s*\}\}/g, (whole, name) => {
|
|
10403
|
+
if (name === "payload") return context.payload ?? "";
|
|
10404
|
+
if (name.startsWith("payload.")) return scalar(lookupPath(json, name.slice("payload.".length).split(".")));
|
|
10405
|
+
if (name === "run.id") return context.runId;
|
|
10406
|
+
if (name === "automation.name") return context.automationName;
|
|
10407
|
+
if (name === "now") return formatNow(context.now ?? Date.now(), context.tz);
|
|
10408
|
+
return whole;
|
|
10409
|
+
});
|
|
10410
|
+
}
|
|
10411
|
+
function renderAction(action, context) {
|
|
10412
|
+
const r = (value) => renderTemplate(value, context);
|
|
10413
|
+
if (action.kind === "spawn") return { ...action, prompt: r(action.prompt) };
|
|
10414
|
+
if (action.kind === "send") return { ...action, prompt: r(action.prompt) };
|
|
10415
|
+
return { ...action, command: action.command.map(r), ...action.env ? { env: Object.fromEntries(Object.entries(action.env).map(([k, v]) => [k, r(v)])) } : {} };
|
|
10416
|
+
}
|
|
10417
|
+
function clipText(text, maxChars, keep = "head") {
|
|
10418
|
+
if (text.length <= maxChars) return text;
|
|
10419
|
+
return keep === "head" ? text.slice(0, maxChars) : text.slice(text.length - maxChars);
|
|
10420
|
+
}
|
|
10421
|
+
const DURATION_UNITS = { ms: 1, s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
|
|
10422
|
+
function parseDuration(raw) {
|
|
10423
|
+
const text = raw.trim();
|
|
10424
|
+
if (/^\d+$/.test(text)) return Number(text);
|
|
10425
|
+
const re = /(\d+(?:\.\d+)?)(ms|s|m|h|d)/gy;
|
|
10426
|
+
let total = 0;
|
|
10427
|
+
let matched = 0;
|
|
10428
|
+
let last = 0;
|
|
10429
|
+
let m;
|
|
10430
|
+
while ((m = re.exec(text)) !== null) {
|
|
10431
|
+
total += Number(m[1]) * DURATION_UNITS[m[2]];
|
|
10432
|
+
matched++;
|
|
10433
|
+
last = re.lastIndex;
|
|
10434
|
+
}
|
|
10435
|
+
if (matched === 0 || last !== text.length) throw new Error(`Invalid duration: ${raw} (use e.g. 90s, 5m, 1h30m, 2d)`);
|
|
10436
|
+
return Math.round(total);
|
|
10437
|
+
}
|
|
10438
|
+
function formatDuration(ms) {
|
|
10439
|
+
if (ms % 864e5 === 0) return `${ms / 864e5}d`;
|
|
10440
|
+
if (ms % 36e5 === 0) return `${ms / 36e5}h`;
|
|
10441
|
+
if (ms % 6e4 === 0) return `${ms / 6e4}m`;
|
|
10442
|
+
if (ms % 1e3 === 0) return `${ms / 1e3}s`;
|
|
10443
|
+
return `${ms}ms`;
|
|
10444
|
+
}
|
|
10445
|
+
function triggerFromFlags(flags, now = Date.now()) {
|
|
10446
|
+
const given = [flags.cron !== void 0, flags.every !== void 0, flags.at !== void 0, flags.manual === true].filter(Boolean).length;
|
|
10447
|
+
if (given === 0) {
|
|
10448
|
+
if (flags.tz !== void 0) throw new Error("--tz only applies with --cron");
|
|
10449
|
+
return void 0;
|
|
10450
|
+
}
|
|
10451
|
+
if (given > 1) throw new Error("Use exactly one of --cron, --every, --at, --manual");
|
|
10452
|
+
if (flags.cron !== void 0) {
|
|
10453
|
+
if (!flags.tz) throw new Error("--cron requires --tz <IANA zone> (e.g. Asia/Singapore)");
|
|
10454
|
+
return { kind: "cron", expr: flags.cron, tz: flags.tz };
|
|
10455
|
+
}
|
|
10456
|
+
if (flags.tz !== void 0) throw new Error("--tz only applies with --cron");
|
|
10457
|
+
if (flags.every !== void 0) return { kind: "interval", everyMs: parseDuration(flags.every), anchorAt: now };
|
|
10458
|
+
if (flags.at !== void 0) {
|
|
10459
|
+
const at = Date.parse(flags.at);
|
|
10460
|
+
if (!Number.isFinite(at)) throw new Error(`--at must be an ISO 8601 timestamp, got: ${flags.at}`);
|
|
10461
|
+
return { kind: "once", at };
|
|
10462
|
+
}
|
|
10463
|
+
return { kind: "manual" };
|
|
10464
|
+
}
|
|
10465
|
+
function describeTrigger(trigger) {
|
|
10466
|
+
switch (trigger.kind) {
|
|
10467
|
+
case "cron":
|
|
10468
|
+
return `cron ${trigger.expr} (${trigger.tz})`;
|
|
10469
|
+
case "interval":
|
|
10470
|
+
return `every ${formatDuration(trigger.everyMs)}`;
|
|
10471
|
+
case "once":
|
|
10472
|
+
return `once at ${new Date(trigger.at).toISOString()}`;
|
|
10473
|
+
default:
|
|
10474
|
+
return "manual";
|
|
10475
|
+
}
|
|
10476
|
+
}
|
|
10477
|
+
function describeAction(action) {
|
|
10478
|
+
if (action.kind === "spawn") return `spawn ${action.agent} in ${action.directory}${action.sticky ? ` (sticky ${action.sticky.key})` : ""}`;
|
|
10479
|
+
if (action.kind === "send") return `send to session ${action.sessionId}`;
|
|
10480
|
+
return `script ${action.command.join(" ")}`;
|
|
10481
|
+
}
|
|
10482
|
+
|
|
10483
|
+
const RECEIPT_RETENTION_MS = 7 * 864e5;
|
|
10484
|
+
const RECEIPT_MAX_ENTRIES = 2e3;
|
|
10485
|
+
function receiptsPath(home) {
|
|
10486
|
+
return path.join(home, "automation-receipts.json");
|
|
10487
|
+
}
|
|
10488
|
+
function readReceipts(home) {
|
|
10489
|
+
let raw;
|
|
10490
|
+
try {
|
|
10491
|
+
raw = node_fs.readFileSync(receiptsPath(home), "utf8");
|
|
10492
|
+
} catch (error) {
|
|
10493
|
+
if (error.code === "ENOENT") return {};
|
|
10494
|
+
throw error;
|
|
10495
|
+
}
|
|
10496
|
+
const parsed = JSON.parse(raw);
|
|
10497
|
+
if (!parsed || typeof parsed !== "object" || typeof parsed.receipts !== "object") throw new Error("Invalid automation receipts file");
|
|
10498
|
+
return parsed.receipts;
|
|
10499
|
+
}
|
|
10500
|
+
function writeReceipt(home, receipt, now = Date.now()) {
|
|
10501
|
+
if (!/^[a-zA-Z0-9_-]{1,128}$/.test(receipt.runId)) throw new Error("Invalid automation run id");
|
|
10502
|
+
const all = readReceipts(home);
|
|
10503
|
+
const next = { ...receipt, updatedAt: now };
|
|
10504
|
+
all[receipt.runId] = next;
|
|
10505
|
+
const entries = Object.values(all).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
10506
|
+
const kept = {};
|
|
10507
|
+
let finished = 0;
|
|
10508
|
+
for (const entry of entries) {
|
|
10509
|
+
if (entry.phase === "finished") {
|
|
10510
|
+
if (now - entry.updatedAt > RECEIPT_RETENTION_MS || finished >= RECEIPT_MAX_ENTRIES) continue;
|
|
10511
|
+
finished++;
|
|
10512
|
+
}
|
|
10513
|
+
kept[entry.runId] = entry;
|
|
10514
|
+
}
|
|
10515
|
+
const target = receiptsPath(home);
|
|
10516
|
+
persistence.ensurePrivateDirectorySync(path.dirname(target));
|
|
10517
|
+
const tmp = `${target}.${process.pid}.tmp`;
|
|
10518
|
+
persistence.writePrivateFileSync(tmp, JSON.stringify({ version: 1, receipts: kept }));
|
|
10519
|
+
const file = node_fs.openSync(tmp, "r");
|
|
10520
|
+
try {
|
|
10521
|
+
node_fs.fsyncSync(file);
|
|
10522
|
+
} finally {
|
|
10523
|
+
node_fs.closeSync(file);
|
|
10524
|
+
}
|
|
10525
|
+
node_fs.renameSync(tmp, target);
|
|
10526
|
+
if (process.platform !== "win32") {
|
|
10527
|
+
const directory = node_fs.openSync(path.dirname(target), "r");
|
|
10528
|
+
try {
|
|
10529
|
+
node_fs.fsyncSync(directory);
|
|
10530
|
+
} finally {
|
|
10531
|
+
node_fs.closeSync(directory);
|
|
10532
|
+
}
|
|
10533
|
+
}
|
|
10534
|
+
return next;
|
|
10535
|
+
}
|
|
10536
|
+
|
|
10537
|
+
const SCRIPT_KILL_GRACE_MS = 1e4;
|
|
10538
|
+
const SCRIPT_DRAIN_MS = 2e3;
|
|
10539
|
+
class TailBuffer {
|
|
10540
|
+
constructor(maxChars) {
|
|
10541
|
+
this.maxChars = maxChars;
|
|
10542
|
+
}
|
|
10543
|
+
text = "";
|
|
10544
|
+
push(chunk) {
|
|
10545
|
+
this.text += chunk;
|
|
10546
|
+
if (this.text.length > this.maxChars * 2) this.text = this.text.slice(this.text.length - this.maxChars);
|
|
10547
|
+
}
|
|
10548
|
+
value() {
|
|
10549
|
+
return this.text.length > this.maxChars ? this.text.slice(this.text.length - this.maxChars) : this.text;
|
|
10550
|
+
}
|
|
10551
|
+
}
|
|
10552
|
+
function killScriptTree(child, signal) {
|
|
10553
|
+
if (child.exitCode !== null || child.signalCode !== null || !child.pid) return;
|
|
10554
|
+
try {
|
|
10555
|
+
if (process.platform !== "win32") process.kill(-child.pid, signal);
|
|
10556
|
+
else child.kill(signal);
|
|
10557
|
+
} catch {
|
|
10558
|
+
try {
|
|
10559
|
+
child.kill(signal);
|
|
10560
|
+
} catch {
|
|
10561
|
+
}
|
|
10562
|
+
}
|
|
10563
|
+
}
|
|
10564
|
+
function terminateScriptTree(child) {
|
|
10565
|
+
killScriptTree(child, "SIGTERM");
|
|
10566
|
+
const killer = setTimeout(() => killScriptTree(child, "SIGKILL"), SCRIPT_KILL_GRACE_MS);
|
|
10567
|
+
killer.unref();
|
|
10568
|
+
child.once("exit", () => clearTimeout(killer));
|
|
10569
|
+
}
|
|
10570
|
+
function runScript(options) {
|
|
10571
|
+
return new Promise((resolve) => {
|
|
10572
|
+
const tail = new TailBuffer(persistence.AUTOMATION_SUMMARY_MAX_CHARS);
|
|
10573
|
+
let timedOut = false;
|
|
10574
|
+
let settled = false;
|
|
10575
|
+
let child;
|
|
10576
|
+
const timers = [];
|
|
10577
|
+
const finish = (result) => {
|
|
10578
|
+
if (settled) return;
|
|
10579
|
+
settled = true;
|
|
10580
|
+
for (const t of timers) clearTimeout(t);
|
|
10581
|
+
resolve(result);
|
|
10582
|
+
};
|
|
10583
|
+
const timer = setTimeout(() => {
|
|
10584
|
+
timedOut = true;
|
|
10585
|
+
terminateScriptTree(child);
|
|
10586
|
+
}, options.timeoutMs);
|
|
10587
|
+
timer.unref();
|
|
10588
|
+
timers.push(timer);
|
|
10589
|
+
try {
|
|
10590
|
+
child = node_child_process.spawn(options.command[0], options.command.slice(1), {
|
|
10591
|
+
cwd: options.cwd,
|
|
10592
|
+
shell: false,
|
|
10593
|
+
windowsHide: true,
|
|
10594
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
10595
|
+
detached: process.platform !== "win32",
|
|
10596
|
+
env: { ...options.baseEnv ?? process.env, ...options.env ?? {} }
|
|
10597
|
+
});
|
|
10598
|
+
} catch (error) {
|
|
10599
|
+
finish({ exitCode: null, signal: null, timedOut: false, output: "", error: error instanceof Error ? error.message : String(error) });
|
|
10600
|
+
return;
|
|
10601
|
+
}
|
|
10602
|
+
options.onStart?.(child);
|
|
10603
|
+
child.stdout?.setEncoding("utf8").on("data", (chunk) => tail.push(chunk));
|
|
10604
|
+
child.stderr?.setEncoding("utf8").on("data", (chunk) => tail.push(chunk));
|
|
10605
|
+
child.on("error", (error) => finish({ exitCode: null, signal: null, timedOut, output: tail.value(), error: error.message }));
|
|
10606
|
+
child.on("close", (code, signal) => finish({ exitCode: code, signal, timedOut, output: tail.value() }));
|
|
10607
|
+
child.on("exit", (code, signal) => {
|
|
10608
|
+
const drain = setTimeout(() => {
|
|
10609
|
+
killScriptTree(child, "SIGKILL");
|
|
10610
|
+
finish({ exitCode: code, signal, timedOut, output: tail.value() });
|
|
10611
|
+
}, SCRIPT_DRAIN_MS);
|
|
10612
|
+
drain.unref();
|
|
10613
|
+
timers.push(drain);
|
|
10614
|
+
});
|
|
10615
|
+
});
|
|
10616
|
+
}
|
|
10617
|
+
|
|
10618
|
+
const AUTOMATION_TICK_MS = 5e3;
|
|
10619
|
+
const AUTOMATION_LEASE_RENEW_MS = 3e4;
|
|
10620
|
+
const AUTOMATION_LOG_READ_MS = 3e4;
|
|
10621
|
+
const AUTOMATION_UNAVAILABLE_LOG_MS = 10 * 6e4;
|
|
10622
|
+
const AUTOMATION_MAX_CONCURRENT = persistence.AUTOMATION_CLAIM_MAX_RUNS;
|
|
10623
|
+
const AUTOMATION_SPAWNED_BY = "automation";
|
|
10624
|
+
function automationPromptHeader(name, runId) {
|
|
10625
|
+
return `[Very Happy automation "${name}" run ${runId}; finish with automation_report (runId ${runId}) or \`very-happy auto report --run ${runId}\`]`;
|
|
10626
|
+
}
|
|
10627
|
+
function automationRunAnchor(runId) {
|
|
10628
|
+
const marker = ` run ${runId};`;
|
|
10629
|
+
return (body) => userPromptText(body)?.startsWith("[Very Happy automation ") === true && userPromptText(body).includes(marker);
|
|
10630
|
+
}
|
|
10631
|
+
async function defaultReadTurn(sessionId, runId) {
|
|
10632
|
+
const persisted = persistence.readPersistedSessions()[sessionId];
|
|
10633
|
+
if (!persisted) throw new Error(`No local key for session ${sessionId}`);
|
|
10634
|
+
return analyzeLatestTurn(await readSessionLog(sessionId, persisted, TURN_WINDOW), { anchor: automationRunAnchor(runId) });
|
|
10635
|
+
}
|
|
10636
|
+
async function defaultSend(sessionId, text, meta) {
|
|
10637
|
+
const persisted = await waitForSessionKey(sessionId, 15e3);
|
|
10638
|
+
await sendUserMessage(sessionId, persisted, text, "automation", { ...meta, sentFrom: "automation" });
|
|
10639
|
+
}
|
|
10640
|
+
function expandHome(path$1) {
|
|
10641
|
+
if (path$1 === "~") return os.homedir();
|
|
10642
|
+
if (path$1.startsWith("~/")) return path.join(os.homedir(), path$1.slice(2));
|
|
10643
|
+
return path$1;
|
|
10644
|
+
}
|
|
10645
|
+
function isSettledByServer(error) {
|
|
10646
|
+
if (!(error instanceof agentGuidance.AutomationsRequestError)) return false;
|
|
10647
|
+
if (error.status === 409 && (error.code === "run_finished" || error.code === "claim_mismatch")) return true;
|
|
10648
|
+
return error.status === 404 && error.code === "run_not_found";
|
|
10649
|
+
}
|
|
10650
|
+
function scriptAlive(item) {
|
|
10651
|
+
return !!item.child && item.child.exitCode === null && item.child.signalCode === null;
|
|
10652
|
+
}
|
|
10653
|
+
function createAutomationRunner(deps) {
|
|
10654
|
+
const home = deps.home ?? persistence.configuration.happyHomeDir;
|
|
10655
|
+
const client = deps.client ?? agentGuidance.createAutomationsClient({ serverUrl: deps.serverUrl ?? persistence.configuration.serverUrl, token: deps.token, client: "daemon-auto" });
|
|
10656
|
+
const runScript$1 = deps.runScript ?? runScript;
|
|
10657
|
+
const readTurn = deps.readTurn ?? defaultReadTurn;
|
|
10658
|
+
const send = deps.send ?? defaultSend;
|
|
10659
|
+
const prepareWorktree = deps.prepareWorktree ?? prepareTeamWorktree;
|
|
10660
|
+
const now = deps.now ?? (() => Date.now());
|
|
10661
|
+
const tracked = /* @__PURE__ */ new Map();
|
|
10662
|
+
let running = false;
|
|
10663
|
+
let renewing = false;
|
|
10664
|
+
let closed = false;
|
|
10665
|
+
let disabledUntil = 0;
|
|
10666
|
+
let lastUnavailableLogAt = -Infinity;
|
|
10667
|
+
let recovered = false;
|
|
10668
|
+
function persist(receipt) {
|
|
10669
|
+
writeReceipt(home, receipt, now());
|
|
10670
|
+
}
|
|
10671
|
+
async function finish(item, report2) {
|
|
10672
|
+
try {
|
|
10673
|
+
await client.report(item.runId, report2);
|
|
10674
|
+
} catch (error) {
|
|
10675
|
+
if (!isSettledByServer(error)) {
|
|
10676
|
+
item.pendingFinal = report2;
|
|
10677
|
+
deps.log(`Automation run ${item.runId} final report deferred`);
|
|
10678
|
+
return;
|
|
10679
|
+
}
|
|
10680
|
+
}
|
|
10681
|
+
persist({ runId: item.runId, automationId: item.automationId, kind: item.kind, phase: "finished", claimId: item.claimId, sessionId: item.sessionId });
|
|
10682
|
+
tracked.delete(item.runId);
|
|
10683
|
+
}
|
|
10684
|
+
function track(claimed, kind, sessionId, child) {
|
|
10685
|
+
const at = now();
|
|
10686
|
+
const item = { runId: claimed.run.id, automationId: claimed.automation.id, claimId: claimed.run.claimId, kind, sessionId, child, sawTurn: false, startedAt: at, lastLeaseAt: at, nextLogReadAt: at + AUTOMATION_LOG_READ_MS, attentionReported: false, exited: false };
|
|
10687
|
+
tracked.set(item.runId, item);
|
|
10688
|
+
return item;
|
|
10689
|
+
}
|
|
10690
|
+
async function failNow(claimed, kind, error, attentionReason, sessionId) {
|
|
10691
|
+
const item = track(claimed, kind, sessionId);
|
|
10692
|
+
await finish(item, { claimId: item.claimId, status: "failed", error: clipText(error, persistence.AUTOMATION_SUMMARY_MAX_CHARS), ...sessionId ? { sessionId } : {}, ...attentionReason ? { needsAttention: true, attentionReason } : {} });
|
|
10693
|
+
}
|
|
10694
|
+
async function reportRunning(item, sessionId, stickyKey) {
|
|
10695
|
+
const body = { claimId: item.claimId, status: "running", ...sessionId ? { sessionId } : {}, ...stickyKey ? { stickyKey } : {} };
|
|
10696
|
+
try {
|
|
10697
|
+
await client.report(item.runId, body);
|
|
10698
|
+
} catch (error) {
|
|
10699
|
+
if (isSettledByServer(error)) {
|
|
10700
|
+
settleExternally(item);
|
|
10701
|
+
return;
|
|
10702
|
+
}
|
|
10703
|
+
if (sessionId) item.pendingRunning = { sessionId, ...stickyKey ? { stickyKey } : {} };
|
|
10704
|
+
deps.log(`Automation run ${item.runId} running report deferred`);
|
|
10705
|
+
}
|
|
10706
|
+
}
|
|
10707
|
+
async function execute(claimed) {
|
|
10708
|
+
const { run, automation } = claimed;
|
|
10709
|
+
const existing = readReceipts(home)[run.id];
|
|
10710
|
+
if (existing) {
|
|
10711
|
+
if (existing.phase === "finished" || tracked.has(run.id)) return;
|
|
10712
|
+
if (existing.phase === "starting") {
|
|
10713
|
+
await failNow(claimed, existing.kind, "Local execution outcome unknown after restart; verify before re-running", "unknown_outcome");
|
|
10714
|
+
return;
|
|
10715
|
+
}
|
|
10716
|
+
if (existing.kind === "script") {
|
|
10717
|
+
await failNow(claimed, "script", "Daemon restarted while the script was running", "daemon_restarted");
|
|
10718
|
+
return;
|
|
10719
|
+
}
|
|
10720
|
+
track(claimed, existing.kind, existing.sessionId).sawTurn = true;
|
|
10721
|
+
return;
|
|
10722
|
+
}
|
|
10723
|
+
const context = { payload: run.payload, runId: run.id, automationName: automation.name, ...automation.trigger.kind === "cron" ? { tz: automation.trigger.tz } : {}, now: now() };
|
|
10724
|
+
const action = renderAction(automation.action, context);
|
|
10725
|
+
const env = { VH_AUTOMATION_RUN_ID: run.id, VH_AUTOMATION_NAME: automation.name };
|
|
10726
|
+
const header = automationPromptHeader(automation.name, run.id);
|
|
10727
|
+
if (action.kind === "script") {
|
|
10728
|
+
const timeoutMs = action.timeoutMs ?? automation.maxRuntimeMs;
|
|
10729
|
+
persist({ runId: run.id, automationId: automation.id, kind: "script", phase: "starting", claimId: run.claimId });
|
|
10730
|
+
const item2 = track(claimed, "script");
|
|
10731
|
+
const finished = runScript$1({
|
|
10732
|
+
command: action.command,
|
|
10733
|
+
cwd: action.cwd ? expandHome(action.cwd) : void 0,
|
|
10734
|
+
timeoutMs,
|
|
10735
|
+
env: { ...action.env ?? {}, ...env, ...run.payload ? { VH_AUTOMATION_PAYLOAD: run.payload } : {} },
|
|
10736
|
+
onStart: (child) => {
|
|
10737
|
+
item2.child = child;
|
|
10738
|
+
}
|
|
10739
|
+
});
|
|
10740
|
+
persist({ runId: run.id, automationId: automation.id, kind: "script", phase: "running", claimId: run.claimId });
|
|
10741
|
+
await reportRunning(item2);
|
|
10742
|
+
void finished.then(async (result) => {
|
|
10743
|
+
if (!tracked.has(run.id)) return;
|
|
10744
|
+
const ok = result.exitCode === 0 && !result.timedOut && !result.error;
|
|
10745
|
+
const error = result.error ? `Launch failed: ${result.error}` : result.timedOut ? `Timed out after ${timeoutMs}ms` : result.exitCode !== 0 ? `Exit ${result.exitCode ?? `signal ${result.signal}`}` : void 0;
|
|
10746
|
+
await finish(item2, { claimId: run.claimId, status: ok ? "done" : "failed", summary: clipText(result.output, persistence.AUTOMATION_SUMMARY_MAX_CHARS, "tail"), exitCode: result.exitCode, ...error ? { error } : {} });
|
|
10747
|
+
});
|
|
10748
|
+
return;
|
|
10749
|
+
}
|
|
10750
|
+
if (action.kind === "send") {
|
|
10751
|
+
if (!deps.live(action.sessionId)) {
|
|
10752
|
+
await failNow(claimed, "send", `Session ${action.sessionId} is not running on this machine`, "session_not_live", action.sessionId);
|
|
10753
|
+
return;
|
|
10754
|
+
}
|
|
10755
|
+
persist({ runId: run.id, automationId: automation.id, kind: "send", phase: "running", claimId: run.claimId, sessionId: action.sessionId });
|
|
10756
|
+
try {
|
|
10757
|
+
await send(action.sessionId, `${header}
|
|
10758
|
+
${action.prompt}`, { localId: `automation-${run.id}` });
|
|
10759
|
+
} catch (error) {
|
|
10760
|
+
await failNow(claimed, "send", `Message delivery failed: ${error instanceof Error ? error.message : String(error)}`, "send_failed", action.sessionId);
|
|
10761
|
+
return;
|
|
10762
|
+
}
|
|
10763
|
+
await reportRunning(track(claimed, "send", action.sessionId), action.sessionId);
|
|
10764
|
+
return;
|
|
10765
|
+
}
|
|
10766
|
+
const agent = action.agent;
|
|
10767
|
+
if (!isSpawnAgent(agent)) {
|
|
10768
|
+
await failNow(claimed, "spawn", `Unknown agent "${agent}"`, "invalid_action");
|
|
10769
|
+
return;
|
|
10770
|
+
}
|
|
10771
|
+
if (action.permissionMode && sanitizeSpawnPermissionMode(action.permissionMode) === null) {
|
|
10772
|
+
await failNow(claimed, "spawn", `Invalid permission mode "${action.permissionMode}"`, "invalid_action");
|
|
10773
|
+
return;
|
|
10774
|
+
}
|
|
10775
|
+
const permissionMode = resolveSpawnPermissionMode(agent, action.permissionMode ?? void 0);
|
|
10776
|
+
const stickyKey = action.sticky ? renderTemplate(action.sticky.key, context) : void 0;
|
|
10777
|
+
if (stickyKey) {
|
|
10778
|
+
const bound = claimed.stickies.find((sticky) => sticky.key === stickyKey);
|
|
10779
|
+
if (bound && deps.live(bound.sessionId)) {
|
|
10780
|
+
persist({ runId: run.id, automationId: automation.id, kind: "send", phase: "running", claimId: run.claimId, sessionId: bound.sessionId, stickyKey });
|
|
10781
|
+
try {
|
|
10782
|
+
await send(bound.sessionId, `${header}
|
|
10783
|
+
${action.prompt}`, { localId: `automation-${run.id}` });
|
|
10784
|
+
} catch (error) {
|
|
10785
|
+
await failNow(claimed, "send", `Sticky session delivery failed: ${error instanceof Error ? error.message : String(error)}`, "send_failed", bound.sessionId);
|
|
10786
|
+
return;
|
|
10787
|
+
}
|
|
10788
|
+
await reportRunning(track(claimed, "send", bound.sessionId), bound.sessionId, stickyKey);
|
|
10789
|
+
return;
|
|
10790
|
+
}
|
|
10791
|
+
if (bound) await client.deleteSticky(automation.id, stickyKey).catch(() => deps.log(`Automation ${automation.name}: stale sticky ${stickyKey} not cleared`));
|
|
10792
|
+
}
|
|
10793
|
+
let directory = expandHome(action.directory);
|
|
10794
|
+
if (!path.isAbsolute(directory)) {
|
|
10795
|
+
await failNow(claimed, "spawn", `Directory must be absolute: ${action.directory}`, "invalid_action");
|
|
10796
|
+
return;
|
|
10797
|
+
}
|
|
10798
|
+
if (action.worktree) {
|
|
10799
|
+
try {
|
|
10800
|
+
directory = (await prepareWorktree(home, directory, `auto-${run.id}`)).directory;
|
|
10801
|
+
} catch (error) {
|
|
10802
|
+
await failNow(claimed, "spawn", `Worktree preparation failed: ${error instanceof Error ? error.message : String(error)}`, "worktree_failed");
|
|
10803
|
+
return;
|
|
10804
|
+
}
|
|
10805
|
+
}
|
|
10806
|
+
persist({ runId: run.id, automationId: automation.id, kind: "spawn", phase: "starting", claimId: run.claimId, stickyKey, ...action.worktree ? { directory } : {} });
|
|
10807
|
+
const spawned = await deps.spawn({ directory, agent, permissionMode, spawnedBy: AUTOMATION_SPAWNED_BY, environmentVariables: env });
|
|
10808
|
+
if (spawned.type !== "success") {
|
|
10809
|
+
await failNow(claimed, "spawn", spawned.type === "error" ? spawned.errorMessage : "Directory approval required", "spawn_failed");
|
|
10810
|
+
return;
|
|
10811
|
+
}
|
|
10812
|
+
persist({ runId: run.id, automationId: automation.id, kind: "spawn", phase: "running", claimId: run.claimId, sessionId: spawned.sessionId, stickyKey, ...action.worktree ? { directory } : {} });
|
|
10813
|
+
const item = track(claimed, "spawn", spawned.sessionId);
|
|
10814
|
+
try {
|
|
10815
|
+
const capabilities = persistence.readPersistedSessions()[spawned.sessionId]?.metadata?.capabilities ?? null;
|
|
10816
|
+
const meta = resolveFirstMessageMeta({ agent, permissionMode, explicitModel: action.model ?? void 0, capabilities });
|
|
10817
|
+
await send(spawned.sessionId, `${header}
|
|
10818
|
+
${action.prompt}`, { localId: `automation-${run.id}`, ...meta });
|
|
10819
|
+
} catch (error) {
|
|
10820
|
+
await finish(item, { claimId: run.claimId, status: "failed", sessionId: spawned.sessionId, error: `First message failed: ${error instanceof Error ? error.message : String(error)}`, needsAttention: true, attentionReason: "first_message_failed" });
|
|
10821
|
+
return;
|
|
10822
|
+
}
|
|
10823
|
+
await reportRunning(item, spawned.sessionId, stickyKey);
|
|
10824
|
+
}
|
|
10825
|
+
async function monitor() {
|
|
10826
|
+
for (const item of [...tracked.values()]) {
|
|
10827
|
+
if (closed) return;
|
|
10828
|
+
if (item.pendingFinal) {
|
|
10829
|
+
await finish(item, item.pendingFinal);
|
|
10830
|
+
continue;
|
|
10831
|
+
}
|
|
10832
|
+
if (item.kind === "script") continue;
|
|
10833
|
+
const sessionId = item.sessionId;
|
|
10834
|
+
const active = deps.turnActive(sessionId);
|
|
10835
|
+
if (active) item.sawTurn = true;
|
|
10836
|
+
const alive = deps.live(sessionId) && !item.exited;
|
|
10837
|
+
if (!alive) {
|
|
10838
|
+
const turn2 = await readTurn(sessionId, item.runId).catch(() => null);
|
|
10839
|
+
if (turn2?.ended && turn2.status !== "failed" && turn2.status !== "cancelled") await finish(item, { claimId: item.claimId, status: "done", sessionId, summary: clipText(turn2.answer, persistence.AUTOMATION_SUMMARY_MAX_CHARS) });
|
|
10840
|
+
else await finish(item, { claimId: item.claimId, status: "failed", sessionId, error: turn2?.error ?? "Session exited before the turn ended", needsAttention: true, attentionReason: "session_exited" });
|
|
10841
|
+
continue;
|
|
10842
|
+
}
|
|
10843
|
+
const edgeFell = item.sawTurn && !active;
|
|
10844
|
+
if (!edgeFell && now() < item.nextLogReadAt) continue;
|
|
10845
|
+
item.nextLogReadAt = now() + AUTOMATION_LOG_READ_MS;
|
|
10846
|
+
if (edgeFell) item.sawTurn = false;
|
|
10847
|
+
const turn = await readTurn(sessionId, item.runId).catch(() => null);
|
|
10848
|
+
if (!turn?.ended) continue;
|
|
10849
|
+
if (turn.status === "failed" || turn.status === "cancelled") await finish(item, { claimId: item.claimId, status: "failed", sessionId, error: turn.error ?? `Turn ${turn.status}`, needsAttention: true, attentionReason: `turn_${turn.status}` });
|
|
10850
|
+
else await finish(item, { claimId: item.claimId, status: "done", sessionId, summary: clipText(turn.answer, persistence.AUTOMATION_SUMMARY_MAX_CHARS) });
|
|
10851
|
+
}
|
|
10852
|
+
}
|
|
10853
|
+
async function renewAll() {
|
|
10854
|
+
if (renewing || closed) return;
|
|
10855
|
+
renewing = true;
|
|
10856
|
+
try {
|
|
10857
|
+
const at = now();
|
|
10858
|
+
for (const item of [...tracked.values()]) {
|
|
10859
|
+
if (closed) return;
|
|
10860
|
+
if (at - item.lastLeaseAt < AUTOMATION_LEASE_RENEW_MS) continue;
|
|
10861
|
+
item.lastLeaseAt = at;
|
|
10862
|
+
const body = { claimId: item.claimId, leaseMs: persistence.AUTOMATION_DEFAULT_LEASE_MS, ...item.pendingRunning ? { status: "running", ...item.pendingRunning } : {} };
|
|
10863
|
+
try {
|
|
10864
|
+
const run = await client.report(item.runId, body);
|
|
10865
|
+
item.pendingRunning = void 0;
|
|
10866
|
+
if (persistence.isAutomationRunTerminal(run.status)) settleExternally(item);
|
|
10867
|
+
} catch (error) {
|
|
10868
|
+
if (isSettledByServer(error)) settleExternally(item);
|
|
10869
|
+
else deps.log(`Automation run ${item.runId} lease renewal failed`);
|
|
10870
|
+
}
|
|
10871
|
+
}
|
|
10872
|
+
} finally {
|
|
10873
|
+
renewing = false;
|
|
10874
|
+
}
|
|
10875
|
+
}
|
|
10876
|
+
function settleExternally(item) {
|
|
10877
|
+
if (item.child && scriptAlive(item)) terminateScriptTree(item.child);
|
|
10878
|
+
persist({ runId: item.runId, automationId: item.automationId, kind: item.kind, phase: "finished", claimId: item.claimId, sessionId: item.sessionId });
|
|
10879
|
+
tracked.delete(item.runId);
|
|
10880
|
+
}
|
|
10881
|
+
async function recover() {
|
|
10882
|
+
recovered = true;
|
|
10883
|
+
let receipts;
|
|
10884
|
+
try {
|
|
10885
|
+
receipts = readReceipts(home);
|
|
10886
|
+
} catch {
|
|
10887
|
+
deps.log("Automation receipts unreadable; refusing to execute until repaired");
|
|
10888
|
+
closed = true;
|
|
10889
|
+
return;
|
|
10890
|
+
}
|
|
10891
|
+
for (const receipt of Object.values(receipts)) {
|
|
10892
|
+
if (receipt.phase === "finished") continue;
|
|
10893
|
+
const item = track({ run: { id: receipt.runId, claimId: receipt.claimId }, automation: { id: receipt.automationId } }, receipt.kind, receipt.sessionId);
|
|
10894
|
+
item.sawTurn = true;
|
|
10895
|
+
item.lastLeaseAt = 0;
|
|
10896
|
+
if (receipt.phase === "starting") await finish(item, { claimId: receipt.claimId, status: "failed", error: "Daemon restarted before the launch outcome was known", needsAttention: true, attentionReason: "unknown_outcome" });
|
|
10897
|
+
else if (receipt.kind === "script") await finish(item, { claimId: receipt.claimId, status: "failed", error: "Daemon restarted while the script was running", needsAttention: true, attentionReason: "daemon_restarted" });
|
|
10898
|
+
}
|
|
10899
|
+
}
|
|
10900
|
+
async function tick() {
|
|
10901
|
+
if (running || closed) return;
|
|
10902
|
+
running = true;
|
|
10903
|
+
try {
|
|
10904
|
+
if (!recovered) await recover();
|
|
10905
|
+
if (closed) return;
|
|
10906
|
+
await monitor();
|
|
10907
|
+
const capacity = AUTOMATION_MAX_CONCURRENT - tracked.size;
|
|
10908
|
+
if (now() >= disabledUntil && capacity > 0) {
|
|
10909
|
+
try {
|
|
10910
|
+
const claimed = await client.claim({ machineId: deps.machineId, limit: capacity, leaseMs: persistence.AUTOMATION_DEFAULT_LEASE_MS });
|
|
10911
|
+
await Promise.all(claimed.runs.map((entry) => closed ? Promise.resolve() : execute(entry).catch((error) => deps.log(`Automation run ${entry.run.id} failed to start: ${error instanceof Error ? error.message : String(error)}`))));
|
|
10912
|
+
} catch (error) {
|
|
10913
|
+
if (agentGuidance.isAutomationsUnavailable(error)) {
|
|
10914
|
+
disabledUntil = now() + 6e4;
|
|
10915
|
+
if (now() - lastUnavailableLogAt >= AUTOMATION_UNAVAILABLE_LOG_MS) {
|
|
10916
|
+
lastUnavailableLogAt = now();
|
|
10917
|
+
deps.log("Automations unavailable on this server (404); claim loop idle");
|
|
10918
|
+
}
|
|
10919
|
+
} else {
|
|
10920
|
+
disabledUntil = now() + 1e4;
|
|
10921
|
+
deps.log(`Automation claim failed${error instanceof agentGuidance.AutomationsRequestError ? ` (${error.status})` : ""}`);
|
|
10922
|
+
}
|
|
10923
|
+
}
|
|
10924
|
+
}
|
|
10925
|
+
} finally {
|
|
10926
|
+
running = false;
|
|
10927
|
+
}
|
|
10928
|
+
}
|
|
10929
|
+
function report(sessionId, event) {
|
|
10930
|
+
for (const item of tracked.values()) {
|
|
10931
|
+
if (item.sessionId !== sessionId) continue;
|
|
10932
|
+
if (event === "exited") item.exited = true;
|
|
10933
|
+
if (event === "blocked" && !item.attentionReported) {
|
|
10934
|
+
item.attentionReported = true;
|
|
10935
|
+
void client.report(item.runId, { claimId: item.claimId, needsAttention: true, attentionReason: "needs_input" }).catch(() => deps.log(`Automation run ${item.runId} attention report failed`));
|
|
10936
|
+
}
|
|
10937
|
+
}
|
|
10938
|
+
}
|
|
10939
|
+
const tickMs = deps.tickMs ?? AUTOMATION_TICK_MS;
|
|
10940
|
+
const timer = setInterval(() => {
|
|
10941
|
+
void tick();
|
|
10942
|
+
}, tickMs);
|
|
10943
|
+
timer.unref();
|
|
10944
|
+
const leaseTimer = setInterval(() => {
|
|
10945
|
+
void renewAll();
|
|
10946
|
+
}, tickMs);
|
|
10947
|
+
leaseTimer.unref();
|
|
10948
|
+
void tick();
|
|
10949
|
+
return {
|
|
10950
|
+
tick,
|
|
10951
|
+
renewAll,
|
|
10952
|
+
report,
|
|
10953
|
+
hasSession: (id) => [...tracked.values()].some((item) => item.sessionId === id),
|
|
10954
|
+
trackedRunIds: () => [...tracked.keys()],
|
|
10955
|
+
/** Executing a claim, or a script child is still alive — handover and auto-update wait for this. */
|
|
10956
|
+
get busy() {
|
|
10957
|
+
return running || [...tracked.values()].some(scriptAlive);
|
|
10958
|
+
},
|
|
10959
|
+
/**
|
|
10960
|
+
* Stop the loops. `killScripts` (real shutdown) terminates live script
|
|
10961
|
+
* trees; the next daemon's recovery reports them failed + attention from
|
|
10962
|
+
* the receipt, never re-running them. A handover waits on `busy` instead.
|
|
10963
|
+
*/
|
|
10964
|
+
stop: (options = {}) => {
|
|
10965
|
+
closed = true;
|
|
10966
|
+
clearInterval(timer);
|
|
10967
|
+
clearInterval(leaseTimer);
|
|
10968
|
+
if (options.killScripts) {
|
|
10969
|
+
for (const item of tracked.values()) if (item.child && scriptAlive(item)) terminateScriptTree(item.child);
|
|
10970
|
+
}
|
|
10971
|
+
}
|
|
10972
|
+
};
|
|
10973
|
+
}
|
|
10974
|
+
|
|
10331
10975
|
function daemonExitCode(source) {
|
|
10332
10976
|
return source === "exception" ? 1 : 0;
|
|
10333
10977
|
}
|
|
@@ -10488,6 +11132,7 @@ async function startDaemon() {
|
|
|
10488
11132
|
const turnActivity = new index.TurnActivityTracker();
|
|
10489
11133
|
const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
|
|
10490
11134
|
let teamWorker;
|
|
11135
|
+
let automationRunner;
|
|
10491
11136
|
const persisted = persistence.readPersistedSessions();
|
|
10492
11137
|
const liveHappyProcesses = await findAllHappyProcesses();
|
|
10493
11138
|
for (const [id, s] of Object.entries(persisted)) {
|
|
@@ -11342,6 +11987,7 @@ async function startDaemon() {
|
|
|
11342
11987
|
const onChildExited = (pid) => {
|
|
11343
11988
|
const session = pidToTrackedSession.get(pid);
|
|
11344
11989
|
if (session?.happySessionId && (session.spawnedBy === "teams" || teamWorker?.hasSession(session.happySessionId))) teamWorker?.report(session.happySessionId, "exited");
|
|
11990
|
+
if (session?.happySessionId && automationRunner?.hasSession(session.happySessionId)) automationRunner.report(session.happySessionId, "exited");
|
|
11345
11991
|
if (session?.happySessionId) turnActivity.forget(session.happySessionId);
|
|
11346
11992
|
if (session?.happySessionId && session.encryption) {
|
|
11347
11993
|
sessionIdToFinishedSession.set(session.happySessionId, session);
|
|
@@ -11361,6 +12007,7 @@ async function startDaemon() {
|
|
|
11361
12007
|
}
|
|
11362
12008
|
};
|
|
11363
12009
|
const onSessionStateEvent = (sessionId, event, spawnedByFromSession) => {
|
|
12010
|
+
if (automationRunner?.hasSession(sessionId)) automationRunner.report(sessionId, event === "completed" ? "idle" : "blocked");
|
|
11364
12011
|
if (spawnedByFromSession === "teams" || teamWorker?.hasSession(sessionId) || [...pidToTrackedSession.values()].some((s) => s.happySessionId === sessionId && s.spawnedBy === "teams")) {
|
|
11365
12012
|
teamWorker?.report(sessionId, event === "completed" ? "idle" : "blocked");
|
|
11366
12013
|
return;
|
|
@@ -11599,7 +12246,7 @@ async function startDaemon() {
|
|
|
11599
12246
|
} catch {
|
|
11600
12247
|
}
|
|
11601
12248
|
}
|
|
11602
|
-
if (bundleReplaced && !teamWorker?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn()) {
|
|
12249
|
+
if (bundleReplaced && !teamWorker?.busy && !automationRunner?.busy && !updateController.isRunning() && !turnActivity.hasActiveTurn()) {
|
|
11603
12250
|
const preflight = await preflightNewBundle(bundlePath);
|
|
11604
12251
|
if (preflight.action === "hold") {
|
|
11605
12252
|
if (lastHandoverHold !== preflight.reason) {
|
|
@@ -11609,10 +12256,11 @@ async function startDaemon() {
|
|
|
11609
12256
|
updateController.holdHandover(preflight.reason);
|
|
11610
12257
|
return;
|
|
11611
12258
|
}
|
|
11612
|
-
if (teamWorker?.busy || updateController.isRunning() || turnActivity.hasActiveTurn()) return;
|
|
12259
|
+
if (teamWorker?.busy || automationRunner?.busy || updateController.isRunning() || turnActivity.hasActiveTurn()) return;
|
|
11613
12260
|
lastHandoverHold = null;
|
|
11614
12261
|
persistence.logger.debug("[DAEMON RUN] Daemon bundle replaced on disk and verified, handing off to new daemon");
|
|
11615
12262
|
teamWorker?.stop();
|
|
12263
|
+
automationRunner?.stop();
|
|
11616
12264
|
clearInterval(restartOnStaleVersionAndHeartbeat);
|
|
11617
12265
|
clearInterval(cliUpdateInterval);
|
|
11618
12266
|
stopAgentVersionChecks();
|
|
@@ -11664,6 +12312,14 @@ async function startDaemon() {
|
|
|
11664
12312
|
live: (id) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === id && isPidAlive(s.pid)),
|
|
11665
12313
|
log: (message) => persistence.logger.debug(`[DAEMON RUN] ${message}`)
|
|
11666
12314
|
});
|
|
12315
|
+
automationRunner = createAutomationRunner({
|
|
12316
|
+
machineId,
|
|
12317
|
+
token: credentials.token,
|
|
12318
|
+
spawn: spawnSession,
|
|
12319
|
+
live: (id) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === id && isPidAlive(s.pid)),
|
|
12320
|
+
turnActive: (id) => turnActivity.activeSessions().includes(id),
|
|
12321
|
+
log: (message) => persistence.logger.debug(`[DAEMON RUN] ${message}`)
|
|
12322
|
+
});
|
|
11667
12323
|
void apiMachine.updateMachineMetadata((current) => ({
|
|
11668
12324
|
...current ?? initialMachineMetadata,
|
|
11669
12325
|
teamsVersion: 1,
|
|
@@ -11672,6 +12328,7 @@ async function startDaemon() {
|
|
|
11672
12328
|
const cleanupAndShutdown = async (source, errorMessage) => {
|
|
11673
12329
|
persistence.logger.debug(`[DAEMON RUN] Starting proper cleanup (source: ${source}, errorMessage: ${errorMessage})...`);
|
|
11674
12330
|
teamWorker?.stop();
|
|
12331
|
+
automationRunner?.stop({ killScripts: true });
|
|
11675
12332
|
if (restartOnStaleVersionAndHeartbeat) {
|
|
11676
12333
|
clearInterval(restartOnStaleVersionAndHeartbeat);
|
|
11677
12334
|
persistence.logger.debug("[DAEMON RUN] Health check interval cleared");
|
|
@@ -12176,6 +12833,7 @@ function createMcpServer(handlers, options, sessionId) {
|
|
|
12176
12833
|
version: "1.0.0"
|
|
12177
12834
|
});
|
|
12178
12835
|
agentGuidance.registerTeamsTools(mcp, sessionId);
|
|
12836
|
+
agentGuidance.registerAutomationTools(mcp);
|
|
12179
12837
|
mcp.registerTool("change_title", {
|
|
12180
12838
|
description: "Change the title of the current chat session",
|
|
12181
12839
|
title: "Change Chat Title",
|
|
@@ -12370,7 +13028,7 @@ async function startHappyServer(client, options) {
|
|
|
12370
13028
|
return;
|
|
12371
13029
|
}
|
|
12372
13030
|
}
|
|
12373
|
-
const usage =
|
|
13031
|
+
const usage = persistence.ContextUsageSchema.parse({ ...JSON.parse(body), updatedAt: Date.now() });
|
|
12374
13032
|
options.onContextUsage(usage);
|
|
12375
13033
|
res.writeHead(204).end();
|
|
12376
13034
|
} catch {
|
|
@@ -12418,6 +13076,7 @@ async function startHappyServer(client, options) {
|
|
|
12418
13076
|
agentGuidance.PREVIEW_TOOL_NAME,
|
|
12419
13077
|
agentGuidance.REPORT_PROGRESS_TOOL_NAME,
|
|
12420
13078
|
...agentGuidance.TEAM_TOOL_NAMES,
|
|
13079
|
+
...agentGuidance.AUTOMATION_TOOL_NAMES,
|
|
12421
13080
|
...options?.assistant && !process.env.VH_TEAM_SCOPE_FILE ? ASSISTANT_TOOL_NAMES : []
|
|
12422
13081
|
],
|
|
12423
13082
|
stop: () => {
|
|
@@ -12754,7 +13413,7 @@ function registerSideQuestionHandler(rpc, deps) {
|
|
|
12754
13413
|
const retainMs = deps.retainMs ?? SIDE_QUESTION_RETAIN_MS;
|
|
12755
13414
|
const maxRunMs = deps.maxRunMs ?? SIDE_QUESTION_MAX_RUN_MS;
|
|
12756
13415
|
const fork = deps.run ?? (async (input) => {
|
|
12757
|
-
const { query } = await Promise.resolve().then(function () { return require('./index-
|
|
13416
|
+
const { query } = await Promise.resolve().then(function () { return require('./index-CRaJ9k2p.cjs'); });
|
|
12758
13417
|
return runSideQuestion(query, input);
|
|
12759
13418
|
});
|
|
12760
13419
|
const run = async (input, live) => {
|
|
@@ -12873,7 +13532,7 @@ const MAX_TITLE_CHARS = 60;
|
|
|
12873
13532
|
const GENERATION_TIMEOUT_MS = 3e4;
|
|
12874
13533
|
function resolveClaudeBinary() {
|
|
12875
13534
|
try {
|
|
12876
|
-
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-
|
|
13535
|
+
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-ZIW1jrYm.cjs', document.baseURI).href)));
|
|
12877
13536
|
const utilsPath = path.resolve(path.join(projectPath.projectPath(), "scripts", "claude_version_utils.cjs"));
|
|
12878
13537
|
const { getClaudeCliPath } = require$1(utilsPath);
|
|
12879
13538
|
const path$1 = getClaudeCliPath();
|
|
@@ -15102,9 +15761,9 @@ function resolveLocalSignupBootstrap(configuredMode, configuredInviteCodes, gene
|
|
|
15102
15761
|
};
|
|
15103
15762
|
}
|
|
15104
15763
|
|
|
15105
|
-
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-
|
|
15764
|
+
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-ZIW1jrYm.cjs', document.baseURI).href)));
|
|
15106
15765
|
const __dirname$1 = path.dirname(__filename$1);
|
|
15107
|
-
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
15766
|
+
const require_ = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-ZIW1jrYm.cjs', document.baseURI).href)));
|
|
15108
15767
|
const PRISMA_QUERY_ENGINE_FILES = {
|
|
15109
15768
|
"arm64-darwin": "libquery_engine-darwin-arm64.dylib.node",
|
|
15110
15769
|
"x64-darwin": "libquery_engine-darwin.dylib.node",
|
|
@@ -15539,14 +16198,14 @@ function maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagent
|
|
|
15539
16198
|
if (!subagent || startedSubagents.has(subagent)) {
|
|
15540
16199
|
return;
|
|
15541
16200
|
}
|
|
15542
|
-
envelopes.push(
|
|
16201
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "start" }, { ...opts, subagent }));
|
|
15543
16202
|
startedSubagents.add(subagent);
|
|
15544
16203
|
activeSubagents.add(subagent);
|
|
15545
16204
|
}
|
|
15546
16205
|
function emitSubagentStops(opts, startedSubagents, activeSubagents) {
|
|
15547
16206
|
const envelopes = [];
|
|
15548
16207
|
for (const subagent of activeSubagents) {
|
|
15549
|
-
envelopes.push(
|
|
16208
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "stop" }, { ...opts, subagent }));
|
|
15550
16209
|
}
|
|
15551
16210
|
activeSubagents.clear();
|
|
15552
16211
|
startedSubagents.clear();
|
|
@@ -15642,7 +16301,7 @@ function turnStatus(turn) {
|
|
|
15642
16301
|
function emitHistoricalToolCall(envelopes, turn, item, name, title, args, output) {
|
|
15643
16302
|
const time = turnTimestampMs(turn);
|
|
15644
16303
|
const opts = { turn: turn.id, time, codexItemId: item.id };
|
|
15645
|
-
envelopes.push(
|
|
16304
|
+
envelopes.push(persistence.createEnvelope("agent", {
|
|
15646
16305
|
t: "tool-call-start",
|
|
15647
16306
|
call: item.id,
|
|
15648
16307
|
name,
|
|
@@ -15654,7 +16313,7 @@ function emitHistoricalToolCall(envelopes, turn, item, name, title, args, output
|
|
|
15654
16313
|
id: `${item.id}:start`
|
|
15655
16314
|
}));
|
|
15656
16315
|
if (output && output.trim().length > 0) {
|
|
15657
|
-
envelopes.push(
|
|
16316
|
+
envelopes.push(persistence.createEnvelope("agent", {
|
|
15658
16317
|
t: "text",
|
|
15659
16318
|
text: output,
|
|
15660
16319
|
thinking: true
|
|
@@ -15664,7 +16323,7 @@ function emitHistoricalToolCall(envelopes, turn, item, name, title, args, output
|
|
|
15664
16323
|
}));
|
|
15665
16324
|
}
|
|
15666
16325
|
if ("status" in item && (item.status === "inProgress" || item.status === "running")) return;
|
|
15667
|
-
envelopes.push(
|
|
16326
|
+
envelopes.push(persistence.createEnvelope("agent", {
|
|
15668
16327
|
t: "tool-call-end",
|
|
15669
16328
|
call: item.id
|
|
15670
16329
|
}, {
|
|
@@ -15686,7 +16345,7 @@ function mapCodexCollaborationItem(item, opts = {}, source = "history") {
|
|
|
15686
16345
|
agentsStates: item.agentsStates ?? {}
|
|
15687
16346
|
};
|
|
15688
16347
|
const startId = source === "live" ? `${item.id}:${item.status ?? "unknown"}:start` : `${item.id}:start`;
|
|
15689
|
-
const envelopes = [
|
|
16348
|
+
const envelopes = [persistence.createEnvelope("agent", {
|
|
15690
16349
|
t: "tool-call-start",
|
|
15691
16350
|
call: item.id,
|
|
15692
16351
|
name: "CodexCollaboration",
|
|
@@ -15695,7 +16354,7 @@ function mapCodexCollaborationItem(item, opts = {}, source = "history") {
|
|
|
15695
16354
|
args
|
|
15696
16355
|
}, { ...opts, id: startId })];
|
|
15697
16356
|
if (item.status === "completed" || item.status === "failed" || item.status === "interrupted") {
|
|
15698
|
-
envelopes.push(
|
|
16357
|
+
envelopes.push(persistence.createEnvelope("agent", {
|
|
15699
16358
|
t: "tool-call-end",
|
|
15700
16359
|
call: item.id,
|
|
15701
16360
|
result: { text: JSON.stringify(args, null, 2), isError: item.status !== "completed" }
|
|
@@ -15708,7 +16367,7 @@ function mapCodexThreadToSessionEnvelopes(thread) {
|
|
|
15708
16367
|
for (const turn of thread.turns ?? []) {
|
|
15709
16368
|
const startedAt = turnTimestampMs(turn);
|
|
15710
16369
|
const completedAt = completedTimestampMs(turn);
|
|
15711
|
-
envelopes.push(
|
|
16370
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "turn-start" }, {
|
|
15712
16371
|
id: `${turn.id}:start`,
|
|
15713
16372
|
turn: turn.id,
|
|
15714
16373
|
time: startedAt
|
|
@@ -15723,7 +16382,7 @@ function mapCodexThreadToSessionEnvelopes(thread) {
|
|
|
15723
16382
|
case "userMessage": {
|
|
15724
16383
|
const text = textFromInputItems(item.content);
|
|
15725
16384
|
if (text) {
|
|
15726
|
-
envelopes.push(
|
|
16385
|
+
envelopes.push(persistence.createEnvelope("user", { t: "text", text }, {
|
|
15727
16386
|
id: item.id,
|
|
15728
16387
|
time: startedAt,
|
|
15729
16388
|
codexItemId: item.id
|
|
@@ -15734,7 +16393,7 @@ function mapCodexThreadToSessionEnvelopes(thread) {
|
|
|
15734
16393
|
case "agentMessage": {
|
|
15735
16394
|
const text = typeof item.text === "string" ? item.text.trim() : "";
|
|
15736
16395
|
if (text.length > 0) {
|
|
15737
|
-
envelopes.push(
|
|
16396
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "text", text }, {
|
|
15738
16397
|
id: item.id,
|
|
15739
16398
|
turn: turn.id,
|
|
15740
16399
|
time: completedAt,
|
|
@@ -15746,7 +16405,7 @@ function mapCodexThreadToSessionEnvelopes(thread) {
|
|
|
15746
16405
|
case "reasoning": {
|
|
15747
16406
|
const text = reasoningText(item);
|
|
15748
16407
|
if (text) {
|
|
15749
|
-
envelopes.push(
|
|
16408
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "text", text, thinking: true }, {
|
|
15750
16409
|
id: item.id,
|
|
15751
16410
|
turn: turn.id,
|
|
15752
16411
|
time: startedAt,
|
|
@@ -15801,7 +16460,7 @@ function mapCodexThreadToSessionEnvelopes(thread) {
|
|
|
15801
16460
|
}
|
|
15802
16461
|
}
|
|
15803
16462
|
}
|
|
15804
|
-
envelopes.push(
|
|
16463
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "turn-end", status: turnStatus(turn) }, {
|
|
15805
16464
|
id: `${turn.id}:end`,
|
|
15806
16465
|
turn: turn.id,
|
|
15807
16466
|
time: completedAt
|
|
@@ -15856,7 +16515,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
15856
16515
|
}
|
|
15857
16516
|
if (type === "task_started") {
|
|
15858
16517
|
const turnId = cuid2.createId();
|
|
15859
|
-
const turnStart =
|
|
16518
|
+
const turnStart = persistence.createEnvelope("agent", { t: "turn-start" }, { turn: turnId });
|
|
15860
16519
|
startedSubagents.clear();
|
|
15861
16520
|
activeSubagents.clear();
|
|
15862
16521
|
providerSubagentToSessionSubagent.clear();
|
|
@@ -15887,7 +16546,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
15887
16546
|
providerSubagentToSessionSubagent,
|
|
15888
16547
|
envelopes: [
|
|
15889
16548
|
...emitSubagentStops(lifecycleOpts, startedSubagents, activeSubagents),
|
|
15890
|
-
|
|
16549
|
+
persistence.createEnvelope("agent", {
|
|
15891
16550
|
t: "turn-end",
|
|
15892
16551
|
status: pickTurnEndStatus(message, type)
|
|
15893
16552
|
}, lifecycleOpts)
|
|
@@ -15917,7 +16576,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
15917
16576
|
}
|
|
15918
16577
|
const envelopes = [];
|
|
15919
16578
|
maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
|
|
15920
|
-
envelopes.push(
|
|
16579
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "text", text: message.message }, opts));
|
|
15921
16580
|
return {
|
|
15922
16581
|
currentTurnId: state.currentTurnId,
|
|
15923
16582
|
startedSubagents,
|
|
@@ -15939,7 +16598,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
15939
16598
|
}
|
|
15940
16599
|
const envelopes = [];
|
|
15941
16600
|
maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
|
|
15942
|
-
envelopes.push(
|
|
16601
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "text", text, thinking: true }, opts));
|
|
15943
16602
|
return {
|
|
15944
16603
|
currentTurnId: state.currentTurnId,
|
|
15945
16604
|
startedSubagents,
|
|
@@ -15956,7 +16615,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
15956
16615
|
const envelopes = [];
|
|
15957
16616
|
maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
|
|
15958
16617
|
envelopes.push(
|
|
15959
|
-
|
|
16618
|
+
persistence.createEnvelope("agent", {
|
|
15960
16619
|
t: "tool-call-start",
|
|
15961
16620
|
call,
|
|
15962
16621
|
name: "CodexBash",
|
|
@@ -15977,7 +16636,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
15977
16636
|
const call = pickCallId(message);
|
|
15978
16637
|
const envelopes = [];
|
|
15979
16638
|
maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
|
|
15980
|
-
envelopes.push(
|
|
16639
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "tool-call-end", call }, opts));
|
|
15981
16640
|
return {
|
|
15982
16641
|
currentTurnId: state.currentTurnId,
|
|
15983
16642
|
startedSubagents,
|
|
@@ -15993,7 +16652,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
15993
16652
|
const envelopes = [];
|
|
15994
16653
|
maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
|
|
15995
16654
|
envelopes.push(
|
|
15996
|
-
|
|
16655
|
+
persistence.createEnvelope("agent", {
|
|
15997
16656
|
t: "tool-call-start",
|
|
15998
16657
|
call,
|
|
15999
16658
|
name: "CodexPatch",
|
|
@@ -16017,7 +16676,7 @@ function mapCodexMcpMessageToSessionEnvelopes(message, state) {
|
|
|
16017
16676
|
const call = pickCallId(message);
|
|
16018
16677
|
const envelopes = [];
|
|
16019
16678
|
maybeEmitSubagentStart(subagent, opts, startedSubagents, activeSubagents, envelopes);
|
|
16020
|
-
envelopes.push(
|
|
16679
|
+
envelopes.push(persistence.createEnvelope("agent", { t: "tool-call-end", call }, opts));
|
|
16021
16680
|
return {
|
|
16022
16681
|
currentTurnId: state.currentTurnId,
|
|
16023
16682
|
startedSubagents,
|
|
@@ -16038,7 +16697,7 @@ function mapCodexProcessorMessageToSessionEnvelopes(message, state) {
|
|
|
16038
16697
|
const toolLikeMessage = message;
|
|
16039
16698
|
const opts = buildEnvelopeOptions(state.currentTurnId);
|
|
16040
16699
|
if (message.type === "reasoning") {
|
|
16041
|
-
return [
|
|
16700
|
+
return [persistence.createEnvelope("agent", {
|
|
16042
16701
|
t: "text",
|
|
16043
16702
|
text: message.message,
|
|
16044
16703
|
thinking: true
|
|
@@ -16046,7 +16705,7 @@ function mapCodexProcessorMessageToSessionEnvelopes(message, state) {
|
|
|
16046
16705
|
}
|
|
16047
16706
|
if (message.type === "tool-call") {
|
|
16048
16707
|
const title = typeof toolLikeMessage.input?.title === "string" ? toolLikeMessage.input.title : `${toolLikeMessage.name || "Tool"} call`;
|
|
16049
|
-
return [
|
|
16708
|
+
return [persistence.createEnvelope("agent", {
|
|
16050
16709
|
t: "tool-call-start",
|
|
16051
16710
|
call: toolLikeMessage.callId,
|
|
16052
16711
|
name: toolLikeMessage.name || "unknown",
|
|
@@ -16059,13 +16718,13 @@ function mapCodexProcessorMessageToSessionEnvelopes(message, state) {
|
|
|
16059
16718
|
const envelopes = [];
|
|
16060
16719
|
const content = toolLikeMessage.output?.content;
|
|
16061
16720
|
if (typeof content === "string" && content.trim().length > 0) {
|
|
16062
|
-
envelopes.push(
|
|
16721
|
+
envelopes.push(persistence.createEnvelope("agent", {
|
|
16063
16722
|
t: "text",
|
|
16064
16723
|
text: content,
|
|
16065
16724
|
thinking: true
|
|
16066
16725
|
}, opts));
|
|
16067
16726
|
}
|
|
16068
|
-
envelopes.push(
|
|
16727
|
+
envelopes.push(persistence.createEnvelope("agent", {
|
|
16069
16728
|
t: "tool-call-end",
|
|
16070
16729
|
call: toolLikeMessage.callId
|
|
16071
16730
|
}, opts));
|
|
@@ -17061,7 +17720,7 @@ function buildCodexTurnPrompt(opts) {
|
|
|
17061
17720
|
parts.push(opts.message);
|
|
17062
17721
|
if (opts.includeTitleInstruction) {
|
|
17063
17722
|
parts.push(CHANGE_TITLE_INSTRUCTION);
|
|
17064
|
-
parts.push(
|
|
17723
|
+
parts.push(persistence.BUILTIN_TODO_DISCOVERY);
|
|
17065
17724
|
}
|
|
17066
17725
|
return parts.join("\n\n");
|
|
17067
17726
|
}
|
|
@@ -18042,7 +18701,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18042
18701
|
return;
|
|
18043
18702
|
} else if (subcommand === "install-terminal-hooks") {
|
|
18044
18703
|
try {
|
|
18045
|
-
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-
|
|
18704
|
+
const { installTerminalHooks, parseTerminalHooksArgs, TERMINAL_HOOKS_HELP } = await Promise.resolve().then(function () { return require('./installTerminalHooks-BoDxpaBO.cjs'); });
|
|
18046
18705
|
const command = parseTerminalHooksArgs(args.slice(1));
|
|
18047
18706
|
if (command.action === "help") {
|
|
18048
18707
|
console.log(TERMINAL_HOOKS_HELP);
|
|
@@ -18059,7 +18718,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18059
18718
|
}
|
|
18060
18719
|
} else if (subcommand === "agent-home") {
|
|
18061
18720
|
try {
|
|
18062
|
-
const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-
|
|
18721
|
+
const { parseAgentHomeArgs, runAgentHomeCommand } = await Promise.resolve().then(function () { return require('./agentHome-CpJjrQZc.cjs'); });
|
|
18063
18722
|
await runAgentHomeCommand(parseAgentHomeArgs(args.slice(1)));
|
|
18064
18723
|
process.exit(0);
|
|
18065
18724
|
} catch (error) {
|
|
@@ -18068,7 +18727,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18068
18727
|
}
|
|
18069
18728
|
} else if (subcommand === "spawn") {
|
|
18070
18729
|
try {
|
|
18071
|
-
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-
|
|
18730
|
+
const { handleSpawnCommand } = await Promise.resolve().then(function () { return require('./spawn-DA8WAFmm.cjs'); });
|
|
18072
18731
|
await handleSpawnCommand(args.slice(1));
|
|
18073
18732
|
} catch (error) {
|
|
18074
18733
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -18080,7 +18739,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18080
18739
|
return;
|
|
18081
18740
|
} else if (subcommand === "sessions") {
|
|
18082
18741
|
try {
|
|
18083
|
-
const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-
|
|
18742
|
+
const { handleSessionsCommand } = await Promise.resolve().then(function () { return require('./sessions-Tad8elmy.cjs'); });
|
|
18084
18743
|
await handleSessionsCommand(args.slice(1));
|
|
18085
18744
|
} catch (error) {
|
|
18086
18745
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -18092,7 +18751,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18092
18751
|
return;
|
|
18093
18752
|
} else if (subcommand === "send") {
|
|
18094
18753
|
try {
|
|
18095
|
-
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-
|
|
18754
|
+
const { handleSendCommand } = await Promise.resolve().then(function () { return require('./send-wl9ei8yG.cjs'); });
|
|
18096
18755
|
await handleSendCommand(args.slice(1));
|
|
18097
18756
|
} catch (error) {
|
|
18098
18757
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -18198,9 +18857,9 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18198
18857
|
if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
|
|
18199
18858
|
const projectId = args[3];
|
|
18200
18859
|
try {
|
|
18201
|
-
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
18202
|
-
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-
|
|
18203
|
-
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-
|
|
18860
|
+
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-DeJgSMh-.cjs'); });
|
|
18861
|
+
const { readCredentialsForConfiguredRelay: readCredentialsForConfiguredRelay2 } = await Promise.resolve().then(function () { return require('./limits-BNTWyUaZ.cjs'); }).then(function (n) { return n.persistence; });
|
|
18862
|
+
const { ApiClient: ApiClient2 } = await Promise.resolve().then(function () { return require('./types-CN28qJl7.cjs'); }).then(function (n) { return n.api; });
|
|
18204
18863
|
let userEmail = void 0;
|
|
18205
18864
|
try {
|
|
18206
18865
|
const credentials = await readCredentialsForConfiguredRelay2();
|
|
@@ -18231,7 +18890,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18231
18890
|
}
|
|
18232
18891
|
if (geminiSubcommand === "project" && args[2] === "get") {
|
|
18233
18892
|
try {
|
|
18234
|
-
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-
|
|
18893
|
+
const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-DeJgSMh-.cjs'); });
|
|
18235
18894
|
const config = readGeminiLocalConfig();
|
|
18236
18895
|
if (config.googleCloudProject) {
|
|
18237
18896
|
console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
|
|
@@ -18271,7 +18930,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18271
18930
|
process.exit(0);
|
|
18272
18931
|
}
|
|
18273
18932
|
try {
|
|
18274
|
-
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-
|
|
18933
|
+
const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-Bgg1BzDK.cjs'); });
|
|
18275
18934
|
let startedBy = void 0;
|
|
18276
18935
|
for (let i = 1; i < args.length; i++) {
|
|
18277
18936
|
if (args[i] === "--started-by") {
|
|
@@ -18294,7 +18953,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18294
18953
|
} else if (subcommand === "pi") {
|
|
18295
18954
|
if (args[1] === "--terminal") {
|
|
18296
18955
|
try {
|
|
18297
|
-
const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-
|
|
18956
|
+
const { runPiTerminal } = await Promise.resolve().then(function () { return require('./piTerminal-B7K75aXB.cjs'); });
|
|
18298
18957
|
process.exitCode = await runPiTerminal(args.slice(2));
|
|
18299
18958
|
} catch (error) {
|
|
18300
18959
|
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
@@ -18311,7 +18970,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18311
18970
|
}
|
|
18312
18971
|
};
|
|
18313
18972
|
try {
|
|
18314
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
18973
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-imt4mC41.cjs'); });
|
|
18315
18974
|
const parsed = parsePiRunnerArgs(args.slice(1));
|
|
18316
18975
|
const resolved = resolveAcpAgentConfig(["pi", ...parsed.passthrough]);
|
|
18317
18976
|
const { credentials } = await authAndSetupMachineIfNeeded();
|
|
@@ -18339,7 +18998,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18339
18998
|
return;
|
|
18340
18999
|
} else if (subcommand === "acp") {
|
|
18341
19000
|
try {
|
|
18342
|
-
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-
|
|
19001
|
+
const { runAcp, resolveAcpAgentConfig } = await Promise.resolve().then(function () { return require('./index-imt4mC41.cjs'); });
|
|
18343
19002
|
let startedBy = void 0;
|
|
18344
19003
|
let verbose = false;
|
|
18345
19004
|
const acpArgs = [];
|
|
@@ -18379,7 +19038,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18379
19038
|
return;
|
|
18380
19039
|
} else if (subcommand === "openclaw") {
|
|
18381
19040
|
try {
|
|
18382
|
-
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-
|
|
19041
|
+
const { runOpenClaw } = await Promise.resolve().then(function () { return require('./runOpenClaw-B9qWHybc.cjs'); });
|
|
18383
19042
|
let startedBy = void 0;
|
|
18384
19043
|
let verbose = false;
|
|
18385
19044
|
let gatewayUrl;
|
|
@@ -18430,7 +19089,7 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18430
19089
|
return;
|
|
18431
19090
|
} else if (subcommand === "todo") {
|
|
18432
19091
|
try {
|
|
18433
|
-
const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-
|
|
19092
|
+
const { handleTodoCommand } = await Promise.resolve().then(function () { return require('./todo-mCMoGjJk.cjs'); });
|
|
18434
19093
|
await handleTodoCommand(args.slice(1));
|
|
18435
19094
|
} catch (error) {
|
|
18436
19095
|
console.error(JSON.stringify({ error: error instanceof Error ? error.message : "Todo command failed" }));
|
|
@@ -18439,16 +19098,28 @@ Conversation history is preserved on the server, but in-flight tool calls are in
|
|
|
18439
19098
|
return;
|
|
18440
19099
|
} else if (subcommand === "teams") {
|
|
18441
19100
|
try {
|
|
18442
|
-
const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-
|
|
19101
|
+
const { handleTeamsCommand } = await Promise.resolve().then(function () { return require('./teams-qVLrFcdd.cjs'); });
|
|
18443
19102
|
await handleTeamsCommand(args.slice(1));
|
|
18444
19103
|
} catch (error) {
|
|
18445
19104
|
console.error(error instanceof Error ? error.message : "Teams command failed");
|
|
18446
19105
|
process.exitCode = 1;
|
|
18447
19106
|
}
|
|
18448
19107
|
return;
|
|
19108
|
+
} else if (subcommand === "auto") {
|
|
19109
|
+
try {
|
|
19110
|
+
const { handleAutoCommand } = await Promise.resolve().then(function () { return require('./auto-DncmTDvw.cjs'); });
|
|
19111
|
+
await handleAutoCommand(args.slice(1));
|
|
19112
|
+
} catch (error) {
|
|
19113
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Automation command failed");
|
|
19114
|
+
if (process.env.DEBUG) {
|
|
19115
|
+
console.error(error);
|
|
19116
|
+
}
|
|
19117
|
+
process.exitCode = 1;
|
|
19118
|
+
}
|
|
19119
|
+
return;
|
|
18449
19120
|
} else if (subcommand === "mcp" && (args.length === 1 || args.length === 2 && args[1] === "--terminal-tools")) {
|
|
18450
19121
|
try {
|
|
18451
|
-
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-
|
|
19122
|
+
const { handleMcpCommand } = await Promise.resolve().then(function () { return require('./mcp-CCKCKL6l.cjs'); });
|
|
18452
19123
|
await handleMcpCommand(args[1] === "--terminal-tools");
|
|
18453
19124
|
} catch (error) {
|
|
18454
19125
|
process.stderr.write(`[very-happy mcp] Fatal: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -18682,6 +19353,8 @@ ${chalk.bold("Usage:")}
|
|
|
18682
19353
|
conversations on this machine (agent-home --help)
|
|
18683
19354
|
very-happy connect Connect AI vendor API keys
|
|
18684
19355
|
very-happy todo Built-in Todos and official agent skill (todo --help)
|
|
19356
|
+
very-happy auto Scheduled / triggered automations: spawn, sticky
|
|
19357
|
+
sessions or scripts with tracked runs (auto --help)
|
|
18685
19358
|
very-happy sandbox Configure and manage OS-level sandboxing
|
|
18686
19359
|
very-happy notify Send push notification
|
|
18687
19360
|
very-happy mcp Stdio MCP server exposing copy_to_clipboard for a
|
|
@@ -18839,12 +19512,15 @@ exports.appendStagedAttachmentsToPrompt = appendStagedAttachmentsToPrompt;
|
|
|
18839
19512
|
exports.archiveSession = archiveSession;
|
|
18840
19513
|
exports.checkPreviewPath = checkPreviewPath;
|
|
18841
19514
|
exports.createSessionMetadata = createSessionMetadata;
|
|
19515
|
+
exports.describeAction = describeAction;
|
|
19516
|
+
exports.describeTrigger = describeTrigger;
|
|
18842
19517
|
exports.hashObject = hashObject;
|
|
18843
19518
|
exports.initialMachineMetadata = initialMachineMetadata;
|
|
18844
19519
|
exports.isValidSpawnOrigin = isValidSpawnOrigin;
|
|
18845
19520
|
exports.listAccountSessions = listAccountSessions;
|
|
18846
19521
|
exports.listSessions = listSessions;
|
|
18847
19522
|
exports.normalizeAcpPermissionMode = normalizeAcpPermissionMode;
|
|
19523
|
+
exports.parseDuration = parseDuration;
|
|
18848
19524
|
exports.query = query;
|
|
18849
19525
|
exports.readSessionMetadata = readSessionMetadata;
|
|
18850
19526
|
exports.readSessionTranscript = readSessionTranscript;
|
|
@@ -18852,7 +19528,9 @@ exports.registerAgentAttachmentDownloads = registerAgentAttachmentDownloads;
|
|
|
18852
19528
|
exports.registerAssistantSessionTools = registerAssistantSessionTools;
|
|
18853
19529
|
exports.registerKillSessionHandler = registerKillSessionHandler;
|
|
18854
19530
|
exports.removeSessionModeFile = removeSessionModeFile;
|
|
19531
|
+
exports.resolveFirstMessageMeta = resolveFirstMessageMeta;
|
|
18855
19532
|
exports.resolvePermissionRequest = resolvePermissionRequest;
|
|
19533
|
+
exports.resolveSpawnPermissionMode = resolveSpawnPermissionMode;
|
|
18856
19534
|
exports.sanitizeSpawnPermissionMode = sanitizeSpawnPermissionMode;
|
|
18857
19535
|
exports.sendUserMessage = sendUserMessage;
|
|
18858
19536
|
exports.sessionWebUrl = sessionWebUrl;
|
|
@@ -18861,6 +19539,7 @@ exports.stageClaudeAttachments = stageClaudeAttachments;
|
|
|
18861
19539
|
exports.startHappyServer = startHappyServer;
|
|
18862
19540
|
exports.stopSession = stopSession;
|
|
18863
19541
|
exports.tmuxSupportsSessionEnv = tmuxSupportsSessionEnv;
|
|
19542
|
+
exports.triggerFromFlags = triggerFromFlags;
|
|
18864
19543
|
exports.waitForSessionKey = waitForSessionKey;
|
|
18865
19544
|
exports.waitForTurnEnd = waitForTurnEnd;
|
|
18866
19545
|
exports.writeSessionModeFile = writeSessionModeFile;
|