@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
package/README.md
CHANGED
|
@@ -1,25 +1,87 @@
|
|
|
1
1
|
# PAI Knowledge OS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Local AI used to be hard. Now it is a button.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
I have spent a long time on local AI. Getting a strong model to run on my own machine was the easy part; making it actually useful was not. Which server, which quantization, which port, how to keep it alive, how to send it only the work it can do, and how to fall back to the cloud when it cannot. Every piece worked on its own and none of them worked together.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
PAI is what came out of that, and I am giving it to the community. A MacBook can already run a serious model: on mine, [Strata](https://github.com/Niko1221/Strata) serves [Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next) in its compact [Gyro-M](https://huggingface.co/agentionai/Qwen3.8-Flash-Next-Gyro-GGUF) quantization, and PAI turns that into a worker like any other. Start it from the cockpit, and PAI routes worker jobs to it automatically, shows its speed and cache live, and hands a job to the cloud only when it needs a wider context or deeper reasoning than the local model has. You stop thinking about local AI. It just takes its share of the work.
|
|
8
|
+
|
|
9
|
+
**An AI chat is one vendor, one model, one budget and no memory. PAI turns it into a team: it remembers, it routes every job to the right model, cloud or local, and it shows you all of it live.**
|
|
10
|
+
|
|
11
|
+
You burn your premium tokens on work a local model could do. You hit the weekly limit on a Tuesday. Every new session starts from zero. PAI fixes all three:
|
|
12
|
+
|
|
13
|
+
- **Not bound to Anthropic.** Claude Code is only the front end you type into; the model behind it is your choice. Run a whole session on GLM, Kimi, any other provider you add, or a model on your own machine, with no Anthropic model involved at all. Or mix them: switch on the fly with `/model`, in the middle of a session, without losing your place.
|
|
14
|
+
- **Model routing, cloud and local.** When one provider's budget runs out, the next one takes over by itself, and every request is accounted per provider and per session.
|
|
15
|
+
- **A hierarchy that spends tokens where they matter.** Three tiers: `t0` the session you talk to, `t1` the orchestrator that plans and reviews, `t2` the workers that implement. Workers go local first, because local tokens are free. Cloud comes first only where it earns its price: wide context and real reasoning. And all of it is yours to set: each tier is an ordered list of models, the first available one serves, and you change the order as your default (`pai worker route set t2 local,glm/glm-5.3-flash`, or from the cockpit) or just for one session (`--session <name>`), without touching the others. Every worker runs in its own visible pane and git worktree; you review the diff, PAI merges it.
|
|
16
|
+
- **A live cockpit.** One page shows your token budget per provider, cache hits, every model and local server with start and stop buttons, running workers, routing per tier, and memory and embedding progress. Drag the cards into the layout you want.
|
|
17
|
+
- **Memory underneath it all.** Every session writes its own notes in the background, searchable across sessions, projects and your notes vault, by keyword, meaning or both. Everything stays on your machine.
|
|
18
|
+
|
|
19
|
+
**What's inside**
|
|
20
|
+
|
|
21
|
+
- Sessions: [pick and open](docs/features.md#pick-and-open-a-session) · [pause and end](docs/features.md#pause-and-end-a-session) · [session notes](docs/features.md#session-notes) · [context preservation](docs/features.md#context-preservation-and-auto-compact)
|
|
22
|
+
- Memory and search: [search memory](docs/features.md#search-your-memory) · [knowledge graph](docs/features.md#knowledge-graph) · [embeddings](docs/features.md#index-and-embeddings) · [observations](docs/features.md#observations)
|
|
23
|
+
- Notes and vault: [connect two ideas](docs/features.md#connect-two-ideas) · [find orphans](docs/features.md#find-orphans) · [what is emerging](docs/features.md#what-is-emerging) · [trace an idea](docs/features.md#trace-an-idea)
|
|
24
|
+
- Zettelkasten: [explore links](docs/features.md#explore-links) · [surprising connections](docs/features.md#surprising-connections) · [ask the vault](docs/features.md#ask-the-vault) · [vault health](docs/features.md#vault-health)
|
|
25
|
+
- Journal, review, plan: [journal](docs/features.md#journal) · [review](docs/features.md#review) · [plan](docs/features.md#plan)
|
|
26
|
+
- Tasks and ingress: [Todoist](docs/features.md#todoist-as-an-input-channel) · [GitHub issues](docs/features.md#github-issues-as-an-input-channel) · [PAILot](docs/features.md#pailot-as-an-input-channel) · [WhatsApp](docs/features.md#whatsapp-as-an-input-channel) · [Telegram](docs/features.md#telegram-as-an-input-channel)
|
|
27
|
+
- Workers: [run a worker](docs/features.md#run-a-worker) · [tiers and routing](docs/features.md#tiers-and-routing) · [local models](docs/features.md#local-models) · [plans](docs/features.md#plans) · [queue](docs/features.md#queue)
|
|
28
|
+
- Router and cockpit: [router](docs/features.md#router) · [cockpit](docs/features.md#cockpit) · [where tokens go](docs/features.md#where-tokens-go)
|
|
29
|
+
- Messaging and rules: [AIBroker](docs/features.md#aibroker) · [whisper rules](docs/features.md#whisper-rules) · [budget advisor](docs/features.md#budget-and-advisor-mode)
|
|
30
|
+
- Make and share: [art and diagrams](docs/features.md#art-and-diagrams) · [share](docs/features.md#share) · [research](docs/features.md#research-and-extraction)
|
|
31
|
+
- Care: [setup](docs/features.md#setup-and-update) · [backup](docs/features.md#backup-and-restore)
|
|
32
|
+
|
|
33
|
+
Everything PAI does: [docs/features.md](docs/features.md)
|
|
34
|
+
|
|
35
|
+
`pai` starts or resumes a session in the current project. `pai pause` and `pai end` save your place. Memory works on its own; the router, workers and cockpit join when you want them. Terms are explained in the [glossary](docs/README.md#words-used-in-these-docs).
|
|
36
|
+
|
|
37
|
+
**Install it in one sentence: tell Claude Code "Clone https://github.com/mnott/PAI and set it up for me".** [Jump to install](#install).
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+

|
|
8
52
|
|
|
9
53
|
*The router cockpit (`http://127.0.0.1:8790/cockpit`). See [the cockpit page](docs/cockpit.md).*
|
|
10
54
|
|
|
55
|
+
## How it fits together
|
|
56
|
+
|
|
57
|
+
<img src="docs/images/architecture.svg" width="100%" alt="PAI architecture: Claude Code sessions with PAI hooks and skills on top; PAI core (CLI, daemon, storage, notes, router on port 8790 with tiers t0, t1, t2 and the cockpit, workers) side by side with AIBroker (messaging hub, session control, inbound channels with prefixes); ingress from Todoist, GitHub issues, PAILot, WhatsApp and Telegram feeding AIBroker; model providers Anthropic, other cloud and local models behind the router; an operating system layer with iTerm2 and tmux for worker panes and session tabs, launchd or systemd services, and git worktrees">
|
|
58
|
+
|
|
59
|
+
*Source: [docs/images/architecture.drawio](docs/images/architecture.drawio), editable in draw.io.*
|
|
60
|
+
|
|
11
61
|
## Install
|
|
12
62
|
|
|
13
63
|
Prerequisites: [Claude Code](https://claude.com/claude-code) and Node.js 20 or newer. Docker is only needed for the optional PostgreSQL storage (semantic search); the default sqlite needs nothing.
|
|
14
64
|
|
|
15
|
-
|
|
65
|
+
The easy way: tell Claude Code
|
|
66
|
+
|
|
67
|
+
> Clone https://github.com/mnott/PAI and set it up for me
|
|
68
|
+
|
|
69
|
+
Claude reads this repository, finds the setup skill and walks you through it: it checks each phase first, does only what is missing, and ends with a pass/fail list of its checks.
|
|
70
|
+
|
|
71
|
+
Or install it as a plugin, then say **"set up PAI"**:
|
|
16
72
|
|
|
17
73
|
```
|
|
18
74
|
/plugin marketplace add mnott/PAI
|
|
19
75
|
/plugin install pai@pai
|
|
20
76
|
```
|
|
21
77
|
|
|
22
|
-
|
|
78
|
+
Setup also installs [AIBroker](https://github.com/mnott/AIBroker), a separate project that is PAI's messaging layer: messages between sessions, worker reports to the session that started them, terminal tab names, and WhatsApp, Telegram and PAILot all go through it. PAI starts without it, but none of that works until it is there. To install it by hand:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm install -g aibroker@^0.62.4
|
|
82
|
+
aibroker setup # service, MCP registration, Claude Code hooks
|
|
83
|
+
aibroker doctor # every check green, or it says exactly what to fix
|
|
84
|
+
```
|
|
23
85
|
|
|
24
86
|
Without the plugin, from a clone, or for a one-session plugin load: [docs/install/index.md](docs/install/index.md). Memory works as soon as setup is done; workers are optional ([First workers](docs/install/first-workers.md)).
|
|
25
87
|
|
|
@@ -177,4 +177,4 @@ async function switchToSession(target, opts = {}) {
|
|
|
177
177
|
|
|
178
178
|
//#endregion
|
|
179
179
|
export { switchToSession as i, fetchLiveSessions as n, sendToSession as r, callAiBroker as t };
|
|
180
|
-
//# sourceMappingURL=aibroker-client-
|
|
180
|
+
//# sourceMappingURL=aibroker-client-CQPGqLxL.mjs.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/config/atomic-file.ts
|
|
6
|
+
/** Write text to a temp file and rename it over `path`: a crash mid-write leaves the old file intact. */
|
|
7
|
+
function writeFileAtomic(path, text) {
|
|
8
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
9
|
+
const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
|
|
10
|
+
try {
|
|
11
|
+
writeFileSync(tmp, text, "utf8");
|
|
12
|
+
renameSync(tmp, path);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
rmSync(tmp, { force: true });
|
|
15
|
+
throw e;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { writeFileAtomic as t };
|
|
21
|
+
//# sourceMappingURL=atomic-file-BorMa4T3.mjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as readPaiMarker } from "./pai-marker-
|
|
2
|
-
import { i as populateSlugs } from "./search-
|
|
1
|
+
import { r as readPaiMarker } from "./pai-marker-DurzIbw8.mjs";
|
|
2
|
+
import { i as populateSlugs } from "./search-RSyeQqj1.mjs";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
|
|
@@ -158,4 +158,4 @@ function formatAutoRouteJson(result) {
|
|
|
158
158
|
|
|
159
159
|
//#endregion
|
|
160
160
|
export { formatAutoRouteJson as n, detectTopicShift as r, autoRoute as t };
|
|
161
|
-
//# sourceMappingURL=auto-route-
|
|
161
|
+
//# sourceMappingURL=auto-route-B4azPk4l.mjs.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "./config-XpZWOYOG.mjs";
|
|
2
|
+
import "./config-Bu1_vbY8.mjs";
|
|
3
|
+
import "./paths-CHifubDh.mjs";
|
|
4
|
+
import "./worktree-CrnOqTBW.mjs";
|
|
5
|
+
import "./status-ggJ7lgVg.mjs";
|
|
6
|
+
import "./pool-BRvoOkv6.mjs";
|
|
7
|
+
import "./registrable-Uzgmfyhz.mjs";
|
|
8
|
+
import "./pai-marker-DurzIbw8.mjs";
|
|
9
|
+
import { n as formatAutoRouteJson, t as autoRoute } from "./auto-route-B4azPk4l.mjs";
|
|
10
|
+
|
|
11
|
+
export { autoRoute, formatAutoRouteJson };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "./config-XpZWOYOG.mjs";
|
|
2
|
+
import "./config-Bu1_vbY8.mjs";
|
|
3
|
+
import "./paths-CHifubDh.mjs";
|
|
4
|
+
import "./status-ggJ7lgVg.mjs";
|
|
5
|
+
import "./scope-D-h6F6DN.mjs";
|
|
6
|
+
import { A as budgetSkipReason, D as budgetExceeded, E as budgetCache, M as budgetWall, N as fetchBudgetReading, O as budgetFresh, P as pickBudgetWindow, T as BudgetCache, j as budgetUntilLabel, k as budgetFull, w as BUDGET_TTL_MS } from "./routing-BAAST9vT.mjs";
|
|
7
|
+
import "./tool-errors-7E13StWd.mjs";
|
|
8
|
+
import "./wait-ByV0OyMZ.mjs";
|
|
9
|
+
import "./local-tiers-BE4jGaMa.mjs";
|
|
10
|
+
import "./caller-identity-yLFb7CKq.mjs";
|
|
11
|
+
import "./capacity-DEveQdFV.mjs";
|
|
12
|
+
import "./local-instances-DOxSgT_L.mjs";
|
|
13
|
+
import "./local-candidate-DLdwQt0s.mjs";
|
|
14
|
+
|
|
15
|
+
export { BUDGET_TTL_MS, BudgetCache, budgetCache, budgetExceeded, budgetFresh, budgetFull, budgetSkipReason, budgetUntilLabel, budgetWall, fetchBudgetReading, pickBudgetWindow };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { g as paiHomePath, l as claudeHomeDir } from "./runtime-paths-WsO9sJFc.mjs";
|
|
2
|
-
import { f as readMainConfigRaw } from "./config-
|
|
3
|
-
import { i as itermUuid } from "./scope-
|
|
2
|
+
import { f as readMainConfigRaw } from "./config-Bu1_vbY8.mjs";
|
|
3
|
+
import { i as itermUuid } from "./scope-D-h6F6DN.mjs";
|
|
4
|
+
import { n as minOf } from "./min-max-DrSRUaWQ.mjs";
|
|
4
5
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, writeFileSync } from "node:fs";
|
|
5
6
|
import { join } from "node:path";
|
|
6
7
|
|
|
@@ -271,7 +272,7 @@ async function buildNext(dir, idOrLabel, d = {}) {
|
|
|
271
272
|
const t = all.find((x) => x.id === idOrLabel) ?? all.find((x) => x.label === idOrLabel && x.state === "waiting");
|
|
272
273
|
if (!t) throw new Error(`no queued build "${idOrLabel}"`);
|
|
273
274
|
if (t.state !== "waiting") throw new Error(`build ${t.id} is already running`);
|
|
274
|
-
const lowest =
|
|
275
|
+
const lowest = minOf(all.filter((x) => x.state === "waiting").map((x) => x.seq));
|
|
275
276
|
writeTicket(dir, {
|
|
276
277
|
...t,
|
|
277
278
|
seq: lowest - 1
|
|
@@ -369,5 +370,5 @@ function callerIdentity(env = process.env, deps = {}) {
|
|
|
369
370
|
}
|
|
370
371
|
|
|
371
372
|
//#endregion
|
|
372
|
-
export {
|
|
373
|
-
//# sourceMappingURL=caller-identity-
|
|
373
|
+
export { buildSlots as _, buildsDir as a, stallMinutes as b, listBuilds as c, releaseBuildsOf as d, removeTicket as f, waitReason as g, tryStart as h, buildNext as i, listBuildsSync as l, ticketKind as m, breakStaleMutex as n, enqueue as o, renderBuildQueue as p, buildLogPath as r, getTicket as s, callerIdentity as t, patchTicket as u, poolSlots as v, testSlots as x, slotsFor as y };
|
|
374
|
+
//# sourceMappingURL=caller-identity-yLFb7CKq.mjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as isLocalProvider } from "./config-
|
|
2
|
-
import { O as reconcileStatuses, g as isLive, s as alive, v as loadStatus, w as ownsPid, y as loadStatuses } from "./status-
|
|
1
|
+
import { m as isLocalProvider } from "./config-XpZWOYOG.mjs";
|
|
2
|
+
import { O as reconcileStatuses, g as isLive, s as alive, v as loadStatus, w as ownsPid, y as loadStatuses } from "./status-ggJ7lgVg.mjs";
|
|
3
3
|
import { mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
|
|
@@ -488,4 +488,4 @@ async function capacityGate(o) {
|
|
|
488
488
|
|
|
489
489
|
//#endregion
|
|
490
490
|
export { liveQueue as a, queuedText as c, resolveCap as d, sessionOf as f, staggerGate as h, effectiveCap as i, reorderQueue as l, recordWarmup as m, capacityGate as n, providerCap as o, sessionScopeKey as p, capacityOf as r, queueRows as s, admitCap as t, reorderQueueTo as u };
|
|
491
|
-
//# sourceMappingURL=capacity-
|
|
491
|
+
//# sourceMappingURL=capacity-DEveQdFV.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { j as readWorkersSection, wt as appendLedger } from "./config-
|
|
2
|
-
import { i as ledgerPath, u as workersLogDir } from "./paths-
|
|
3
|
-
import { $ as isFlagToken, S as newWorkerId, nt as shortText } from "./status-
|
|
4
|
-
import { t as runWorker } from "./run-
|
|
1
|
+
import { j as readWorkersSection, wt as appendLedger } from "./config-XpZWOYOG.mjs";
|
|
2
|
+
import { i as ledgerPath, u as workersLogDir } from "./paths-CHifubDh.mjs";
|
|
3
|
+
import { $ as isFlagToken, S as newWorkerId, nt as shortText } from "./status-ggJ7lgVg.mjs";
|
|
4
|
+
import { t as runWorker } from "./run-6Q9kCPem.mjs";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
|
|
@@ -163,4 +163,4 @@ async function runChain(opts, deps = {}) {
|
|
|
163
163
|
|
|
164
164
|
//#endregion
|
|
165
165
|
export { swapPromptArg as n, runChain as t };
|
|
166
|
-
//# sourceMappingURL=chain-
|
|
166
|
+
//# sourceMappingURL=chain-D-yvET_y.mjs.map
|