@tekmidian/pai 1.0.0 → 1.0.2
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/.claude-plugin/plugin.json +1 -1
- package/README.md +67 -5
- package/dist/aibroker-client-BxzeEHPF.mjs +3 -0
- package/dist/{aibroker-client-CXEYBzbf.mjs → aibroker-client-CQPGqLxL.mjs} +1 -1
- package/dist/atomic-file-BorMa4T3.mjs +21 -0
- package/dist/{auto-route-D5SXrMpB.mjs → auto-route-B4azPk4l.mjs} +3 -3
- package/dist/auto-route-BjoMHKyI.mjs +11 -0
- package/dist/budget-Dod6rnA9.mjs +15 -0
- package/dist/{caller-identity-CVTuiLSs.mjs → caller-identity-yLFb7CKq.mjs} +6 -5
- package/dist/{capacity-DaXrVj3J.mjs → capacity-DEveQdFV.mjs} +3 -3
- package/dist/{chain-BcQlIlEd.mjs → chain-D-yvET_y.mjs} +5 -5
- package/dist/cli/index.mjs +1621 -357
- package/dist/cockpit-actions-BWunx3rY.mjs +20 -0
- package/dist/{cockpit-actions-ODmt8yF9.mjs → cockpit-actions-C8GlTzts.mjs} +84 -42
- package/dist/cockpit-memory-vTlFWV7F.mjs +20 -0
- package/dist/{config-BSXKyeJ1.mjs → config-Bu1_vbY8.mjs} +42 -3
- package/dist/{config-B955yYmo.mjs → config-Cxi-aBf4.mjs} +2 -2
- package/dist/{config-TaWmdTLx.mjs → config-DtENJ6cL.mjs} +1 -1
- package/dist/{config-D5chi2LO.mjs → config-XpZWOYOG.mjs} +2 -2
- package/dist/{controls-BGkK_Bdi.mjs → controls-BcKFHeG1.mjs} +37 -22
- package/dist/daemon/index.mjs +43 -42
- package/dist/{daemon-CorGh6Ub.mjs → daemon-ColVHwGZ.mjs} +103 -55
- package/dist/daemon-N7WhYi6I.mjs +45 -0
- package/dist/daemon-mcp/index.mjs +40 -39
- package/dist/{define-DGFu-sCf.mjs → define-CjJsmq-6.mjs} +1 -1
- package/dist/{detect-C1d5cUkT.mjs → detect-9CZNO0yf.mjs} +2 -2
- package/dist/detect-D1ziFFfA.mjs +10 -0
- package/dist/{embed-pass-CeQD8kRE.mjs → embed-pass-DIWjA68P.mjs} +5 -5
- package/dist/{embedding-gate-BHuBsgHD.mjs → embedding-gate-6rZrWRXa.mjs} +5 -5
- package/dist/{embedding-gate-Z7CJSOJk.mjs → embedding-gate-Cnk4YCyX.mjs} +3 -3
- package/dist/{embeddings-D4t6L-EH.mjs → embeddings-BVq3esBF.mjs} +1 -1
- package/dist/{embeddings-OF9Pt4by.mjs → embeddings-CIkJBKd-.mjs} +1 -1
- package/dist/{endreason-x1KOSrcO.mjs → endreason-C577xIQz.mjs} +7 -6
- package/dist/{env-DArqGq-Z.mjs → env-BE8mrsxr.mjs} +1 -1
- package/dist/factory-Bsib-qDG.mjs +9 -0
- package/dist/{factory-BtjbQ0np.mjs → factory-DjAAsqr_.mjs} +15 -13
- package/dist/{fallback-BIyEpPsQ.mjs → fallback-DFlItw1Z.mjs} +5 -5
- package/dist/{fmt-age-BiSHrTKN.mjs → fmt-age-ByDkvkoU.mjs} +1 -1
- package/dist/{health-C6jZWvRG.mjs → health-Dnym-qcT.mjs} +4 -4
- package/dist/{helpers-DFmYRCOa.mjs → helpers-BD6V-p9w.mjs} +2 -2
- package/dist/helpers-CMGjy_0N.mjs +10 -0
- package/dist/{helpers-CJpb_MNB.mjs → helpers-CRuBUas3.mjs} +87 -38
- package/dist/hooks/capture-all-events.mjs +52 -11
- package/dist/hooks/capture-session-summary.mjs +64 -47
- package/dist/hooks/capture-tool-output.mjs +49 -8
- package/dist/hooks/context-compression-hook.mjs +30 -10
- package/dist/hooks/initialize-session.mjs +1 -0
- package/dist/hooks/load-core-context.mjs +1 -1
- package/dist/hooks/load-project-context.mjs +32 -29
- package/dist/hooks/security-validator.mjs +45 -13
- package/dist/hooks/stop-hook.mjs +54 -16
- package/dist/hooks/supervision-banner.mjs +9 -0
- package/dist/hooks/sync-todo-to-md.mjs +147 -113
- package/dist/hooks/worker-edit-repair.mjs +2 -1
- package/dist/hooks/worker-guard.mjs +40 -16
- package/dist/hooks/worker-note.mjs +12 -5
- package/dist/hooks/worker-path-repair.mjs +1 -1
- package/dist/hooks/worker-pool-host.mjs +214 -116
- package/dist/hooks/worker-status-line.mjs +195 -114
- package/dist/index.d.mts +18 -0
- package/dist/index.mjs +12 -12
- package/dist/{indexer-backend-BM2CUSu8.mjs → indexer-backend-_a6UNhXJ.mjs} +149 -96
- package/dist/{ipc-client-BMqWw_gv.mjs → ipc-client-CaiGJnSM.mjs} +1 -1
- package/dist/{ipc-client-YYDD6zzU.mjs → ipc-client-ZRmDKd5Z.mjs} +1 -1
- package/dist/kill-tree-BG7dRVtp.mjs +10 -0
- package/dist/{kill-tree-BjYz5BxK.mjs → kill-tree-EWYaEk5v.mjs} +8 -8
- package/dist/{launch-CLp0OJxV.mjs → launch-CXVlZjHt.mjs} +8 -8
- package/dist/{launch-DgqQdAjI.mjs → launch-Jh5NVeNe.mjs} +3 -3
- package/dist/local-candidate-DLdwQt0s.mjs +112 -0
- package/dist/local-instances-DOxSgT_L.mjs +210 -0
- package/dist/local-instances-ZeRkkuS5.mjs +6 -0
- package/dist/{local-tiers-DPZYqv9m.mjs → local-tiers-BE4jGaMa.mjs} +2 -2
- package/dist/{local-tiers-DnBIAkbK.mjs → local-tiers-DNMI5W86.mjs} +3 -3
- package/dist/{main-config-ops-C0SflOWk.mjs → main-config-ops-BEMpuhDz.mjs} +3 -3
- package/dist/{main-resolver-DVPpSWVy.mjs → main-resolver-3Ns1HPmS.mjs} +18 -17
- package/dist/{migrate-BUJHadA8.mjs → migrate-DrA_OwlZ.mjs} +45 -14
- package/dist/min-max-DrSRUaWQ.mjs +16 -0
- package/dist/{model-inventory-Dasber3S.mjs → model-inventory-BFVSNFT3.mjs} +13 -12
- package/dist/{models-add-Bt7aUHDs.mjs → models-add-BtB3Se6f.mjs} +39 -38
- package/dist/operator-BTqvTIc8.mjs +7 -0
- package/dist/{operator-DZxcP-g8.mjs → operator-CyuB3aVw.mjs} +3 -3
- package/dist/{pai-marker-kIYuNt3c.mjs → pai-marker-DurzIbw8.mjs} +7 -6
- package/dist/{pane-audit-OGYrOAik.mjs → pane-audit-BQytYa60.mjs} +7 -7
- package/dist/{paths-DoRuFc60.mjs → paths-CFHTloSe.mjs} +3 -3
- package/dist/{paths-DoIyRnhx.mjs → paths-CHifubDh.mjs} +3 -3
- package/dist/{planner-DLGOYlVb.mjs → planner-BM27GBfC.mjs} +31 -30
- package/dist/{pool-CZ5MZaXg.mjs → pool-BRvoOkv6.mjs} +3 -3
- package/dist/{pool-cli-BxNSPzzY.mjs → pool-cli-B_YR8_Gl.mjs} +5 -5
- package/dist/{pool-cli-CbJfl37y.mjs → pool-cli-DkZTAlSW.mjs} +6 -6
- package/dist/postgres-BdBNkL_l.mjs +7 -0
- package/dist/{postgres-CDnd_k5f.mjs → postgres-C6ti4haA.mjs} +55 -34
- package/dist/{project-setup-DM4npnL3.mjs → project-setup-CfpApz5o.mjs} +131 -74
- package/dist/providers-BeDiVEb-.mjs +16 -0
- package/dist/{providers-UsKtLcUR.mjs → providers-CblTFrhz.mjs} +6 -6
- package/dist/{query-feedback-I-txSnld.mjs → query-feedback-BRfPtqki.mjs} +2 -2
- package/dist/registrable-C7b6givx.mjs +9 -0
- package/dist/{registrable-LrRIVYQc.mjs → registrable-Uzgmfyhz.mjs} +4 -4
- package/dist/render-Cc2j5QG9.mjs +13 -0
- package/dist/{render-BDbb4CF-.mjs → render-CwIrgxLi.mjs} +8 -8
- package/dist/{reranker-B4r4vykM.mjs → reranker-8g6xMwP7.mjs} +1 -1
- package/dist/{reranker-DxxMCtA0.mjs → reranker-CqCbpGnX.mjs} +1 -1
- package/dist/{root-BMeJuHOb.mjs → root-BWy0c2Lq.mjs} +11 -11
- package/dist/root-wC_6Fx0B.mjs +36 -0
- package/dist/route-table-B7zpoypi.mjs +15 -0
- package/dist/{router-L8Nu-OHF.mjs → router-CQSc3lk3.mjs} +17 -7
- package/dist/{router-D6Ec6Fid.mjs → router-DwHJRgG9.mjs} +1 -1
- package/dist/{routing-CUyiglfu.mjs → routing-BAAST9vT.mjs} +27 -308
- package/dist/{routing-ZuGlc0ge.mjs → routing-CENt4HH1.mjs} +13 -12
- package/dist/{run-ulAi5dFD.mjs → run-6Q9kCPem.mjs} +35 -33
- package/dist/{scan-B7I0gPe-.mjs → scan-ZQWm-_se.mjs} +6 -6
- package/dist/{local-candidate-jOjTNlOL.mjs → scheduler-CtUyWJ3O.mjs} +7 -109
- package/dist/scheduler-dmHXoRvm.mjs +3 -0
- package/dist/{scope-D5VSQxe4.mjs → scope-D-h6F6DN.mjs} +4 -4
- package/dist/{search-CPoE0830.mjs → search-RSyeQqj1.mjs} +18 -18
- package/dist/session-Bok2PqRS.mjs +35 -0
- package/dist/{session-CNXF6DLP.mjs → session-DVUExUnX.mjs} +55 -31
- package/dist/session-scan-BJI_ZO8M.mjs +9 -0
- package/dist/{session-scan-BDLEc4w1.mjs → session-scan-W-gbwJHM.mjs} +6 -6
- package/dist/{sources-CjhUKKtO.mjs → sources-ESUkZaWv.mjs} +1 -1
- package/dist/{status-DYydKQUI.mjs → status-Dm4dYciN.mjs} +4 -4
- package/dist/{status-CvVi9cDf.mjs → status-ggJ7lgVg.mjs} +17 -9
- package/dist/{stop-words-SdSL1WKH.mjs → stop-words-DSEYQdNe.mjs} +1 -1
- package/dist/{test-isolation-CoDeOVXb.mjs → test-isolation-lqSmYxr0.mjs} +1 -1
- package/dist/{timeouts-OwEONmc8.mjs → timeouts-1MLooEBB.mjs} +1 -1
- package/dist/{tool-errors-AeRQuG3Y.mjs → tool-errors-7E13StWd.mjs} +4 -3
- package/dist/{tool-errors-R5E0fCgf.mjs → tool-errors-CJWODvlo.mjs} +6 -6
- package/dist/{viewer-DtWj5Vti.mjs → viewer-DcpJwGKE.mjs} +15 -15
- package/dist/viewer-MWBVJP3u.mjs +22 -0
- package/dist/{wait-BMUR-U-U.mjs → wait-ByV0OyMZ.mjs} +3 -3
- package/dist/{worker-config-BLqa1yiD.mjs → worker-config-BDYNxbYz.mjs} +294 -92
- package/dist/worker-config-gmAq_-rI.mjs +41 -0
- package/dist/{workers-config-DEI9lrV4.mjs → workers-config-f8KrkY4L.mjs} +2 -2
- package/dist/{worktree-zmRf556h.mjs → worktree-CrnOqTBW.mjs} +37 -7
- package/dist/{zettelkasten-nigq7fqs.mjs → zettelkasten-B_rRRRvD.mjs} +5 -5
- package/dist/{zettelkasten-Cr_Xj0mG.mjs → zettelkasten-BzMm8REH.mjs} +29 -19
- package/docs/README.md +2 -0
- package/docs/cockpit.md +10 -4
- package/docs/commands/README.md +4 -4
- package/docs/commands/backup.md +2 -0
- package/docs/commands/install.md +29 -4
- package/docs/commands/providers.md +1 -1
- package/docs/commands/restore.md +4 -0
- package/docs/commands/setup.md +29 -4
- package/docs/commands/worker.md +1 -1
- package/docs/config.md +2 -0
- package/docs/features.md +299 -0
- package/docs/images/architecture.drawio +51 -0
- package/docs/images/architecture.svg +3 -0
- package/docs/images/cockpit-01-system-tokens.jpg +0 -0
- package/docs/images/cockpit-02-totals-cache.jpg +0 -0
- package/docs/images/cockpit-03-local-servers-models-pool.jpg +0 -0
- package/docs/images/cockpit-04-workers-memory.jpg +0 -0
- package/docs/images/cockpit-05-performance.jpg +0 -0
- package/docs/images/cockpit-06-runs-speed-routing.jpg +0 -0
- package/docs/images/cockpit-07-settings-registry.jpg +0 -0
- package/docs/install/index.md +29 -0
- package/docs/three-tier-coding.md +1 -1
- package/gemini-extension.json +1 -1
- package/package.json +1 -5
- package/pai-plugin.json +1 -1
- package/plugins/context-preservation/plugin.json +1 -1
- package/plugins/core/plugin.json +1 -1
- package/plugins/core/skills/setup/SKILL.md +41 -9
- package/plugins/creative/plugin.json +1 -1
- package/plugins/observability/plugin.json +1 -1
- package/plugins/productivity/plugin.json +1 -1
- package/plugins/semantic-search/plugin.json +1 -1
- package/plugins/ui/plugin.json +1 -1
- package/plugins/zettelkasten/plugin.json +1 -1
- package/src/hooks/session-autosave.sh +8 -1
- package/src/hooks/session-stop.sh +8 -1
- package/src/hooks/ts/capture-all-events.ts +7 -12
- package/src/hooks/ts/lib/context-fill.ts +2 -1
- package/src/hooks/ts/lib/path-repair.ts +1 -1
- package/src/hooks/ts/lib/project-utils/notify.ts +1 -0
- package/src/hooks/ts/lib/project-utils/session-notes.ts +23 -6
- package/src/hooks/ts/lib/raw-capture.ts +36 -0
- package/src/hooks/ts/lib/session-summary.ts +129 -0
- package/src/hooks/ts/lib/todo-sync.ts +120 -0
- package/src/hooks/ts/lib/worker-git-guard.ts +1 -1
- package/src/hooks/ts/post-tool-use/capture-tool-output.ts +6 -10
- package/src/hooks/ts/post-tool-use/sync-todo-to-md.ts +5 -105
- package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
- package/src/hooks/ts/pre-tool-use/security-validator.ts +35 -14
- package/src/hooks/ts/session-end/capture-session-summary.ts +20 -128
- package/src/hooks/ts/session-start/load-core-context.ts +3 -3
- package/src/hooks/ts/session-start/load-project-context.ts +18 -22
- package/src/hooks/ts/stop/stop-hook.ts +13 -5
- package/src/hooks/ztk-auto.sh +7 -2
- package/dist/aibroker-client-JjE74jo0.mjs +0 -3
- package/dist/auto-route-BRk8NEFv.mjs +0 -11
- package/dist/budget-DuhQ2zzG.mjs +0 -14
- package/dist/cockpit-actions-DcQ-ucU8.mjs +0 -19
- package/dist/cockpit-memory-KV45PPO2.mjs +0 -19
- package/dist/daemon-C7yt_ptC.mjs +0 -44
- package/dist/detect-DRUkmHnb.mjs +0 -10
- package/dist/factory-DAGG9_n8.mjs +0 -9
- package/dist/helpers-DPJEHPq6.mjs +0 -10
- package/dist/kill-tree-LV0Q7Mte.mjs +0 -10
- package/dist/operator-CfL0HiBK.mjs +0 -7
- package/dist/postgres-DgqWyqhN.mjs +0 -7
- package/dist/providers-CTu2s1z2.mjs +0 -15
- package/dist/registrable-D9aNZOTh.mjs +0 -9
- package/dist/render-BSfVlYHj.mjs +0 -13
- package/dist/root-xI9DqVIe.mjs +0 -35
- package/dist/route-table-HjvnLVEU.mjs +0 -14
- package/dist/session-BJHzmUg2.mjs +0 -34
- package/dist/session-scan-YORKE1NO.mjs +0 -9
- package/dist/viewer-B8709jDN.mjs +0 -22
- package/dist/worker-config-D8tRuvo7.mjs +0 -40
- package/docs/images/cockpit-limits-routing.jpg +0 -0
- package/docs/images/cockpit-models.jpg +0 -0
- package/docs/images/cockpit-usage.jpg +0 -0
- package/docs/images/cockpit-workers-system.jpg +0 -0
- package/scripts/build-docs.mjs +0 -41
- package/scripts/build-hooks.mjs +0 -311
- package/scripts/build-skill-stubs.mjs +0 -216
- package/scripts/copy-defaults.mjs +0 -46
|
@@ -7998,6 +7998,13 @@ var init_scratch = __esm({
|
|
|
7998
7998
|
}
|
|
7999
7999
|
});
|
|
8000
8000
|
|
|
8001
|
+
// src/config/atomic-file.ts
|
|
8002
|
+
var init_atomic_file = __esm({
|
|
8003
|
+
"src/config/atomic-file.ts"() {
|
|
8004
|
+
"use strict";
|
|
8005
|
+
}
|
|
8006
|
+
});
|
|
8007
|
+
|
|
8001
8008
|
// src/utils/fmt-age.ts
|
|
8002
8009
|
var init_fmt_age = __esm({
|
|
8003
8010
|
"src/utils/fmt-age.ts"() {
|
|
@@ -8009,6 +8016,7 @@ var init_fmt_age = __esm({
|
|
|
8009
8016
|
var init_pending = __esm({
|
|
8010
8017
|
"src/workers/pending.ts"() {
|
|
8011
8018
|
"use strict";
|
|
8019
|
+
init_atomic_file();
|
|
8012
8020
|
init_status();
|
|
8013
8021
|
init_paths();
|
|
8014
8022
|
init_worktree();
|
|
@@ -8080,6 +8088,7 @@ var init_tree = __esm({
|
|
|
8080
8088
|
var init_endreason = __esm({
|
|
8081
8089
|
"src/workers/endreason.ts"() {
|
|
8082
8090
|
"use strict";
|
|
8091
|
+
init_atomic_file();
|
|
8083
8092
|
init_paths();
|
|
8084
8093
|
init_ledger();
|
|
8085
8094
|
init_status();
|
|
@@ -7370,42 +7370,149 @@ function isWorkerSession(env = process.env) {
|
|
|
7370
7370
|
}
|
|
7371
7371
|
|
|
7372
7372
|
// src/hooks/ts/post-tool-use/sync-todo-to-md.ts
|
|
7373
|
-
import {
|
|
7373
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, mkdirSync as mkdirSync4 } from "fs";
|
|
7374
|
+
import { dirname as dirname4 } from "path";
|
|
7375
|
+
|
|
7376
|
+
// src/hooks/ts/lib/todo-sync.ts
|
|
7377
|
+
import { writeFileSync, renameSync, unlinkSync } from "fs";
|
|
7378
|
+
import { dirname, join, basename } from "path";
|
|
7379
|
+
var MANAGED_HEADING = /^## Current Session[ \t]*$/;
|
|
7380
|
+
var FOOTER = /(\n---[ \t\r\n]*)?(\n\*Last updated:[^\n]*\*[ \t\r\n]*)?$/;
|
|
7381
|
+
function formatSessionTodos(todos) {
|
|
7382
|
+
const inProgress = todos.filter((t) => t.status === "in_progress");
|
|
7383
|
+
const pending = todos.filter((t) => t.status === "pending");
|
|
7384
|
+
const completed = todos.filter((t) => t.status === "completed");
|
|
7385
|
+
let content = "";
|
|
7386
|
+
if (inProgress.length > 0) {
|
|
7387
|
+
content += `### In Progress
|
|
7388
|
+
|
|
7389
|
+
`;
|
|
7390
|
+
for (const todo of inProgress) {
|
|
7391
|
+
content += `- [ ] **${todo.content}** _(${todo.activeForm})_
|
|
7392
|
+
`;
|
|
7393
|
+
}
|
|
7394
|
+
content += "\n";
|
|
7395
|
+
}
|
|
7396
|
+
if (pending.length > 0) {
|
|
7397
|
+
content += `### Pending
|
|
7398
|
+
|
|
7399
|
+
`;
|
|
7400
|
+
for (const todo of pending) {
|
|
7401
|
+
content += `- [ ] ${todo.content}
|
|
7402
|
+
`;
|
|
7403
|
+
}
|
|
7404
|
+
content += "\n";
|
|
7405
|
+
}
|
|
7406
|
+
if (completed.length > 0) {
|
|
7407
|
+
content += `### Completed
|
|
7408
|
+
|
|
7409
|
+
`;
|
|
7410
|
+
for (const todo of completed) {
|
|
7411
|
+
content += `- [x] ${todo.content}
|
|
7412
|
+
`;
|
|
7413
|
+
}
|
|
7414
|
+
content += "\n";
|
|
7415
|
+
}
|
|
7416
|
+
if (todos.length === 0) {
|
|
7417
|
+
content += `_(No active session tasks)_
|
|
7418
|
+
|
|
7419
|
+
`;
|
|
7420
|
+
}
|
|
7421
|
+
return content;
|
|
7422
|
+
}
|
|
7423
|
+
function splitSections(content) {
|
|
7424
|
+
const starts = [];
|
|
7425
|
+
let offset = 0;
|
|
7426
|
+
for (const line of content.split("\n")) {
|
|
7427
|
+
if (line.startsWith("## ")) starts.push(offset);
|
|
7428
|
+
offset += line.length + 1;
|
|
7429
|
+
}
|
|
7430
|
+
if (starts.length === 0) return { preamble: content, sections: [] };
|
|
7431
|
+
const sections = starts.map((s, i) => content.slice(s, starts[i + 1] ?? content.length));
|
|
7432
|
+
return { preamble: content.slice(0, starts[0]), sections };
|
|
7433
|
+
}
|
|
7434
|
+
function buildTodoContent(todos, existingContent, now = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
7435
|
+
const body = existingContent.replace(FOOTER, "");
|
|
7436
|
+
const managed = `## Current Session
|
|
7437
|
+
|
|
7438
|
+
${formatSessionTodos(todos)}`;
|
|
7439
|
+
const { preamble, sections } = splitSections(body);
|
|
7440
|
+
let out;
|
|
7441
|
+
const idx = sections.findIndex((s) => MANAGED_HEADING.test(s.split("\n", 1)[0]));
|
|
7442
|
+
if (idx >= 0) {
|
|
7443
|
+
const old = sections[idx];
|
|
7444
|
+
const trailing = old.slice(old.trimEnd().length);
|
|
7445
|
+
const replaced = sections.slice();
|
|
7446
|
+
replaced[idx] = managed.trimEnd() + (idx < sections.length - 1 ? trailing.length > 1 ? trailing : "\n\n" : "\n");
|
|
7447
|
+
out = preamble + replaced.join("");
|
|
7448
|
+
} else if (body.trim() === "") {
|
|
7449
|
+
out = `# TODO
|
|
7450
|
+
|
|
7451
|
+
${managed}`;
|
|
7452
|
+
} else {
|
|
7453
|
+
const titleEnd = /^# [^\n]*\n\n?/.exec(preamble);
|
|
7454
|
+
const head = titleEnd ? preamble.slice(0, titleEnd[0].length) : "";
|
|
7455
|
+
const rest = preamble.slice(head.length);
|
|
7456
|
+
out = head + managed + rest + sections.join("");
|
|
7457
|
+
}
|
|
7458
|
+
if (!out.endsWith("\n")) out += "\n";
|
|
7459
|
+
return `${out}
|
|
7460
|
+
---
|
|
7461
|
+
|
|
7462
|
+
*Last updated: ${now}*
|
|
7463
|
+
`;
|
|
7464
|
+
}
|
|
7465
|
+
function fixMalformedHeadings(content) {
|
|
7466
|
+
return content.replace(/^---#/gm, "#");
|
|
7467
|
+
}
|
|
7468
|
+
function writeFileAtomic(path, data) {
|
|
7469
|
+
const tmp = join(dirname(path), `.${basename(path)}.${process.pid}.tmp`);
|
|
7470
|
+
try {
|
|
7471
|
+
writeFileSync(tmp, data);
|
|
7472
|
+
renameSync(tmp, path);
|
|
7473
|
+
} catch (e) {
|
|
7474
|
+
try {
|
|
7475
|
+
unlinkSync(tmp);
|
|
7476
|
+
} catch {
|
|
7477
|
+
}
|
|
7478
|
+
throw e;
|
|
7479
|
+
}
|
|
7480
|
+
}
|
|
7374
7481
|
|
|
7375
7482
|
// src/hooks/ts/lib/project-utils/paths.ts
|
|
7376
7483
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2, linkSync, copyFileSync as copyFileSync2 } from "fs";
|
|
7377
|
-
import { join as
|
|
7484
|
+
import { join as join4, basename as basename2 } from "path";
|
|
7378
7485
|
|
|
7379
7486
|
// src/hooks/ts/lib/pai-paths.ts
|
|
7380
7487
|
import { homedir as homedir2 } from "os";
|
|
7381
|
-
import { resolve, join as
|
|
7488
|
+
import { resolve, join as join3 } from "path";
|
|
7382
7489
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
7383
7490
|
|
|
7384
7491
|
// src/config/pai-home.ts
|
|
7385
|
-
import { existsSync, mkdirSync, readFileSync, copyFileSync, renameSync, readdirSync, statSync } from "node:fs";
|
|
7492
|
+
import { existsSync, mkdirSync, readFileSync, copyFileSync, renameSync as renameSync2, readdirSync, statSync } from "node:fs";
|
|
7386
7493
|
import { homedir } from "node:os";
|
|
7387
|
-
import { join, dirname } from "node:path";
|
|
7494
|
+
import { join as join2, dirname as dirname2 } from "node:path";
|
|
7388
7495
|
function legacyPaiHomeDir() {
|
|
7389
|
-
return
|
|
7496
|
+
return join2(homedir(), ".claude", "pai");
|
|
7390
7497
|
}
|
|
7391
7498
|
function claudeHomeDir() {
|
|
7392
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
7499
|
+
return process.env.CLAUDE_CONFIG_DIR || join2(homedir(), ".claude");
|
|
7393
7500
|
}
|
|
7394
7501
|
function legacyConfigDir() {
|
|
7395
|
-
return
|
|
7502
|
+
return join2(homedir(), ".config", "pai");
|
|
7396
7503
|
}
|
|
7397
7504
|
function defaultPaiHomeDir() {
|
|
7398
|
-
return
|
|
7505
|
+
return join2(homedir(), ".pai");
|
|
7399
7506
|
}
|
|
7400
7507
|
function paiHomeDir() {
|
|
7401
7508
|
if (process.env.PAI_HOME) return process.env.PAI_HOME;
|
|
7402
7509
|
const fresh = defaultPaiHomeDir();
|
|
7403
7510
|
const legacy = legacyPaiHomeDir();
|
|
7404
|
-
if (!existsSync(
|
|
7511
|
+
if (!existsSync(join2(fresh, "config.yaml")) && existsSync(join2(legacy, "config.yaml"))) return legacy;
|
|
7405
7512
|
return fresh;
|
|
7406
7513
|
}
|
|
7407
7514
|
function paiHomePath(...segments) {
|
|
7408
|
-
return
|
|
7515
|
+
return join2(paiHomeDir(), ...segments);
|
|
7409
7516
|
}
|
|
7410
7517
|
var noticesPrinted = /* @__PURE__ */ new Set();
|
|
7411
7518
|
function resolvePaiFile(newPath, oldCandidates, migrateHint) {
|
|
@@ -7500,32 +7607,32 @@ function resolveAdapterDir() {
|
|
|
7500
7607
|
return defaultAdapterDir();
|
|
7501
7608
|
}
|
|
7502
7609
|
var ADAPTER_DIR = resolveAdapterDir();
|
|
7503
|
-
var HOOKS_DIR =
|
|
7504
|
-
var SKILLS_DIR =
|
|
7505
|
-
var AGENTS_DIR =
|
|
7506
|
-
var COMMANDS_DIR =
|
|
7610
|
+
var HOOKS_DIR = join3(ADAPTER_DIR, "Hooks");
|
|
7611
|
+
var SKILLS_DIR = join3(ADAPTER_DIR, "skills");
|
|
7612
|
+
var AGENTS_DIR = join3(ADAPTER_DIR, "agents");
|
|
7613
|
+
var COMMANDS_DIR = join3(ADAPTER_DIR, "commands");
|
|
7507
7614
|
|
|
7508
7615
|
// src/hooks/ts/lib/project-utils/paths.ts
|
|
7509
|
-
var PROJECTS_DIR =
|
|
7616
|
+
var PROJECTS_DIR = join4(ADAPTER_DIR, "projects");
|
|
7510
7617
|
function encodePath(path) {
|
|
7511
7618
|
return path.replace(/\//g, "-").replace(/\./g, "-").replace(/ /g, "-");
|
|
7512
7619
|
}
|
|
7513
7620
|
function getProjectDir(cwd) {
|
|
7514
7621
|
const encoded = encodePath(cwd);
|
|
7515
|
-
return
|
|
7622
|
+
return join4(PROJECTS_DIR, encoded);
|
|
7516
7623
|
}
|
|
7517
7624
|
function getNotesDir(cwd) {
|
|
7518
|
-
return
|
|
7625
|
+
return join4(getProjectDir(cwd), "Notes");
|
|
7519
7626
|
}
|
|
7520
7627
|
function findNotesDir(cwd) {
|
|
7521
|
-
const cwdBasename =
|
|
7628
|
+
const cwdBasename = basename2(cwd).toLowerCase();
|
|
7522
7629
|
if (cwdBasename === "notes" && existsSync3(cwd)) {
|
|
7523
7630
|
return { path: cwd, isLocal: true };
|
|
7524
7631
|
}
|
|
7525
7632
|
const localPaths = [
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7633
|
+
join4(cwd, "Notes"),
|
|
7634
|
+
join4(cwd, "notes"),
|
|
7635
|
+
join4(cwd, ".claude", "Notes")
|
|
7529
7636
|
];
|
|
7530
7637
|
for (const path of localPaths) {
|
|
7531
7638
|
if (existsSync3(path)) {
|
|
@@ -7536,20 +7643,20 @@ function findNotesDir(cwd) {
|
|
|
7536
7643
|
}
|
|
7537
7644
|
function findTodoPath(cwd) {
|
|
7538
7645
|
const localPaths = [
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7646
|
+
join4(cwd, "TODO.md"),
|
|
7647
|
+
join4(cwd, "notes", "TODO.md"),
|
|
7648
|
+
join4(cwd, "Notes", "TODO.md"),
|
|
7649
|
+
join4(cwd, ".claude", "TODO.md")
|
|
7543
7650
|
];
|
|
7544
7651
|
for (const path of localPaths) {
|
|
7545
7652
|
if (existsSync3(path)) return path;
|
|
7546
7653
|
}
|
|
7547
|
-
return
|
|
7654
|
+
return join4(getNotesDir(cwd), "TODO.md");
|
|
7548
7655
|
}
|
|
7549
7656
|
|
|
7550
7657
|
// src/hooks/ts/lib/project-utils/session-notes.ts
|
|
7551
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync3, writeFileSync, renameSync as
|
|
7552
|
-
import { join as
|
|
7658
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync as renameSync3 } from "fs";
|
|
7659
|
+
import { join as join5, basename as basename3 } from "path";
|
|
7553
7660
|
function getCurrentNotePath(notesDir) {
|
|
7554
7661
|
if (!existsSync4(notesDir)) return null;
|
|
7555
7662
|
const findLatestIn = (dir) => {
|
|
@@ -7560,18 +7667,18 @@ function getCurrentNotePath(notesDir) {
|
|
|
7560
7667
|
return numA - numB;
|
|
7561
7668
|
});
|
|
7562
7669
|
if (files.length === 0) return null;
|
|
7563
|
-
return
|
|
7670
|
+
return join5(dir, files[files.length - 1]);
|
|
7564
7671
|
};
|
|
7565
7672
|
const now = /* @__PURE__ */ new Date();
|
|
7566
7673
|
const year = String(now.getFullYear());
|
|
7567
7674
|
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
7568
|
-
const currentMonthDir =
|
|
7675
|
+
const currentMonthDir = join5(notesDir, year, month);
|
|
7569
7676
|
const found = findLatestIn(currentMonthDir);
|
|
7570
7677
|
if (found) return found;
|
|
7571
7678
|
const prevDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
7572
7679
|
const prevYear = String(prevDate.getFullYear());
|
|
7573
7680
|
const prevMonth = String(prevDate.getMonth() + 1).padStart(2, "0");
|
|
7574
|
-
const prevMonthDir =
|
|
7681
|
+
const prevMonthDir = join5(notesDir, prevYear, prevMonth);
|
|
7575
7682
|
const prevFound = findLatestIn(prevMonthDir);
|
|
7576
7683
|
if (prevFound) return prevFound;
|
|
7577
7684
|
return findLatestIn(notesDir);
|
|
@@ -7608,8 +7715,8 @@ function addWorkToSessionNote(notePath, workItems, sectionTitle) {
|
|
|
7608
7715
|
content = content.substring(0, nextStepsIndex) + workText + "\n" + content.substring(nextStepsIndex);
|
|
7609
7716
|
}
|
|
7610
7717
|
}
|
|
7611
|
-
|
|
7612
|
-
console.error(`Added ${workItems.length} work item(s) to: ${
|
|
7718
|
+
writeFileSync2(notePath, content);
|
|
7719
|
+
console.error(`Added ${workItems.length} work item(s) to: ${basename3(notePath)}`);
|
|
7613
7720
|
}
|
|
7614
7721
|
|
|
7615
7722
|
// src/session/forge-sink.ts
|
|
@@ -7619,7 +7726,7 @@ var import_yaml4 = __toESM(require_dist(), 1);
|
|
|
7619
7726
|
var PREAMBLE_MAX_BYTES = 16 * 1024;
|
|
7620
7727
|
|
|
7621
7728
|
// src/daemon/config.ts
|
|
7622
|
-
import { join as
|
|
7729
|
+
import { join as join6, dirname as dirname3, basename as basename4 } from "node:path";
|
|
7623
7730
|
|
|
7624
7731
|
// src/config/shipped-defaults.ts
|
|
7625
7732
|
var import_yaml3 = __toESM(require_dist(), 1);
|
|
@@ -7632,93 +7739,20 @@ var import_yaml = __toESM(require_dist(), 1);
|
|
|
7632
7739
|
|
|
7633
7740
|
// src/daemon/config.ts
|
|
7634
7741
|
var NEW_CONFIG_FILE = paiHomePath("config.json");
|
|
7635
|
-
var oldConfigFile = () =>
|
|
7636
|
-
var legacyConfigFile = () =>
|
|
7742
|
+
var oldConfigFile = () => join6(claudeHomeDir(), "pai.json");
|
|
7743
|
+
var legacyConfigFile = () => join6(legacyConfigDir(), "config.json");
|
|
7637
7744
|
function paiConfigFilePath() {
|
|
7638
7745
|
const override = process.env.PAI_CONFIG_FILE;
|
|
7639
7746
|
if (override) return override;
|
|
7640
7747
|
return resolvePaiFile(NEW_CONFIG_FILE, [oldConfigFile(), legacyConfigFile()], "pai config migrate");
|
|
7641
7748
|
}
|
|
7642
7749
|
var CONFIG_FILE = paiConfigFilePath();
|
|
7643
|
-
var CONFIG_DIR =
|
|
7750
|
+
var CONFIG_DIR = dirname3(CONFIG_FILE);
|
|
7644
7751
|
|
|
7645
7752
|
// src/session/checkpoint-block.ts
|
|
7646
7753
|
var AUTHORED_GRACE_MS = 60 * 60 * 1e3;
|
|
7647
7754
|
|
|
7648
7755
|
// src/hooks/ts/post-tool-use/sync-todo-to-md.ts
|
|
7649
|
-
function formatSessionTodos(todos) {
|
|
7650
|
-
const inProgress = todos.filter((t) => t.status === "in_progress");
|
|
7651
|
-
const pending = todos.filter((t) => t.status === "pending");
|
|
7652
|
-
const completed = todos.filter((t) => t.status === "completed");
|
|
7653
|
-
let content = "";
|
|
7654
|
-
if (inProgress.length > 0) {
|
|
7655
|
-
content += `### In Progress
|
|
7656
|
-
|
|
7657
|
-
`;
|
|
7658
|
-
for (const todo of inProgress) {
|
|
7659
|
-
content += `- [ ] **${todo.content}** _(${todo.activeForm})_
|
|
7660
|
-
`;
|
|
7661
|
-
}
|
|
7662
|
-
content += "\n";
|
|
7663
|
-
}
|
|
7664
|
-
if (pending.length > 0) {
|
|
7665
|
-
content += `### Pending
|
|
7666
|
-
|
|
7667
|
-
`;
|
|
7668
|
-
for (const todo of pending) {
|
|
7669
|
-
content += `- [ ] ${todo.content}
|
|
7670
|
-
`;
|
|
7671
|
-
}
|
|
7672
|
-
content += "\n";
|
|
7673
|
-
}
|
|
7674
|
-
if (completed.length > 0) {
|
|
7675
|
-
content += `### Completed
|
|
7676
|
-
|
|
7677
|
-
`;
|
|
7678
|
-
for (const todo of completed) {
|
|
7679
|
-
content += `- [x] ${todo.content}
|
|
7680
|
-
`;
|
|
7681
|
-
}
|
|
7682
|
-
content += "\n";
|
|
7683
|
-
}
|
|
7684
|
-
if (todos.length === 0) {
|
|
7685
|
-
content += `_(No active session tasks)_
|
|
7686
|
-
|
|
7687
|
-
`;
|
|
7688
|
-
}
|
|
7689
|
-
return content;
|
|
7690
|
-
}
|
|
7691
|
-
function extractPreservedSections(content) {
|
|
7692
|
-
let preserved = "";
|
|
7693
|
-
const sectionRegex = /\n(## (?!Current Session)[^\n]+[\s\S]*?)(?=\n## |\n---\n+\*Last updated|$)/g;
|
|
7694
|
-
const matches = content.matchAll(sectionRegex);
|
|
7695
|
-
for (const match of matches) {
|
|
7696
|
-
preserved += match[1];
|
|
7697
|
-
}
|
|
7698
|
-
return preserved;
|
|
7699
|
-
}
|
|
7700
|
-
function fixMalformedHeadings(content) {
|
|
7701
|
-
return content.replace(/^---#/gm, "#");
|
|
7702
|
-
}
|
|
7703
|
-
function buildTodoContent(todos, existingContent) {
|
|
7704
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7705
|
-
const preserved = extractPreservedSections(existingContent);
|
|
7706
|
-
let content = `# TODO
|
|
7707
|
-
|
|
7708
|
-
## Current Session
|
|
7709
|
-
|
|
7710
|
-
${formatSessionTodos(todos)}`;
|
|
7711
|
-
if (preserved.trim()) {
|
|
7712
|
-
content += preserved;
|
|
7713
|
-
}
|
|
7714
|
-
content = content.replace(/(\n---\s*)*(\n\*Last updated:.*\*\s*)*$/, "");
|
|
7715
|
-
content += `
|
|
7716
|
-
---
|
|
7717
|
-
|
|
7718
|
-
*Last updated: ${now}*
|
|
7719
|
-
`;
|
|
7720
|
-
return content;
|
|
7721
|
-
}
|
|
7722
7756
|
async function main() {
|
|
7723
7757
|
if (isWorkerSession()) return;
|
|
7724
7758
|
try {
|
|
@@ -7743,7 +7777,7 @@ async function main() {
|
|
|
7743
7777
|
const cwd = hookInput.cwd || process.cwd();
|
|
7744
7778
|
const todoPath = findTodoPath(cwd);
|
|
7745
7779
|
if (!existsSync5(todoPath)) {
|
|
7746
|
-
const parentDir = todoPath
|
|
7780
|
+
const parentDir = dirname4(todoPath);
|
|
7747
7781
|
mkdirSync4(parentDir, { recursive: true });
|
|
7748
7782
|
console.error(`Creating TODO.md at ${todoPath}`);
|
|
7749
7783
|
}
|
|
@@ -7754,7 +7788,7 @@ async function main() {
|
|
|
7754
7788
|
}
|
|
7755
7789
|
let newContent = buildTodoContent(todos, existingContent);
|
|
7756
7790
|
newContent = fixMalformedHeadings(newContent);
|
|
7757
|
-
|
|
7791
|
+
writeFileAtomic(todoPath, newContent);
|
|
7758
7792
|
const stats = {
|
|
7759
7793
|
inProgress: todos.filter((t) => t.status === "in_progress").length,
|
|
7760
7794
|
pending: todos.filter((t) => t.status === "pending").length,
|
|
@@ -9119,8 +9119,9 @@ function computeSimilarity(s1, s2) {
|
|
|
9119
9119
|
break;
|
|
9120
9120
|
}
|
|
9121
9121
|
}
|
|
9122
|
+
const overlapCap = minLength - prefixLength;
|
|
9122
9123
|
const totalLength = Math.max(s1.length, s2.length);
|
|
9123
|
-
return
|
|
9124
|
+
return (prefixLength + Math.min(suffixLength, overlapCap)) / totalLength;
|
|
9124
9125
|
}
|
|
9125
9126
|
|
|
9126
9127
|
// src/hooks/ts/lib/render-decision.ts
|
|
@@ -9051,16 +9051,23 @@ function resolveToken() {
|
|
|
9051
9051
|
}
|
|
9052
9052
|
return process.env.FORGE_TOKEN || process.env.AIBROKER_FORGE_TOKEN || void 0;
|
|
9053
9053
|
}
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9054
|
+
function curlQuote(v) {
|
|
9055
|
+
if (/[\r\n]/.test(v)) throw new ForgeError("refusing newline in curl config value");
|
|
9056
|
+
return v.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
9057
|
+
}
|
|
9058
|
+
function buildCurlConfig(method, url, token, timeoutMs) {
|
|
9059
|
+
return [
|
|
9060
|
+
`url = "${curlQuote(url)}"`,
|
|
9061
|
+
`request = "${curlQuote(method)}"`,
|
|
9062
|
+
`header = "Authorization: token ${curlQuote(token)}"`,
|
|
9059
9063
|
`header = "Content-Type: application/json"`,
|
|
9060
9064
|
`max-time = ${Math.max(0.5, timeoutMs / 1e3)}`,
|
|
9061
9065
|
`silent`,
|
|
9062
9066
|
`write-out = "\\n%{http_code}"`
|
|
9063
9067
|
].join("\n");
|
|
9068
|
+
}
|
|
9069
|
+
var curlHttp = (method, url, token, body, timeoutMs) => {
|
|
9070
|
+
const cfg = buildCurlConfig(method, url, token, timeoutMs);
|
|
9064
9071
|
const argv = body !== void 0 ? ["-K", "-", "--data-raw", body] : ["-K", "-"];
|
|
9065
9072
|
const r = spawnSync("curl", argv, { input: cfg, encoding: "utf8", timeout: timeoutMs + 500, maxBuffer: 16 * 1024 * 1024 });
|
|
9066
9073
|
if (r.error || r.status !== 0) throw new ForgeError(`curl failed (${r.error?.message ?? `exit ${r.status}`})`);
|
|
@@ -9321,9 +9328,9 @@ function currentWorkerId(env = process.env, logDir) {
|
|
|
9321
9328
|
|
|
9322
9329
|
// src/hooks/ts/pre-tool-use/worker-guard.ts
|
|
9323
9330
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
9324
|
-
import { readFileSync as
|
|
9331
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
9325
9332
|
import { homedir as homedir3 } from "node:os";
|
|
9326
|
-
import { dirname as
|
|
9333
|
+
import { dirname as dirname9, join as join16 } from "node:path";
|
|
9327
9334
|
|
|
9328
9335
|
// src/hooks/ts/lib/render-decision.ts
|
|
9329
9336
|
var GUARD_MARKER = "PAI guard: ";
|
|
@@ -11094,7 +11101,24 @@ function recordToolError(logDir, rec, now = Date.now()) {
|
|
|
11094
11101
|
|
|
11095
11102
|
// src/workers/loop-stop.ts
|
|
11096
11103
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
11097
|
-
|
|
11104
|
+
|
|
11105
|
+
// src/config/atomic-file.ts
|
|
11106
|
+
import { mkdirSync as mkdirSync7, renameSync as renameSync5, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
11107
|
+
import { randomBytes } from "node:crypto";
|
|
11108
|
+
import { dirname as dirname8 } from "node:path";
|
|
11109
|
+
function writeFileAtomic(path, text) {
|
|
11110
|
+
mkdirSync7(dirname8(path), { recursive: true });
|
|
11111
|
+
const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
|
|
11112
|
+
try {
|
|
11113
|
+
writeFileSync6(tmp, text, "utf8");
|
|
11114
|
+
renameSync5(tmp, path);
|
|
11115
|
+
} catch (e) {
|
|
11116
|
+
rmSync3(tmp, { force: true });
|
|
11117
|
+
throw e;
|
|
11118
|
+
}
|
|
11119
|
+
}
|
|
11120
|
+
|
|
11121
|
+
// src/workers/loop-stop.ts
|
|
11098
11122
|
import { join as join15 } from "node:path";
|
|
11099
11123
|
|
|
11100
11124
|
// src/workers/endreason.ts
|
|
@@ -11107,7 +11131,7 @@ function appendStopEvent(logDir, id, stop) {
|
|
|
11107
11131
|
}
|
|
11108
11132
|
|
|
11109
11133
|
// src/builds/queue.ts
|
|
11110
|
-
import { existsSync as existsSync15, mkdirSync as
|
|
11134
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync8, readdirSync as readdirSync4, readFileSync as readFileSync16, renameSync as renameSync6, rmSync as rmSync4, rmdirSync, statSync as statSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
11111
11135
|
import { join as join14 } from "node:path";
|
|
11112
11136
|
var defaultDeps = () => ({
|
|
11113
11137
|
isAlive: (pid) => {
|
|
@@ -11135,7 +11159,7 @@ var ticketFile = (dir, id) => join14(ticketsDir(dir), `${id}.json`);
|
|
|
11135
11159
|
function breakStaleMutex(m, staleMs = 5e3) {
|
|
11136
11160
|
const guard = `${m}.break`;
|
|
11137
11161
|
try {
|
|
11138
|
-
|
|
11162
|
+
mkdirSync8(guard);
|
|
11139
11163
|
} catch {
|
|
11140
11164
|
try {
|
|
11141
11165
|
if (Date.now() - statSync5(guard).mtimeMs > staleMs) rmdirSync(guard);
|
|
@@ -11154,12 +11178,12 @@ function breakStaleMutex(m, staleMs = 5e3) {
|
|
|
11154
11178
|
}
|
|
11155
11179
|
}
|
|
11156
11180
|
async function withMutex(dir, fn) {
|
|
11157
|
-
|
|
11181
|
+
mkdirSync8(dir, { recursive: true });
|
|
11158
11182
|
const m = join14(dir, "mutex");
|
|
11159
11183
|
const t0 = Date.now();
|
|
11160
11184
|
for (; ; ) {
|
|
11161
11185
|
try {
|
|
11162
|
-
|
|
11186
|
+
mkdirSync8(m);
|
|
11163
11187
|
break;
|
|
11164
11188
|
} catch {
|
|
11165
11189
|
breakStaleMutex(m);
|
|
@@ -11203,7 +11227,7 @@ async function releaseBuildsOf(dir, worker, d = {}) {
|
|
|
11203
11227
|
const mine = readTickets(dir).filter((t) => t.worker === worker);
|
|
11204
11228
|
for (const t of mine) {
|
|
11205
11229
|
killTicket(t, deps, true);
|
|
11206
|
-
|
|
11230
|
+
rmSync4(ticketFile(dir, t.id), { force: true });
|
|
11207
11231
|
}
|
|
11208
11232
|
return mine.map((t) => t.id);
|
|
11209
11233
|
});
|
|
@@ -11232,7 +11256,7 @@ function requestLoopStop(logDir, id, reason, deps = {}) {
|
|
|
11232
11256
|
const { kill = (pid, sig) => process.kill(pid, sig), claudePid = defaultClaudePid } = deps;
|
|
11233
11257
|
try {
|
|
11234
11258
|
const m = { ts: (/* @__PURE__ */ new Date()).toISOString(), reason };
|
|
11235
|
-
|
|
11259
|
+
writeFileAtomic(loopStopMarkerPath(logDir, id), JSON.stringify(m));
|
|
11236
11260
|
} catch {
|
|
11237
11261
|
}
|
|
11238
11262
|
appendStopEvent(logDir, id, { killed_by: "loop-guard", forced: false, reason });
|
|
@@ -11267,7 +11291,7 @@ function buildContext(cwd) {
|
|
|
11267
11291
|
home: homedir3(),
|
|
11268
11292
|
worktreeRoot,
|
|
11269
11293
|
inWorktree,
|
|
11270
|
-
mainCheckout: inWorktree && common ?
|
|
11294
|
+
mainCheckout: inWorktree && common ? dirname9(common) : null,
|
|
11271
11295
|
sharedCheckout: () => {
|
|
11272
11296
|
let logDir = null;
|
|
11273
11297
|
try {
|
|
@@ -11278,7 +11302,7 @@ function buildContext(cwd) {
|
|
|
11278
11302
|
},
|
|
11279
11303
|
testScript: () => {
|
|
11280
11304
|
try {
|
|
11281
|
-
const pkg = JSON.parse(
|
|
11305
|
+
const pkg = JSON.parse(readFileSync17(join16(worktreeRoot ?? cwd, "package.json"), "utf8"));
|
|
11282
11306
|
return typeof pkg?.scripts?.test === "string" ? pkg.scripts.test : null;
|
|
11283
11307
|
} catch {
|
|
11284
11308
|
return null;
|
|
@@ -9043,16 +9043,23 @@ function resolveToken() {
|
|
|
9043
9043
|
}
|
|
9044
9044
|
return process.env.FORGE_TOKEN || process.env.AIBROKER_FORGE_TOKEN || void 0;
|
|
9045
9045
|
}
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9046
|
+
function curlQuote(v) {
|
|
9047
|
+
if (/[\r\n]/.test(v)) throw new ForgeError("refusing newline in curl config value");
|
|
9048
|
+
return v.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
9049
|
+
}
|
|
9050
|
+
function buildCurlConfig(method, url, token, timeoutMs) {
|
|
9051
|
+
return [
|
|
9052
|
+
`url = "${curlQuote(url)}"`,
|
|
9053
|
+
`request = "${curlQuote(method)}"`,
|
|
9054
|
+
`header = "Authorization: token ${curlQuote(token)}"`,
|
|
9051
9055
|
`header = "Content-Type: application/json"`,
|
|
9052
9056
|
`max-time = ${Math.max(0.5, timeoutMs / 1e3)}`,
|
|
9053
9057
|
`silent`,
|
|
9054
9058
|
`write-out = "\\n%{http_code}"`
|
|
9055
9059
|
].join("\n");
|
|
9060
|
+
}
|
|
9061
|
+
var curlHttp = (method, url, token, body, timeoutMs) => {
|
|
9062
|
+
const cfg = buildCurlConfig(method, url, token, timeoutMs);
|
|
9056
9063
|
const argv = body !== void 0 ? ["-K", "-", "--data-raw", body] : ["-K", "-"];
|
|
9057
9064
|
const r = spawnSync("curl", argv, { input: cfg, encoding: "utf8", timeout: timeoutMs + 500, maxBuffer: 16 * 1024 * 1024 });
|
|
9058
9065
|
if (r.error || r.status !== 0) throw new ForgeError(`curl failed (${r.error?.message ?? `exit ${r.status}`})`);
|
|
@@ -294,7 +294,7 @@ function cdReason(command, cwd) {
|
|
|
294
294
|
if (existsSync2(target)) continue;
|
|
295
295
|
const fixed = repairValue(target, cwd, true, existsSync2);
|
|
296
296
|
if (!fixed) continue;
|
|
297
|
-
const next = command.replace(target, fixed);
|
|
297
|
+
const next = command.replace(target, () => fixed);
|
|
298
298
|
return `Wrong path in cd: ${target}. You are already in your worktree ${cwd}; drop the cd. Corrected command: ${next}`;
|
|
299
299
|
}
|
|
300
300
|
return null;
|