@tekmidian/pai 0.64.0 → 0.65.1
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/README.md +60 -1051
- package/dist/{aibroker-client-BpfuGPe5.mjs → aibroker-client-B8c42Lh8.mjs} +1 -1
- package/dist/{aibroker-client-DRld7g6z.mjs → aibroker-client-C5Fw7DNz.mjs} +10 -4
- package/dist/{aibroker-client-DRld7g6z.mjs.map → aibroker-client-C5Fw7DNz.mjs.map} +1 -1
- package/dist/{async-CY_cd_8j.mjs → async-CNn36gm4.mjs} +2 -2
- package/dist/{async-CY_cd_8j.mjs.map → async-CNn36gm4.mjs.map} +1 -1
- package/dist/{auto-route-CPlam4iv.mjs → auto-route-sLMU-NnM.mjs} +2 -2
- package/dist/{auto-route-CPlam4iv.mjs.map → auto-route-sLMU-NnM.mjs.map} +1 -1
- package/dist/{chain-o-g8AgE3.mjs → chain-CLb6hbFS.mjs} +4 -4
- package/dist/{chain-o-g8AgE3.mjs.map → chain-CLb6hbFS.mjs.map} +1 -1
- package/dist/cli/index.mjs +19 -19
- package/dist/cli/program.d.mts.map +1 -1
- package/dist/cli/program.mjs +19 -19
- package/dist/{clusters-DsMf20PP.mjs → clusters-PgIUYT_v.mjs} +1 -1
- package/dist/{clusters-DsMf20PP.mjs.map → clusters-PgIUYT_v.mjs.map} +1 -1
- package/dist/{config-2wkz744W.mjs → config-BbLFD7Uf.mjs} +3 -3
- package/dist/config-BbLFD7Uf.mjs.map +1 -0
- package/dist/{config-CUTg6VDq.mjs → config-YinjgXEJ.mjs} +1 -1
- package/dist/{context-handover-cache-BOpjLsKe.mjs → context-handover-cache-mGxq2-8f.mjs} +11 -29
- package/dist/context-handover-cache-mGxq2-8f.mjs.map +1 -0
- package/dist/daemon/index.mjs +16 -16
- package/dist/daemon-BjaPR39W.mjs +19 -0
- package/dist/{daemon-BYieXduQ.mjs → daemon-DqCB3fO-.mjs} +30 -30
- package/dist/{daemon-BYieXduQ.mjs.map → daemon-DqCB3fO-.mjs.map} +1 -1
- package/dist/daemon-mcp/index.mjs +18 -18
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/detector-C3Q7mxQU.mjs +3 -0
- package/dist/{detector-BAlmrLQ0.mjs → detector-CIHEXKsV.mjs} +1 -1
- package/dist/{detector-BAlmrLQ0.mjs.map → detector-CIHEXKsV.mjs.map} +1 -1
- package/dist/{embeddings-DK9XfQic.mjs → embeddings-BbNVXa_0.mjs} +1 -1
- package/dist/{embeddings-DK9XfQic.mjs.map → embeddings-BbNVXa_0.mjs.map} +1 -1
- package/dist/{embeddings-Xg8XLf2K.mjs → embeddings-CDfM63uC.mjs} +1 -1
- package/dist/{factory-BMK0tC1b.mjs → factory-CaswxuJ0.mjs} +1 -1
- package/dist/{factory-C4We3xR_.mjs → factory-y36qGegI.mjs} +13 -13
- package/dist/{factory-C4We3xR_.mjs.map → factory-y36qGegI.mjs.map} +1 -1
- package/dist/{fallback-ECiqCuh6.mjs → fallback-CupzGkuJ.mjs} +1205 -1204
- package/dist/fallback-CupzGkuJ.mjs.map +1 -0
- package/dist/{federation-db-CUgy0WYs.mjs → federation-db-BTyoufBh.mjs} +2 -2
- package/dist/{federation-db-CUgy0WYs.mjs.map → federation-db-BTyoufBh.mjs.map} +1 -1
- package/dist/federation-db-HfIFc7FG.mjs +3 -0
- package/dist/hooks/block-sleep-poll.mjs +36 -11
- package/dist/hooks/block-sleep-poll.mjs.map +2 -2
- package/dist/hooks/capture-all-events.mjs +3 -17
- package/dist/hooks/capture-all-events.mjs.map +3 -3
- package/dist/hooks/capture-session-summary.mjs +3 -17
- package/dist/hooks/capture-session-summary.mjs.map +3 -3
- package/dist/hooks/capture-tool-output.mjs +3 -17
- package/dist/hooks/capture-tool-output.mjs.map +3 -3
- package/dist/hooks/cleanup-session-files.mjs +3 -17
- package/dist/hooks/cleanup-session-files.mjs.map +2 -2
- package/dist/hooks/context-compression-hook.mjs +3 -17
- package/dist/hooks/context-compression-hook.mjs.map +3 -3
- package/dist/hooks/initialize-session.mjs +3 -17
- package/dist/hooks/initialize-session.mjs.map +2 -2
- package/dist/hooks/inject-observations.mjs +3 -17
- package/dist/hooks/inject-observations.mjs.map +2 -2
- package/dist/hooks/load-core-context.mjs +4 -22
- package/dist/hooks/load-core-context.mjs.map +2 -2
- package/dist/hooks/load-project-context.mjs +3 -17
- package/dist/hooks/load-project-context.mjs.map +3 -3
- package/dist/hooks/mcp-deferred-gate.mjs +3 -17
- package/dist/hooks/mcp-deferred-gate.mjs.map +2 -2
- package/dist/hooks/observe.mjs +3 -17
- package/dist/hooks/observe.mjs.map +2 -2
- package/dist/hooks/post-compact-inject.mjs.map +1 -1
- package/dist/hooks/route-agents-to-worker.mjs.map +1 -1
- package/dist/hooks/security-validator.mjs +5 -19
- package/dist/hooks/security-validator.mjs.map +3 -3
- package/dist/hooks/stop-hook.mjs +3 -17
- package/dist/hooks/stop-hook.mjs.map +3 -3
- package/dist/hooks/sync-todo-to-md.mjs +3 -17
- package/dist/hooks/sync-todo-to-md.mjs.map +2 -2
- package/dist/hooks/whisper-rules.mjs.map +1 -1
- package/dist/hooks/worker-guard.mjs.map +2 -2
- package/dist/hooks/worker-proxy.mjs.map +1 -1
- package/dist/hooks/worker-status-line.mjs +4 -4
- package/dist/hooks/worker-status-line.mjs.map +2 -2
- package/dist/hooks/worker-supervision.mjs.map +1 -1
- package/dist/{indexer-backend-CJ0RGgMz.mjs → indexer-backend-Cnc7Tf5C.mjs} +2 -2
- package/dist/{ipc-client-EhWY8XL0.mjs → ipc-client-D16Xw6Uo.mjs} +2 -2
- package/dist/{ipc-client-EhWY8XL0.mjs.map → ipc-client-D16Xw6Uo.mjs.map} +1 -1
- package/dist/{kg-entity-1uqCnk4u.mjs → kg-entity-COTUj1ZC.mjs} +1 -1
- package/dist/{kg-entity-1uqCnk4u.mjs.map → kg-entity-COTUj1ZC.mjs.map} +1 -1
- package/dist/{latent-ideas-CSuKfiq3.mjs → latent-ideas-ByvMjVcb.mjs} +3 -3
- package/dist/{latent-ideas-CSuKfiq3.mjs.map → latent-ideas-ByvMjVcb.mjs.map} +1 -1
- package/dist/{link-boost-BtjzfE3c.mjs → link-boost-UiE-uooT.mjs} +1 -1
- package/dist/{link-boost-BtjzfE3c.mjs.map → link-boost-UiE-uooT.mjs.map} +1 -1
- package/dist/{main-resolver-DyOrwNYw.mjs → main-resolver-BeYWNzrt.mjs} +11 -11
- package/dist/{main-resolver-DyOrwNYw.mjs.map → main-resolver-BeYWNzrt.mjs.map} +1 -1
- package/dist/main-resolver-kHW6FewU.mjs +7 -0
- package/dist/merge-2gqRPFu2.mjs +3 -0
- package/dist/{merge-D58n_-LZ.mjs → merge-DgU9OgZy.mjs} +1 -1
- package/dist/{merge-D58n_-LZ.mjs.map → merge-DgU9OgZy.mjs.map} +1 -1
- package/dist/module-paths-DdRzbkUI.mjs +44 -0
- package/dist/module-paths-DdRzbkUI.mjs.map +1 -0
- package/dist/{neighborhood-DNuRelRB.mjs → neighborhood-CvRHlqdR.mjs} +2 -2
- package/dist/{neighborhood-DNuRelRB.mjs.map → neighborhood-CvRHlqdR.mjs.map} +1 -1
- package/dist/{note-context-D9JZ4-7o.mjs → note-context-BrbfUIoP.mjs} +1 -1
- package/dist/{note-context-D9JZ4-7o.mjs.map → note-context-BrbfUIoP.mjs.map} +1 -1
- package/dist/{pai-home-UncxWxlX.mjs → pai-home-Cm9rcJgX.mjs} +1 -1
- package/dist/{pai-home-UncxWxlX.mjs.map → pai-home-Cm9rcJgX.mjs.map} +1 -1
- package/dist/{planner-DgC3oSvb.mjs → planner-DAq4Yx-H.mjs} +7 -7
- package/dist/{planner-DgC3oSvb.mjs.map → planner-DAq4Yx-H.mjs.map} +1 -1
- package/dist/{postgres-CcsRKir-.mjs → postgres-DYtZg7J7.mjs} +5 -13
- package/dist/{postgres-CcsRKir-.mjs.map → postgres-DYtZg7J7.mjs.map} +1 -1
- package/dist/{program-JhF2GgJY.mjs → program-CWf9mT7Z.mjs} +262 -260
- package/dist/program-CWf9mT7Z.mjs.map +1 -0
- package/dist/{query-feedback-BPa0dISE.mjs → query-feedback-BIaZTTFO.mjs} +2 -2
- package/dist/{query-feedback-BPa0dISE.mjs.map → query-feedback-BIaZTTFO.mjs.map} +1 -1
- package/dist/query-feedback-B_iigYj-.mjs +3 -0
- package/dist/{registry-db-DCzdI4sC.mjs → registry-db-C7voqML9.mjs} +2 -2
- package/dist/{registry-db-DCzdI4sC.mjs.map → registry-db-C7voqML9.mjs.map} +1 -1
- package/dist/registry-db-JHPhA8vF.mjs +3 -0
- package/dist/{registry-postgres-BUnkHKYs.mjs → registry-postgres-DSrkxqfF.mjs} +2 -2
- package/dist/{registry-postgres-BUnkHKYs.mjs.map → registry-postgres-DSrkxqfF.mjs.map} +1 -1
- package/dist/{registry-sqlite-CKYNwkUv.mjs → registry-sqlite-B2436JgX.mjs} +2 -2
- package/dist/{registry-sqlite-CKYNwkUv.mjs.map → registry-sqlite-B2436JgX.mjs.map} +1 -1
- package/dist/router-S6C5BxzZ.mjs +3 -0
- package/dist/{router-CGZATlvm.mjs → router-aqLMvNMg.mjs} +1 -1
- package/dist/{router-CGZATlvm.mjs.map → router-aqLMvNMg.mjs.map} +1 -1
- package/dist/{run-env-Br4Bc7Vz.mjs → run-env-BHWnXqle.mjs} +3 -3
- package/dist/{run-env-Br4Bc7Vz.mjs.map → run-env-BHWnXqle.mjs.map} +1 -1
- package/dist/{run-W2rV_9j0.mjs → run-uAkNItb6.mjs} +140 -44
- package/dist/run-uAkNItb6.mjs.map +1 -0
- package/dist/{runtime-paths-QGQJAekd.mjs → runtime-paths-CHTg3ywb.mjs} +1 -1
- package/dist/{runtime-paths-QGQJAekd.mjs.map → runtime-paths-CHTg3ywb.mjs.map} +1 -1
- package/dist/{server-B71rem4q.mjs → server-DlL1QI2k.mjs} +4 -5
- package/dist/server-DlL1QI2k.mjs.map +1 -0
- package/dist/{session-keepalive-Dgil9hjw.mjs → session-keepalive-BWEjcRrh.mjs} +7 -7
- package/dist/{session-keepalive-Dgil9hjw.mjs.map → session-keepalive-BWEjcRrh.mjs.map} +1 -1
- package/dist/skills/Art/SKILL.md +1 -1
- package/dist/skills/Observability/SKILL.md +4 -4
- package/dist/skills/Research/SKILL.md +1 -1
- package/dist/skills/Tasks/SKILL.md +1 -1
- package/dist/{sources-LcGptLA-.mjs → sources-DX4ElmrE.mjs} +1 -1
- package/dist/{sources-LcGptLA-.mjs.map → sources-DX4ElmrE.mjs.map} +1 -1
- package/dist/{sqlite-CAJcw2zL.mjs → sqlite-BrEu3avy.mjs} +3 -3
- package/dist/{sqlite-CAJcw2zL.mjs.map → sqlite-BrEu3avy.mjs.map} +1 -1
- package/dist/{state-S9wlKarB.mjs → state-DW8zdweW.mjs} +1 -1
- package/dist/{state-CHltNjXI.mjs → state-HyjqTihC.mjs} +1 -1
- package/dist/{state-CHltNjXI.mjs.map → state-HyjqTihC.mjs.map} +1 -1
- package/dist/{themes-D1FQFthd.mjs → themes-BgqahYVM.mjs} +2 -2
- package/dist/{themes-D1FQFthd.mjs.map → themes-BgqahYVM.mjs.map} +1 -1
- package/dist/{tools-BW7OXf-N.mjs → tools-BbqQIHPe.mjs} +4 -4
- package/dist/{tools-BFC-113F.mjs → tools-gMGDIpJ9.mjs} +18 -18
- package/dist/{tools-BFC-113F.mjs.map → tools-gMGDIpJ9.mjs.map} +1 -1
- package/dist/{trace-IDKK1VFs.mjs → trace-CmAB7iJZ.mjs} +1 -1
- package/dist/{trace-IDKK1VFs.mjs.map → trace-CmAB7iJZ.mjs.map} +1 -1
- package/dist/{vault-indexer-y6YC2-mh.mjs → vault-indexer-Ddq51X20.mjs} +1 -1
- package/dist/{vault-indexer-y6YC2-mh.mjs.map → vault-indexer-Ddq51X20.mjs.map} +1 -1
- package/dist/{wakeup-CNZQZzsY.mjs → wakeup-CZw88uXf.mjs} +3 -3
- package/dist/{wakeup-CNZQZzsY.mjs.map → wakeup-CZw88uXf.mjs.map} +1 -1
- package/dist/{work-queue-worker-Dy5FT2ak.mjs → work-queue-worker-DCzfH0d1.mjs} +4 -4
- package/dist/{work-queue-worker-Dy5FT2ak.mjs.map → work-queue-worker-DCzfH0d1.mjs.map} +1 -1
- package/dist/work-queue-worker-Taba_vcA.mjs +11 -0
- package/dist/{zettelkasten-Dx-63BEk.mjs → zettelkasten-Dwj67e4p.mjs} +4 -4
- package/dist/{zettelkasten-Dx-63BEk.mjs.map → zettelkasten-Dwj67e4p.mjs.map} +1 -1
- package/docker/docker-compose.yml +39 -0
- package/docs/auto-compact.md +31 -0
- package/docs/budget-advisor.md +48 -0
- package/docs/command-reference.md +25 -0
- package/docs/commands/README.md +3 -3
- package/docs/commands/config.md +3 -3
- package/docs/commands/setup.md +9 -2
- package/docs/commands/worker.md +2 -2
- package/docs/companion-projects.md +9 -0
- package/docs/context-preservation.md +43 -0
- package/docs/how-it-works.md +25 -0
- package/docs/install-linux.md +32 -0
- package/docs/install.md +56 -0
- package/docs/memory.md +96 -0
- package/docs/observations.md +58 -0
- package/docs/release-history.md +42 -0
- package/docs/rules-and-privacy.md +37 -0
- package/docs/search.md +169 -0
- package/docs/session-management.md +153 -0
- package/docs/session-notes.md +64 -0
- package/docs/skills.md +45 -0
- package/docs/task-bus.md +1 -2
- package/docs/use-cases.md +194 -0
- package/docs/what-you-can-ask.md +78 -0
- package/docs/worker-providers.md +58 -0
- package/docs/zettelkasten.md +37 -0
- package/package.json +3 -2
- package/plugins/productivity/skills/Tasks/SKILL.md +1 -1
- package/scripts/build-hooks.mjs +6 -6
- package/src/hooks/ts/lib/pai-paths-case.test.ts +12 -0
- package/src/hooks/ts/lib/pai-paths-import.test.ts +25 -0
- package/src/hooks/ts/lib/pai-paths.ts +5 -28
- package/src/hooks/ts/lib/sleep-poll-gate.test.ts +17 -1
- package/src/hooks/ts/lib/sleep-poll-gate.ts +21 -9
- package/src/hooks/ts/pre-tool-use/security-validator.test.ts +23 -0
- package/src/hooks/ts/pre-tool-use/security-validator.ts +1 -1
- package/src/hooks/ts/session-start/load-core-context.ts +2 -6
- package/src/hooks/ts/session-start/load-project-context.ts +1 -1
- package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +24 -1
- package/dist/config-2wkz744W.mjs.map +0 -1
- package/dist/context-handover-cache-BOpjLsKe.mjs.map +0 -1
- package/dist/daemon-q3xjHwa4.mjs +0 -19
- package/dist/detector-C-YmZsOi.mjs +0 -3
- package/dist/fallback-ECiqCuh6.mjs.map +0 -1
- package/dist/federation-db-BZ8PyxFe.mjs +0 -3
- package/dist/main-resolver-vN09bkXv.mjs +0 -7
- package/dist/merge-CXGz5wXz.mjs +0 -3
- package/dist/program-JhF2GgJY.mjs.map +0 -1
- package/dist/query-feedback-BPHFFSu1.mjs +0 -3
- package/dist/registry-db-Hphlj3H4.mjs +0 -3
- package/dist/router-CoA8Uy1m.mjs +0 -3
- package/dist/run-W2rV_9j0.mjs.map +0 -1
- package/dist/server-B71rem4q.mjs.map +0 -1
- package/dist/work-queue-worker-CkShUa0z.mjs +0 -11
- /package/dist/{indexer-backend-DotpxHJd.mjs → indexer-backend-isSLg6yE.mjs} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as getRegistryBackend } from "./factory-
|
|
2
|
-
import { E as readWorkersSection, O as resolveModelCapability, T as providerKeyPath, b as isModelCapability, d as NATIVE_ANTHROPIC_MODELS, g as classModelCapability, h as assertProviderRunnable, k as resolveProviderKey, m as WorkersConfigError, n as claudeCommand, t as buildRunEnv } from "./run-env-
|
|
3
|
-
import { _ as statusPath, d as resolveTarget, f as setCooldown, g as panesDir, h as ledgerPath, i as capabilityForRun, m as eventsPath, n as ensureProxyRunning, o as isQuotaFailure, p as ensureNoMcpConfig, s as nextAutoProvider, t as DEFAULT_PROXY_PORT, u as resolveCapabilityRun, v as workersLogDir } from "./server-
|
|
1
|
+
import { i as getRegistryBackend } from "./factory-y36qGegI.mjs";
|
|
2
|
+
import { E as readWorkersSection, O as resolveModelCapability, T as providerKeyPath, b as isModelCapability, d as NATIVE_ANTHROPIC_MODELS, g as classModelCapability, h as assertProviderRunnable, k as resolveProviderKey, m as WorkersConfigError, n as claudeCommand, t as buildRunEnv } from "./run-env-BHWnXqle.mjs";
|
|
3
|
+
import { _ as statusPath, d as resolveTarget, f as setCooldown, g as panesDir, h as ledgerPath, i as capabilityForRun, m as eventsPath, n as ensureProxyRunning, o as isQuotaFailure, p as ensureNoMcpConfig, s as nextAutoProvider, t as DEFAULT_PROXY_PORT, u as resolveCapabilityRun, v as workersLogDir } from "./server-DlL1QI2k.mjs";
|
|
4
4
|
import { appendFileSync, closeSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
5
5
|
import { homedir, platform, tmpdir } from "node:os";
|
|
6
6
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -233,6 +233,7 @@ function parseRunnerArgs(argv) {
|
|
|
233
233
|
let callerModel = false;
|
|
234
234
|
let callerMcpConfig = false;
|
|
235
235
|
let callerSystemPrompt = false;
|
|
236
|
+
const callerSystemPrompts = [];
|
|
236
237
|
let callerTools = false;
|
|
237
238
|
const mcp = [];
|
|
238
239
|
const allowedTools = [];
|
|
@@ -254,7 +255,13 @@ function parseRunnerArgs(argv) {
|
|
|
254
255
|
} else if (a.startsWith("--output-format=")) {
|
|
255
256
|
const v = a.slice(16);
|
|
256
257
|
if (v === "json" || v === "stream-json") outputFormat = v;
|
|
257
|
-
} else if (a === "--verbose") {} else if (a === "--
|
|
258
|
+
} else if (a === "--verbose") {} else if (a === "--append-system-prompt") {
|
|
259
|
+
callerSystemPrompt = true;
|
|
260
|
+
if (i + 1 < argv.length) callerSystemPrompts.push(argv[++i]);
|
|
261
|
+
} else if (a.startsWith("--append-system-prompt=")) {
|
|
262
|
+
callerSystemPrompt = true;
|
|
263
|
+
callerSystemPrompts.push(a.slice(23));
|
|
264
|
+
} else if (a === "--mcp") {
|
|
258
265
|
const v = argv[i + 1];
|
|
259
266
|
if (v !== void 0 && !v.startsWith("-")) {
|
|
260
267
|
mcp.push(v);
|
|
@@ -277,8 +284,6 @@ function parseRunnerArgs(argv) {
|
|
|
277
284
|
if (a.startsWith("--model=")) callerModel = true;
|
|
278
285
|
if (a === "--mcp-config") callerMcpConfig = true;
|
|
279
286
|
if (a.startsWith("--mcp-config=")) callerMcpConfig = true;
|
|
280
|
-
if (a === "--append-system-prompt") callerSystemPrompt = true;
|
|
281
|
-
if (a.startsWith("--append-system-prompt=")) callerSystemPrompt = true;
|
|
282
287
|
if (a === "--tools") callerTools = true;
|
|
283
288
|
if (a.startsWith("--tools=")) callerTools = true;
|
|
284
289
|
if (prompt === null && !a.startsWith("-") && rest.length > 0 && (rest[rest.length - 1] === "-p" || rest[rest.length - 1] === "--print")) prompt = a;
|
|
@@ -294,12 +299,22 @@ function parseRunnerArgs(argv) {
|
|
|
294
299
|
callerModel,
|
|
295
300
|
callerMcpConfig,
|
|
296
301
|
callerSystemPrompt,
|
|
302
|
+
callerSystemPrompts,
|
|
297
303
|
callerTools,
|
|
298
304
|
mcp,
|
|
299
305
|
allowedTools
|
|
300
306
|
};
|
|
301
307
|
}
|
|
302
308
|
/**
|
|
309
|
+
* The one --append-system-prompt flag for a spawn: claude keeps only the LAST
|
|
310
|
+
* occurrence, so every piece is joined (blank line between) into a single flag.
|
|
311
|
+
* Empty parts are dropped; no parts, no flag.
|
|
312
|
+
*/
|
|
313
|
+
function appendSystemPromptArgs(parts) {
|
|
314
|
+
const text = parts.filter((p) => p.trim()).join("\n\n");
|
|
315
|
+
return text ? ["--append-system-prompt", text] : [];
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
303
318
|
* Turn `-p "<prompt>"` into bare `-p` (same for --print): for stream-json
|
|
304
319
|
* stdin runs the prompt moves to the first user message on stdin, so the
|
|
305
320
|
* value must not stay on the command line. Only prompt values directly
|
|
@@ -903,6 +918,10 @@ function salvageOnExit(ledger, id, label, wtDir, timeoutMs) {
|
|
|
903
918
|
paths: committed.join(","),
|
|
904
919
|
skipped: skipped.length
|
|
905
920
|
});
|
|
921
|
+
if (skipped.length) appendLedger(ledger, "WORKER-NOTE", {
|
|
922
|
+
id,
|
|
923
|
+
note: `salvage skipped: ${skipped.join("; ")}`
|
|
924
|
+
});
|
|
906
925
|
return committed;
|
|
907
926
|
} catch (e) {
|
|
908
927
|
try {
|
|
@@ -992,8 +1011,10 @@ function salvageUncommitted(wtDir, label, timeoutMs) {
|
|
|
992
1011
|
skipped: []
|
|
993
1012
|
};
|
|
994
1013
|
const skipped = [];
|
|
1014
|
+
const missing = new Set(git(wtDir, ["ls-files", "--deleted"], timeoutMs).split("\n").filter(Boolean));
|
|
995
1015
|
const toStage = [];
|
|
996
|
-
for (const p of paths) if (
|
|
1016
|
+
for (const p of paths) if (missing.has(p)) skipped.push(`${p} (missing, not committed)`);
|
|
1017
|
+
else if (symlinkEscapesWorktree(wtDir, p)) skipped.push(`symlink ${p} -> ${readlinkSync(join(wtDir, p))} (points outside the worktree)`);
|
|
997
1018
|
else toStage.push(p);
|
|
998
1019
|
if (!toStage.length) return {
|
|
999
1020
|
committed: [],
|
|
@@ -1002,11 +1023,21 @@ function salvageUncommitted(wtDir, label, timeoutMs) {
|
|
|
1002
1023
|
try {
|
|
1003
1024
|
git(wtDir, [
|
|
1004
1025
|
"add",
|
|
1005
|
-
"-
|
|
1026
|
+
"--ignore-removal",
|
|
1006
1027
|
"--",
|
|
1007
1028
|
".",
|
|
1008
1029
|
...paths.filter((p) => !toStage.includes(p)).map((p) => `:(exclude,literal)${p}`)
|
|
1009
1030
|
], timeoutMs);
|
|
1031
|
+
const deleted = git(wtDir, [
|
|
1032
|
+
"diff",
|
|
1033
|
+
"--cached",
|
|
1034
|
+
"--diff-filter=D",
|
|
1035
|
+
"--name-only"
|
|
1036
|
+
], timeoutMs).split("\n").filter(Boolean);
|
|
1037
|
+
if (deleted.length > MAX_SALVAGE_DELETES) {
|
|
1038
|
+
git(wtDir, ["reset", "-q"], timeoutMs);
|
|
1039
|
+
throw new Error(`salvage would delete ${deleted.length} tracked files (${deleted.slice(0, 5).join(", ")}, ...), refused`);
|
|
1040
|
+
}
|
|
1010
1041
|
git(wtDir, [
|
|
1011
1042
|
"commit",
|
|
1012
1043
|
"-m",
|
|
@@ -1020,6 +1051,8 @@ function salvageUncommitted(wtDir, label, timeoutMs) {
|
|
|
1020
1051
|
skipped
|
|
1021
1052
|
};
|
|
1022
1053
|
}
|
|
1054
|
+
/** A salvage commit that deletes more tracked files than this is refused. */
|
|
1055
|
+
const MAX_SALVAGE_DELETES = 5;
|
|
1023
1056
|
/**
|
|
1024
1057
|
* The dirty paths of a checkout, parsed from `git status --porcelain -z`:
|
|
1025
1058
|
* NUL-separated (a path with a newline in it cannot corrupt the parse),
|
|
@@ -1338,14 +1371,20 @@ function gcWorktrees(logDir, olderThanHours = 24, dryRun = false, now = Date.now
|
|
|
1338
1371
|
const out = [];
|
|
1339
1372
|
const root = worktreesDir(logDir);
|
|
1340
1373
|
const known = /* @__PURE__ */ new Set();
|
|
1341
|
-
const archive = (id, dir,
|
|
1374
|
+
const archive = (id, dir, st) => {
|
|
1342
1375
|
const target = `refs/pai-archive/${id}`;
|
|
1343
1376
|
if (dryRun) return void out.push({
|
|
1344
1377
|
id,
|
|
1345
1378
|
archive: target
|
|
1346
1379
|
});
|
|
1347
1380
|
try {
|
|
1348
|
-
|
|
1381
|
+
let repo;
|
|
1382
|
+
try {
|
|
1383
|
+
const raw = git(dir, ["rev-parse", "--git-common-dir"]);
|
|
1384
|
+
repo = isAbsolute(raw) ? raw : resolve(dir, raw);
|
|
1385
|
+
} catch {
|
|
1386
|
+
throw new Error("not a git worktree");
|
|
1387
|
+
}
|
|
1349
1388
|
const label = `archive: leftover state of worker ${id}`;
|
|
1350
1389
|
if (uncommittedPaths(dir).length) {
|
|
1351
1390
|
const res = salvageUncommitted(dir, label);
|
|
@@ -1424,7 +1463,7 @@ function gcWorktrees(logDir, olderThanHours = 24, dryRun = false, now = Date.now
|
|
|
1424
1463
|
continue;
|
|
1425
1464
|
}
|
|
1426
1465
|
if (end > cutoff) continue;
|
|
1427
|
-
archive(st.id, st.worktreeDir, st
|
|
1466
|
+
archive(st.id, st.worktreeDir, st);
|
|
1428
1467
|
}
|
|
1429
1468
|
if (existsSync(root)) for (const ent of readdirSync(root, { withFileTypes: true })) {
|
|
1430
1469
|
if (!ent.isDirectory() || known.has(ent.name) || existsSync(statusPath(logDir, ent.name))) continue;
|
|
@@ -1434,14 +1473,7 @@ function gcWorktrees(logDir, olderThanHours = 24, dryRun = false, now = Date.now
|
|
|
1434
1473
|
} catch {
|
|
1435
1474
|
continue;
|
|
1436
1475
|
}
|
|
1437
|
-
|
|
1438
|
-
try {
|
|
1439
|
-
const raw = git(dir, ["rev-parse", "--git-common-dir"]);
|
|
1440
|
-
repo = isAbsolute(raw) ? raw : resolve(dir, raw);
|
|
1441
|
-
} catch {
|
|
1442
|
-
repo = null;
|
|
1443
|
-
}
|
|
1444
|
-
archive(ent.name, dir, repo, null);
|
|
1476
|
+
archive(ent.name, dir, null);
|
|
1445
1477
|
}
|
|
1446
1478
|
if (!dryRun) for (const repo of new Set(loadStatuses(logDir).map((s) => s.cwd))) try {
|
|
1447
1479
|
git(repo, ["worktree", "prune"]);
|
|
@@ -2200,12 +2232,51 @@ function absoluteCliPath() {
|
|
|
2200
2232
|
if (argv1.endsWith("pai")) return argv1;
|
|
2201
2233
|
return "pai";
|
|
2202
2234
|
}
|
|
2235
|
+
/** The one place that decides where a follow pane opens: tmux (any OS) > iTerm2 (macOS) > nowhere. */
|
|
2236
|
+
function paneBackend(env = process.env, platform = process.platform) {
|
|
2237
|
+
if (env.TMUX) return "tmux";
|
|
2238
|
+
if (platform === "darwin" && env.ITERM_SESSION_ID) return "iterm";
|
|
2239
|
+
return "none";
|
|
2240
|
+
}
|
|
2241
|
+
function noPaneMessage(wid) {
|
|
2242
|
+
return `no pane support here, use: pai worker follow${wid ? ` ${wid}` : ""}`;
|
|
2243
|
+
}
|
|
2244
|
+
/** Split the current tmux window horizontally (right-hand column) and run cmd in it, focus stays put. */
|
|
2245
|
+
function tmuxSplit(cmd) {
|
|
2246
|
+
const target = process.env.TMUX_PANE ? ["-t", process.env.TMUX_PANE] : [];
|
|
2247
|
+
try {
|
|
2248
|
+
execFileSync("tmux", [
|
|
2249
|
+
"split-window",
|
|
2250
|
+
"-h",
|
|
2251
|
+
"-d",
|
|
2252
|
+
"-l",
|
|
2253
|
+
"40%",
|
|
2254
|
+
...target,
|
|
2255
|
+
cmd
|
|
2256
|
+
], { stdio: "pipe" });
|
|
2257
|
+
} catch (e) {
|
|
2258
|
+
const err = e;
|
|
2259
|
+
throw new Error(`pai worker pane: tmux split-window failed: ${(err.stderr?.toString() || err.message || "").trim().slice(0, 200)}`);
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2203
2262
|
/** Open (or only report on) the stacked follow pane of one worker. */
|
|
2204
2263
|
async function openPaneForWorker(logDir, config, wid, term) {
|
|
2205
2264
|
if (workerPaneOpen(wid)) return {
|
|
2206
2265
|
message: `pane for ${wid} already open`,
|
|
2207
2266
|
session: null
|
|
2208
2267
|
};
|
|
2268
|
+
const backend = paneBackend();
|
|
2269
|
+
if (backend === "none") return {
|
|
2270
|
+
message: noPaneMessage(wid),
|
|
2271
|
+
session: null
|
|
2272
|
+
};
|
|
2273
|
+
if (backend === "tmux") {
|
|
2274
|
+
tmuxSplit(followCommand(wid, config.pane.autoExitSecs));
|
|
2275
|
+
return {
|
|
2276
|
+
message: `pane opened for ${wid}`,
|
|
2277
|
+
session: null
|
|
2278
|
+
};
|
|
2279
|
+
}
|
|
2209
2280
|
const uid = itermUuid(term);
|
|
2210
2281
|
const regPath = join(panesDir(logDir), `${scopeKey(term)}.json`);
|
|
2211
2282
|
const reg = loadRegistry(regPath);
|
|
@@ -2259,6 +2330,7 @@ async function windowBoundsLine(term) {
|
|
|
2259
2330
|
*/
|
|
2260
2331
|
async function checkPaneForWorker(wid, fontSize, term) {
|
|
2261
2332
|
const lines = [workerPaneOpen(wid) ? `pane for ${wid} open` : `no pane for ${wid}`];
|
|
2333
|
+
if (paneBackend() !== "iterm") return lines.join("\n");
|
|
2262
2334
|
lines.push(await windowBoundsLine(term));
|
|
2263
2335
|
const path = dynamicProfilePath();
|
|
2264
2336
|
if (existsSync(path)) {
|
|
@@ -2281,6 +2353,13 @@ async function checkPaneForWorker(wid, fontSize, term) {
|
|
|
2281
2353
|
* with the running command, so names cannot serve as idempotence).
|
|
2282
2354
|
*/
|
|
2283
2355
|
async function openFollowPane(logDir, _config, term, checkOnly) {
|
|
2356
|
+
const backend = paneBackend();
|
|
2357
|
+
if (backend === "none") return noPaneMessage();
|
|
2358
|
+
if (backend === "tmux") {
|
|
2359
|
+
if (checkOnly) return "no follow pane";
|
|
2360
|
+
tmuxSplit(`${process.execPath} ${absoluteCliPath()} worker follow`);
|
|
2361
|
+
return "follow pane opened";
|
|
2362
|
+
}
|
|
2284
2363
|
const uid = itermUuid(term);
|
|
2285
2364
|
const out = (await osascript(TAB_TTYS_SCRIPT, [uid])).stdout.trim();
|
|
2286
2365
|
if (out === "notfound") throw new Error("pai worker pane: no open iTerm2 session matches ITERM_SESSION_ID");
|
|
@@ -2399,7 +2478,9 @@ function operatorSocketPath(logDir, id) {
|
|
|
2399
2478
|
}
|
|
2400
2479
|
/**
|
|
2401
2480
|
* The runner's side: listen on the worker socket, hand every received line to
|
|
2402
|
-
* `onLine`.
|
|
2481
|
+
* `onLine`. It acknowledges with "ok" only when `onLine` returns without a
|
|
2482
|
+
* string; a returned string (or a throw) is the failure reason, sent back as
|
|
2483
|
+
* `err <reason>` so `say` never reports ok for a message nobody received. Returns the server (close it when the run ends; the socket file is
|
|
2403
2484
|
* unlinked on close, best effort).
|
|
2404
2485
|
*/
|
|
2405
2486
|
function createOperatorServer(logDir, id, onLine) {
|
|
@@ -2409,14 +2490,20 @@ function createOperatorServer(logDir, id, onLine) {
|
|
|
2409
2490
|
} catch {}
|
|
2410
2491
|
const server = createServer((socket) => {
|
|
2411
2492
|
let buf = "";
|
|
2412
|
-
socket.on("
|
|
2493
|
+
socket.on("error", () => {});
|
|
2494
|
+
socket.on("data", async (chunk) => {
|
|
2413
2495
|
buf += chunk.toString("utf8");
|
|
2414
2496
|
let nl;
|
|
2415
2497
|
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
2416
2498
|
const line = buf.slice(0, nl).replace(/\r$/, "");
|
|
2417
2499
|
buf = buf.slice(nl + 1);
|
|
2418
|
-
|
|
2419
|
-
|
|
2500
|
+
let failure;
|
|
2501
|
+
if (line.trim()) try {
|
|
2502
|
+
failure = await onLine(line);
|
|
2503
|
+
} catch (e) {
|
|
2504
|
+
failure = e.message;
|
|
2505
|
+
}
|
|
2506
|
+
if (!socket.destroyed) socket.write(typeof failure === "string" && failure ? `err ${failure.replace(/\n/g, " ")}\n` : "ok\n");
|
|
2420
2507
|
}
|
|
2421
2508
|
});
|
|
2422
2509
|
});
|
|
@@ -2430,7 +2517,7 @@ function createOperatorServer(logDir, id, onLine) {
|
|
|
2430
2517
|
}
|
|
2431
2518
|
/**
|
|
2432
2519
|
* `pai worker say <id> "<text>"`: forward one line to a running worker.
|
|
2433
|
-
* Resolves "ok"
|
|
2520
|
+
* Resolves "ok" only once the worker acknowledged delivery; rejects with the reason otherwise.
|
|
2434
2521
|
*/
|
|
2435
2522
|
function sayToWorker(logDir, id, text, timeoutMs = 4e3) {
|
|
2436
2523
|
const status = loadStatus(logDir, id);
|
|
@@ -2449,10 +2536,13 @@ function sayToWorker(logDir, id, text, timeoutMs = 4e3) {
|
|
|
2449
2536
|
sock.once("connect", () => {
|
|
2450
2537
|
sock.write(text.replace(/\n/g, " ") + "\n");
|
|
2451
2538
|
});
|
|
2452
|
-
sock.once("data", () => {
|
|
2539
|
+
sock.once("data", (d) => {
|
|
2453
2540
|
sock.end();
|
|
2454
|
-
|
|
2541
|
+
const reply = d.toString("utf8").trim();
|
|
2542
|
+
if (reply === "ok") resolve("ok");
|
|
2543
|
+
else reject(/* @__PURE__ */ new Error(`worker ${id} did not take the message: ${reply.replace(/^err /, "") || "no acknowledgement"}`));
|
|
2455
2544
|
});
|
|
2545
|
+
sock.once("close", () => fail(/* @__PURE__ */ new Error("connection closed before the worker acknowledged")));
|
|
2456
2546
|
});
|
|
2457
2547
|
}
|
|
2458
2548
|
|
|
@@ -2857,10 +2947,10 @@ function fullContractPrompt(format) {
|
|
|
2857
2947
|
"report.",
|
|
2858
2948
|
"No narration, no timestamps, no greetings, no summaries of what you read; act, verify, then stop.",
|
|
2859
2949
|
"Never sleep-poll: no `sleep N` over 60 seconds, anywhere in a command — standalone, after `&&`/`||`/",
|
|
2860
|
-
"`;`/`|`, or inside a loop or subshell
|
|
2861
|
-
"
|
|
2862
|
-
"
|
|
2863
|
-
"
|
|
2950
|
+
"`;`/`|`, or inside a loop or subshell — and the sleeps of one command add up (`sleep 58; sleep 58` is",
|
|
2951
|
+
"116 s). Ending your turn ends this process, so a background job gets no later wake-up here:",
|
|
2952
|
+
"run_in_background is denied. Run the long command in the FOREGROUND with a Bash timeout up to 600000 ms",
|
|
2953
|
+
"and split longer jobs into steps that each fit it.",
|
|
2864
2954
|
...fileNotInlineBlock(),
|
|
2865
2955
|
"",
|
|
2866
2956
|
`Operator messages: a user turn starting with ${OPERATOR_MARK} was typed by the operator while you`,
|
|
@@ -2903,7 +2993,7 @@ function promptTrailer(format) {
|
|
|
2903
2993
|
return format === "ag2" ? "\n\nFinal message: one AG2 R message only, no prose (format in system prompt)." : "\n\nFinal message: a JSON object only, no prose before or after, no code fence (format in system prompt).";
|
|
2904
2994
|
}
|
|
2905
2995
|
/** The exact text sent to resend a final message that failed AG2 validation. */
|
|
2906
|
-
const AG2_REASK_TEXT = "Your final message was not a valid AG2 R message. Resend it now as a single AG2 R message only
|
|
2996
|
+
const AG2_REASK_TEXT = "Your final message was not a valid AG2 R message. Resend it now as a single AG2 R message only, no prose, no code fence. Minimal example (one key=value per line, first line R):\nR\ni=task-id\nr=+\nG=+\nc=path summary\nt=Name+\np=proof command\nz=the answer, one line\n(r is + - ~ ? !; r=+ needs G=+ and p; when r is not +, add y=why.)";
|
|
2907
2997
|
/** The full-contract AG2 prompt — the keepalive path's identical-construction baseline. */
|
|
2908
2998
|
const WORKER_CONTRACT_PROMPT = fullContractPrompt("ag2");
|
|
2909
2999
|
/**
|
|
@@ -3433,7 +3523,7 @@ async function runWorker(opts) {
|
|
|
3433
3523
|
if (gc?.length) process.stderr.write(`pai worker: archived ${gc.length} leftover worktree(s) (pai worker gc)\n`);
|
|
3434
3524
|
} catch {}
|
|
3435
3525
|
if (opts.className === "plan" && !opts._planner) {
|
|
3436
|
-
const { runPlanner } = await import("./planner-
|
|
3526
|
+
const { runPlanner } = await import("./planner-DAq4Yx-H.mjs");
|
|
3437
3527
|
return runPlanner(opts);
|
|
3438
3528
|
}
|
|
3439
3529
|
const parent = launchParent(opts.parent);
|
|
@@ -3809,7 +3899,7 @@ async function executeImageRun(a) {
|
|
|
3809
3899
|
* ledger line). Fire-and-forget, never blocks the worker.
|
|
3810
3900
|
*/
|
|
3811
3901
|
async function announcePane(logDir, config, wid, term, noPane, ledger) {
|
|
3812
|
-
const skip = !noPane ? !config.pane.enabled ? "workers.pane.enabled is false" : process.env.PAI_WORKER_AUTOPANE === "0" ? "PAI_WORKER_AUTOPANE=0" :
|
|
3902
|
+
const skip = !noPane ? !config.pane.enabled ? "workers.pane.enabled is false" : process.env.PAI_WORKER_AUTOPANE === "0" ? "PAI_WORKER_AUTOPANE=0" : paneBackend() === "none" ? "no tmux ($TMUX) or iTerm2 (ITERM_SESSION_ID) here" : null : "--no-pane";
|
|
3813
3903
|
if (skip) {
|
|
3814
3904
|
process.stderr.write(`[pai worker] no pane for ${wid}: ${skip}\n`);
|
|
3815
3905
|
return;
|
|
@@ -3902,12 +3992,12 @@ async function executeRun(a) {
|
|
|
3902
3992
|
let cmd = [...claudeCmd];
|
|
3903
3993
|
cmd.push(...modelFlagArgs(headless, model, Boolean(parsed.callerModel)));
|
|
3904
3994
|
cmd.push(...chromeArgs, ...mcpArgs, ...toolArgs, ...toolsFlag, ...restArgs);
|
|
3905
|
-
if (headless)
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3995
|
+
if (headless) cmd.push("--output-format", "stream-json", "--verbose", "--input-format", "stream-json");
|
|
3996
|
+
cmd.push(...appendSystemPromptArgs([
|
|
3997
|
+
...headless && !parsed.callerSystemPrompt ? [workerContractPrompt(a.className, a.reportFormat)] : [],
|
|
3998
|
+
...headless ? [worktree ? worktreeSystemPrompt(wid, worktree.branch, worktree.dir, worktree.snapshot) : inPlaceSystemPrompt()] : [],
|
|
3999
|
+
...parsed.callerSystemPrompts
|
|
4000
|
+
]));
|
|
3911
4001
|
cmd = ensureToolSearch(cmd);
|
|
3912
4002
|
if (a.printCmd) {
|
|
3913
4003
|
console.log(JSON.stringify({
|
|
@@ -3994,7 +4084,9 @@ async function executeRun(a) {
|
|
|
3994
4084
|
}) + "\n");
|
|
3995
4085
|
} catch {}
|
|
3996
4086
|
};
|
|
3997
|
-
const operatorServer = headless ? createOperatorServer(logDir, wid, (text) => {
|
|
4087
|
+
const operatorServer = headless ? createOperatorServer(logDir, wid, async (text) => {
|
|
4088
|
+
const stdin = proc.stdin;
|
|
4089
|
+
if (!stdin || !stdin.writable || stdin.writableEnded) return "the worker's stdin is already closed (its turn ended) — use: pai worker resume";
|
|
3998
4090
|
operatorInFlight += 1;
|
|
3999
4091
|
if (closeTimer) {
|
|
4000
4092
|
clearTimeout(closeTimer);
|
|
@@ -4005,9 +4097,13 @@ async function executeRun(a) {
|
|
|
4005
4097
|
text,
|
|
4006
4098
|
handoff: isHandoffMessage(text)
|
|
4007
4099
|
});
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4100
|
+
return new Promise((resolve) => {
|
|
4101
|
+
try {
|
|
4102
|
+
stdin.write(stdinUserMessage(operatorUserText(text)) + "\n", (e) => resolve(e ? `write to the worker failed: ${e.message}` : void 0));
|
|
4103
|
+
} catch (e) {
|
|
4104
|
+
resolve(`write to the worker failed: ${e.message}`);
|
|
4105
|
+
}
|
|
4106
|
+
});
|
|
4011
4107
|
}) : null;
|
|
4012
4108
|
let killed = false;
|
|
4013
4109
|
const cleanup = () => {
|
|
@@ -4595,4 +4691,4 @@ function resultFromOutput(out) {
|
|
|
4595
4691
|
|
|
4596
4692
|
//#endregion
|
|
4597
4693
|
export { expandMcpNames as $, ledgerSummary as A, loadStatuses as B, discardWorker as C, uncommittedPaths as D, mergeWorker as E, contextPercent as F, setWorkerLabel as G, nowStamp as H, elapsedOf as I, parseRunnerArgs as J, waitForTerminalStatus as K, isChatPane as L, ageOf as M, alive as N, worktreesDir as O, contextLabel as P, describeMcp as Q, isLive as R, workerInScope as S, git as T, ownsPid as U, newWorkerId as V, saveStatus as W, pinNotices as X, shortText as Y, projectLaunchConfig as Z, itermForClaudeSession as _, parseWorkerReport as a, sessionMapPath as b, readInbox as c, checkPaneForWorker as d, openFollowPane as f, currentTabKey as g, markControlsHeld as h, usageContextTokens as i, UNLABELED as j, appendLedger as k, sayToWorker as l, clickrControlsArgv as m, runWorker as n, renderReport as o, openPaneForWorker as p, longInlinePromptHint as q, testProvider as r, handoffFromInside as s, printResult as t, workerDepth as u, itermUuid as v, gcWorktrees as w, sessionTag as x, resolveSession as y, loadStatus as z };
|
|
4598
|
-
//# sourceMappingURL=run-
|
|
4694
|
+
//# sourceMappingURL=run-uAkNItb6.mjs.map
|