pi-orchestrator-config 4.4.1 → 4.6.0
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 +12 -2
- package/extensions/coms/coms-p2p.ts +51 -39
- package/extensions/coms/coms-shared.ts +7 -5
- package/extensions/openai-compatible-discovery/index.ts +131 -122
- package/extensions/orchestrator/agents.ts +9 -1
- package/extensions/orchestrator/cron-store.ts +92 -37
- package/extensions/orchestrator/cron.ts +27 -6
- package/extensions/orchestrator/extended-autocomplete.ts +30 -1
- package/extensions/orchestrator/project-settings.ts +9 -29
- package/extensions/orchestrator/rules.ts +4 -1
- package/extensions/orchestrator/session-validation.ts +45 -24
- package/extensions/orchestrator/settings-source.ts +139 -0
- package/extensions/orchestrator/utils.ts +1 -1
- package/extensions/pidash/event-projection.ts +19 -0
- package/extensions/pidash/pidash-ui/dist/assets/{index-C1VH6cPk.js → index-CI6UL4g4.js} +1 -1
- package/extensions/pidash/pidash-ui/dist/index.html +1 -1
- package/extensions/pidash/pidash.ts +9 -3
- package/extensions/pidiff/pidiff-ui/dist/assets/{angular-html-ghA4VuM0.js → angular-html-Bfyy3ooe.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{angular-ts-BiEwt-Qs.js → angular-ts-nVgE7bZq.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{apl-DmYAGNOL.js → apl-tvfwqHpz.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{astro-Bju7L81l.js → astro-l8TnD3AA.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{blade-C_YtSRJN.js → blade-BdHBbmKC.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{c-DxcP9pmN.js → c-D1CypT9z.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{chapel-BjVM8zvB.js → chapel-D56VAXz2.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{cobol-CyAifE-8.js → cobol-BwRRZSIY.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{coffee-BNW4Zttb.js → coffee-Cet_1pvq.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{cpp-De6s9lN-.js → cpp-CZ8C9S-h.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{crystal-JzhjW33_.js → crystal-EOxgVG_1.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{css-DAnI1EKT.js → css-lK_4bfX4.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{edge-DlbkxEj4.js → edge-C7pTOYjM.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{elixir-BXz6vpDX.js → elixir-D1OnpXXN.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{elm-CJcSKM6_.js → elm-DPOsZNNm.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{erb-VHOaTR5g.js → erb-D_E9Tmw3.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{git-rebase-PAYwCVk-.js → git-rebase-FRK9CwsX.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{glimmer-js-CspJJiU_.js → glimmer-js-BNQDK9N_.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{glimmer-ts-CSMIai5o.js → glimmer-ts-TWnnEP-7.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{glsl-Cw9yKL2B.js → glsl-C90MQFKT.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{graphql-D0OMgGsM.js → graphql-hToq3IB7.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{hack-DfiAACVA.js → hack-B9KIVyIF.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{haml-DU8pAbRK.js → haml-CP3pGCyN.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{handlebars-CoaiK3xT.js → handlebars-D1bq27yj.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{html-B4C3aTRB.js → html-DDPkOyoL.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{html-derivative-C_NJUsxF.js → html-derivative-BR4J_BCH.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{http-Cr9w59E3.js → http-BmExgdIq.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{hurl-BEScLvfg.js → hurl-UvOw6UjF.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/index-Bo8LhGN_.js +2796 -0
- package/extensions/pidiff/pidiff-ui/dist/assets/{java-hb-3TTCg.js → java-CFjffq9z.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{javascript-Bc0DeQtz.js → javascript-D6jF2sRD.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{jinja-DoEIYL2y.js → jinja-_MAtAn3c.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{jison-C2OZYR2e.js → jison-CzjG9woH.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{json-DKeabECb.js → json-Cq0awPRn.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{jsx-Dadu-wAB.js → jsx-iffPQUDY.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{julia-CpUr0nh2.js → julia-BJh5g1V6.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{just-BysHL69Z.js → just-BiplQU-x.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{latex-iNrlK36R.js → latex-C9i8ER6l.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{liquid-g8x_A5Ru.js → liquid-CJFKQVVC.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{lua-B4BSWsUC.js → lua-CQPggDzM.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{marko-CHSFXjEi.js → marko-d7_vCT_U.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{mdc-js2C5rVG.js → mdc-5MqUEkF6.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{nginx-BblTQvRl.js → nginx-BGYrJESG.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{nim-ChxMAPPZ.js → nim-BT5d3bbB.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{org-CHoj3SWZ.js → org-Dcsoek_G.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{perl-3zusLAIc.js → perl-Dzum8ON5.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{php-DVx3dbu3.js → php-DMd6jR7H.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{pug-DITNjLsK.js → pug-zSUb8M7G.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{qml-BYmD788c.js → qml-B-xKh7qQ.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{r-Dp_qVPOX.js → r-Bjwskoo1.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{razor-DT4CEDjF.js → razor-CXf_WKrJ.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{regexp-DVFGbBOe.js → regexp-DT6fzMFy.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{rst-njZM0E3u.js → rst-9nW3vkMx.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{ruby-gu2hDDCx.js → ruby-qIjs3ahE.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{sas-Bo6NwyH7.js → sas-C5jUuuyr.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{scss-COdGMqPA.js → scss-DDLNCEB-.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{shellscript-DSg7qNC1.js → shellscript-BhivxeP8.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{shellsession-CD1RmUpx.js → shellsession-n_duFdfp.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{soy-C0QWCEMl.js → soy-Dpt5nO7G.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{sql-VoWQdTUw.js → sql-BtjLhqvp.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{stata-BEj75h4q.js → stata-D4GbpMWg.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{surrealql-Cj1XbW6j.js → surrealql-Cn3MlekA.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{svelte-HcwCBvjC.js → svelte-DkuizfXa.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{templ-D775vyzu.js → templ-Bu3VqwV1.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{tex-DNmK_71Q.js → tex-BmuNCLCK.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{ts-tags-KERjFDJj.js → ts-tags-BYWWTBIT.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{tsx-CMT8AiHA.js → tsx-DNTVrA8s.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{twig-B5uxCA6R.js → twig-CxSsuKw_.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{typescript-5zwf3bJw.js → typescript-nBJ-jOMj.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{typst-xx02l63O.js → typst-CJ8ooa07.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{vue-BvvQRkFj.js → vue-CFh-25xK.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{vue-html-BrBDvgBy.js → vue-html-C0o6Mt8F.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{vue-vine-1CllPWUz.js → vue-vine-CdvaqX2M.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/worker-1fjNO6T8.js +164 -0
- package/extensions/pidiff/pidiff-ui/dist/assets/{xml-C3nsfg4x.js → xml-DgTZJwkL.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{xsl-DDOShcMh.js → xsl-DpEWsE0p.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/assets/{yaml-BGNXenqm.js → yaml-DnMT_m8N.js} +1 -1
- package/extensions/pidiff/pidiff-ui/dist/index.html +1 -1
- package/extensions/pidiff/pidiff-ui/package.json +1 -1
- package/extensions/providers/acpx-driver.ts +136 -69
- package/extensions/providers/claude-driver.ts +20 -18
- package/extensions/providers/cursor-acpx-driver.ts +136 -70
- package/extensions/providers/cursor-cli-driver.ts +22 -17
- package/extensions/providers/gemini-driver.ts +20 -17
- package/extensions/providers/index.ts +10 -7
- package/extensions/providers/last-thinking-level.ts +336 -70
- package/extensions/shared/build-system-prompt.ts +12 -5
- package/extensions/shared/create-runtime-provider.ts +7 -1
- package/extensions/shared/file-logger.ts +17 -16
- package/extensions/shared/logger.ts +7 -3
- package/extensions/shared/openai-compatible-discovery.ts +17 -7
- package/package.json +10 -2
- package/prompts/qodo-review.md +93 -0
- package/scripts/daemon-shared.ts +11 -0
- package/scripts/pidash-server.ts +2 -2
- package/scripts/pidiff-server.ts +2 -2
- package/extensions/pidiff/pidiff-ui/dist/assets/index-CisAus9r.js +0 -2801
- package/extensions/pidiff/pidiff-ui/dist/assets/worker-BX5VNpEv.js +0 -161
package/README.md
CHANGED
|
@@ -65,6 +65,7 @@ Single extension that provides:
|
|
|
65
65
|
| `/issue-review` | Review a GitHub issue spec and fix it |
|
|
66
66
|
| `/release [flags]` | Create GitHub release with changelog and version bumping |
|
|
67
67
|
| `/review-local [branch]` | Review local uncommitted or branch changes |
|
|
68
|
+
| `/qodo-review [--autofix] [--fast\|--deep] [--ticket <url>] [path ...]` | Review local changes with Qodo, attach session context, and optionally autofix (max 3 cycles) |
|
|
68
69
|
| `/review-handler [url] [--autorabbit] [--autoqodo]` | Process PR review comments, fix approved items |
|
|
69
70
|
| `/domain-model [focus area]` | Scan codebase and build/update a CONTEXT.md domain glossary for consistent AI vocabulary |
|
|
70
71
|
| `/refine-review <url>` | Refine and improve existing PR review comments |
|
|
@@ -76,7 +77,7 @@ Single extension that provides:
|
|
|
76
77
|
| `/dream` | Run memory consolidation — extract, deduplicate, maintain topic-based memory |
|
|
77
78
|
| `/remember <what>` | Save a memory for future sessions |
|
|
78
79
|
| `/dream-auto` | Toggle automatic memory dreaming (every 3h + session end) |
|
|
79
|
-
| `/cron add\|list\|list-all\|remove [--persist]` | Schedule recurring tasks. Session jobs end with the session; `--persist` keeps a job across Pi sessions in this project. Add/remove mutations still work when leader election fails closed on an unsupported platform. For example: `/cron add every 2h check for new issues --persist` or `/cron remove persist:<uuid>`. `/cron list` opens an overlay for the selected jobs (or both when omitted). Persistent delivery is local at-least-once: a crash or leader recovery can repeat a run. |
|
|
80
|
+
| `/cron add\|list\|list-all\|remove [--persist]` | Schedule recurring tasks. Session jobs end with the session; `--persist` keeps a job across Pi sessions in this project. Add/remove mutations still work when leader election fails closed on an unsupported platform. For example: `/cron add every 2h check for new issues --persist` or `/cron remove persist:<uuid>`. `/cron list` opens an overlay for the selected jobs (or both when omitted). Persistent delivery is local at-least-once: a crash or leader recovery can repeat a run. Project cron writes use a stable OS `flock` (included in Docker via `util-linux`) across the entire transaction; native installations need `flock` and a shared filesystem that supports advisory locks. A busy or unavailable lock fails closed after two seconds. **Upgrade gate (enforced):** stop and drain every old Pi process writing crons on the shared mount before starting a version with this kernel lock; old directory-lock writers do not honor `flock` and must not resume. If a legacy `crons.json.mutation.lock` directory exists, new writes fail closed even if its PID is invisible or its heartbeat expired. Only after verifying every old writer cannot resume may an operator remove that stale directory (not `crons.json` or cron tasks). Never remove it merely because a write timed out. |
|
|
80
81
|
| `/async-kill [name\|id\|all]` | Kill async agents (overlay picker or by name/id) |
|
|
81
82
|
| `/pi-config-settings [project\|global]` | Interactive TUI settings editor — browse all pi-config settings with scope indicators, smart pickers for providers/models, and immediate save |
|
|
82
83
|
| `/status` | Unified session snapshot — async agents, cron tasks, git branch, context usage |
|
|
@@ -466,6 +467,13 @@ settings; it reads the project locally and stores its regenerable graph in `./gr
|
|
|
466
467
|
Native installations require Node.js 22+, npm 12+, Python 3, `make`, and G++; the
|
|
467
468
|
installer uses the same audited strict installation and failure remains non-fatal.
|
|
468
469
|
|
|
470
|
+
**Persistent cron locking:** The image includes `flock` from `util-linux` for kernel-backed,
|
|
471
|
+
cross-container store mutations on shared mounts. The shared filesystem must support
|
|
472
|
+
advisory locks. Before deploying this version alongside old Pi containers, stop and
|
|
473
|
+
drain every legacy cron writer. An existing legacy mutation-lock directory blocks
|
|
474
|
+
new writes until an operator verifies old writers cannot resume and removes only
|
|
475
|
+
that directory. Do not stop running containers merely to test this PR.
|
|
476
|
+
|
|
469
477
|
**CLI provider binaries (optional `cli_agents`):** The image installs the CLIs used by
|
|
470
478
|
`cli-*` providers — `claude` (Claude Code), `gemini` (`@google/gemini-cli`), and
|
|
471
479
|
`agent` (Cursor Agent CLI). Enable with `cli_agents` in settings (e.g.
|
|
@@ -710,6 +718,7 @@ PI_PIDIFF_ENABLE=false pi
|
|
|
710
718
|
| `-v "$HOME/.claude/credentials.json":"$HOME/.claude/credentials.json":ro` | Claude CLI auth (for acpx-claude / cli-claude models) |
|
|
711
719
|
| `-v "$HOME/.config/glab-cli":"$HOME/.config/glab-cli":ro` | GitLab CLI config (auth tokens, host settings) |
|
|
712
720
|
| `-v "$HOME/.coderabbit":"$HOME/.coderabbit":rw` | CodeRabbit CLI auth and review data |
|
|
721
|
+
| `-v "$HOME/.qodo":"$HOME/.qodo":rw` | Qodo CLI auth directory (mount at the container user's `$HOME/.qodo`; with `PI_HOST_USER`, that is `/home/$PI_HOST_USER/.qodo`). Create it on the host first with `mkdir -p "$HOME/.qodo"`; inside the container run `qodo read whoami` and, if signed out, `qodo login`. Host OS-keychain credentials may not work inside the container. |
|
|
713
722
|
| `-v "$HOME/screenshots":"$HOME/screenshots"` | Share screenshots/images with the agent |
|
|
714
723
|
| `-v /var/run/docker.sock:/var/run/docker.sock:ro` + `--group-add $(stat -c '%g' /var/run/docker.sock)` | Docker container inspection via `docker-safe` |
|
|
715
724
|
| `-v /var/run/podman/podman.sock:/var/run/podman/podman.sock:ro` | Podman container inspection via `docker-safe` |
|
|
@@ -740,6 +749,7 @@ PI_PIDIFF_ENABLE=false pi
|
|
|
740
749
|
| `jq` | JSON processing |
|
|
741
750
|
| `rg` (ripgrep) | Fast recursive search |
|
|
742
751
|
| `cr` | CodeRabbit CLI — local AI code reviews |
|
|
752
|
+
| `qodo` | Qodo CLI — local code reviews (`qodo --version`; mount `~/.qodo` as above and authenticate inside the container if needed) |
|
|
743
753
|
| `curl` | HTTP requests |
|
|
744
754
|
|
|
745
755
|
#### `myk-pi-tools` subcommands
|
|
@@ -886,7 +896,7 @@ See [DEVELOPMENT.md](DEVELOPMENT.md) for tips on testing extensions locally, run
|
|
|
886
896
|
|
|
887
897
|
## Prerequisites
|
|
888
898
|
|
|
889
|
-
- [pi](https://github.com/badlogic/pi-mono) (minimum version: **0.
|
|
899
|
+
- [pi](https://github.com/badlogic/pi-mono) (minimum version: **0.87.0**). Pidash uses Pi's `ui_prompt_start` and `ui_prompt_end` events to show prompt wait separately from agent work.
|
|
890
900
|
- `gh` CLI (for GitHub operations)
|
|
891
901
|
- `uv` (for Python execution)
|
|
892
902
|
- `myk-pi-tools` (optional, for `/pr-review` and `/release`)
|
|
@@ -848,10 +848,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
848
848
|
ackOk(socket, env.msg_id);
|
|
849
849
|
}
|
|
850
850
|
|
|
851
|
-
function buildAgentCard(): AgentCard {
|
|
851
|
+
async function buildAgentCard(): Promise<AgentCard> {
|
|
852
852
|
const ctx = currentCtx;
|
|
853
853
|
const ident = identity;
|
|
854
854
|
const pct = ctx ? Math.round(ctx.getContextUsage()?.percent ?? 0) : 0;
|
|
855
|
+
log.debug("build_agent_card", { hasIdentity: !!ident });
|
|
855
856
|
return {
|
|
856
857
|
name: ident?.name ?? "unknown",
|
|
857
858
|
purpose: ident?.purpose ?? "",
|
|
@@ -859,22 +860,24 @@ export default function (pi: ExtensionAPI) {
|
|
|
859
860
|
color: ident?.color ?? "#36F9F6",
|
|
860
861
|
context_used_pct: pct,
|
|
861
862
|
queue_depth: getPendingInboundCount(),
|
|
862
|
-
tasks_summary: readTaskSummary(currentCtx?.cwd ?? process.cwd(), currentCtx?.sessionManager?.getSessionId?.()),
|
|
863
|
+
tasks_summary: await readTaskSummary(currentCtx?.cwd ?? process.cwd(), currentCtx?.sessionManager?.getSessionId?.()),
|
|
863
864
|
};
|
|
864
865
|
}
|
|
865
866
|
|
|
866
867
|
/** Push current agent card to ping worker so it can respond independently */
|
|
867
|
-
function updatePingWorkerCard(): void {
|
|
868
|
+
async function updatePingWorkerCard(): Promise<void> {
|
|
869
|
+
log.debug("update_ping_worker_card", { ready: pingWorkerReady });
|
|
868
870
|
if (!pingWorker || !pingWorkerReady) return;
|
|
869
871
|
try {
|
|
870
|
-
const card = buildAgentCard();
|
|
872
|
+
const card = await buildAgentCard();
|
|
871
873
|
const pong: Pong = { type: "pong", msg_id: "", agent_card: card };
|
|
872
874
|
pingWorker.postMessage({ type: "update_card", pong });
|
|
873
875
|
} catch { /* ignore */ }
|
|
874
876
|
}
|
|
875
877
|
|
|
876
|
-
function handlePing(socket: net.Socket, env: PingEnvelope): void {
|
|
877
|
-
|
|
878
|
+
async function handlePing(socket: net.Socket, env: PingEnvelope): Promise<void> {
|
|
879
|
+
log.debug("handle_ping", { msgId: env.msg_id });
|
|
880
|
+
const card = await buildAgentCard();
|
|
878
881
|
const pong: Pong = { type: "pong", msg_id: env.msg_id, agent_card: card };
|
|
879
882
|
try {
|
|
880
883
|
socket.write(JSON.stringify(pong) + "\n");
|
|
@@ -883,7 +886,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
883
886
|
}
|
|
884
887
|
try { socket.end(); } catch { /* ignore */ }
|
|
885
888
|
// Also update worker with latest card
|
|
886
|
-
updatePingWorkerCard();
|
|
889
|
+
await updatePingWorkerCard();
|
|
887
890
|
}
|
|
888
891
|
|
|
889
892
|
function isValidEnvelope(obj: any): obj is Envelope {
|
|
@@ -935,7 +938,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
935
938
|
} else if (parsed.type === "response") {
|
|
936
939
|
handleResponse(socket, parsed as ResponseEnvelope);
|
|
937
940
|
} else if (parsed.type === "ping") {
|
|
938
|
-
handlePing(socket, parsed as PingEnvelope);
|
|
941
|
+
void handlePing(socket, parsed as PingEnvelope).catch(() => nack(socket, parsed.msg_id, "internal error"));
|
|
939
942
|
} else if (parsed.type === "task_update") {
|
|
940
943
|
handleTaskUpdate(socket, parsed as TaskUpdateEnvelope);
|
|
941
944
|
} else if (parsed.type === "queue_manage") {
|
|
@@ -1994,7 +1997,7 @@ Do not respond to this message.`;
|
|
|
1994
1997
|
// Append sender's active tasks for this peer to the prompt
|
|
1995
1998
|
let promptText = params.prompt;
|
|
1996
1999
|
try {
|
|
1997
|
-
const { listTasksForSession } =
|
|
2000
|
+
const { listTasksForSession } = await import("../pitasks/index.js");
|
|
1998
2001
|
const targetPiSessionId = target.pi_session_id || target.coms_session_id;
|
|
1999
2002
|
const allTasks = listTasksForSession(targetPiSessionId, target.cwd) || [];
|
|
2000
2003
|
const myTasks = allTasks.filter((t: any) =>
|
|
@@ -2021,27 +2024,8 @@ Do not respond to this message.`;
|
|
|
2021
2024
|
tasks: params.tasks ?? null,
|
|
2022
2025
|
};
|
|
2023
2026
|
|
|
2024
|
-
//
|
|
2025
|
-
|
|
2026
|
-
comsSendCalledThisTurn.add(target.coms_session_id);
|
|
2027
|
-
|
|
2028
|
-
// Auto-create tasks on the target's task store (sender-side, instant)
|
|
2029
|
-
if (params.tasks && params.tasks.length > 0 && target.coms_session_id) {
|
|
2030
|
-
try {
|
|
2031
|
-
const count = createComsInboundTasks(
|
|
2032
|
-
params.tasks,
|
|
2033
|
-
{ sender_session: identity.coms_session_id, sender_name: identity.name, sender_endpoint: identity.endpoint },
|
|
2034
|
-
target.pi_session_id || target.coms_session_id,
|
|
2035
|
-
target.cwd,
|
|
2036
|
-
);
|
|
2037
|
-
if (count > 0) {
|
|
2038
|
-
log.info("tasks_auto_created", msg_id, "to", target.name, "count", count);
|
|
2039
|
-
}
|
|
2040
|
-
} catch { /* best-effort */ }
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
// Register a pending entry whose promise the receiver-side handleResponse
|
|
2044
|
-
// (or the timeout below) will settle.
|
|
2027
|
+
// Register before sending. A peer may acknowledge and respond before
|
|
2028
|
+
// task creation's dynamic import completes.
|
|
2045
2029
|
let resolveFn!: (v: { response?: any; error?: string | null }) => void;
|
|
2046
2030
|
let rejectFn!: (e: Error) => void;
|
|
2047
2031
|
const promise = new Promise<{ response?: any; error?: string | null }>((res, rej) => {
|
|
@@ -2069,13 +2053,37 @@ Do not respond to this message.`;
|
|
|
2069
2053
|
try { (entry.timer as any).unref?.(); } catch { /* ignore */ }
|
|
2070
2054
|
pendingReplies.set(msg_id, entry);
|
|
2071
2055
|
|
|
2072
|
-
log.debug("outbound_prompt", msg_id, "to", target.name, "hops", hops);
|
|
2073
|
-
|
|
2074
|
-
// Track pending outbound
|
|
2075
2056
|
const targetKey = target.name;
|
|
2076
2057
|
if (!pendingOutbound.has(targetKey)) pendingOutbound.set(targetKey, new Set());
|
|
2077
2058
|
pendingOutbound.get(targetKey)!.add(msg_id);
|
|
2078
2059
|
|
|
2060
|
+
try {
|
|
2061
|
+
await sendEnvelope(target.endpoint, env);
|
|
2062
|
+
} catch (error) {
|
|
2063
|
+
pendingReplies.delete(msg_id);
|
|
2064
|
+
pendingOutbound.get(targetKey)?.delete(msg_id);
|
|
2065
|
+
if (pendingOutbound.get(targetKey)?.size === 0) pendingOutbound.delete(targetKey);
|
|
2066
|
+
if (entry.timer) clearTimeout(entry.timer);
|
|
2067
|
+
throw error;
|
|
2068
|
+
}
|
|
2069
|
+
comsSendCalledThisTurn.add(target.coms_session_id);
|
|
2070
|
+
|
|
2071
|
+
if (params.tasks && params.tasks.length > 0 && target.coms_session_id) {
|
|
2072
|
+
try {
|
|
2073
|
+
const count = await createComsInboundTasks(
|
|
2074
|
+
params.tasks,
|
|
2075
|
+
{ sender_session: identity.coms_session_id, sender_name: identity.name, sender_endpoint: identity.endpoint },
|
|
2076
|
+
target.pi_session_id || target.coms_session_id,
|
|
2077
|
+
target.cwd,
|
|
2078
|
+
);
|
|
2079
|
+
if (count > 0) log.info("tasks_auto_created", msg_id, "to", target.name, "count", count);
|
|
2080
|
+
} catch (error) {
|
|
2081
|
+
log.warn("tasks_auto_create_failed", { msg_id, target: target.name, error: error instanceof Error ? error.message : String(error) });
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
log.debug("outbound_prompt", msg_id, "to", target.name, "hops", hops);
|
|
2086
|
+
|
|
2079
2087
|
// Peer status from peerCards
|
|
2080
2088
|
const peerCard = peerCards.get(target.coms_session_id);
|
|
2081
2089
|
const peer_queue_depth = peerCard?.queue_depth ?? 0;
|
|
@@ -2305,6 +2313,7 @@ Do not respond to this message.`;
|
|
|
2305
2313
|
}), { description: "Tasks to create on the peer" }),
|
|
2306
2314
|
}),
|
|
2307
2315
|
async execute(_callId, params) {
|
|
2316
|
+
log.debug("coms_tasks_create_start", { target: params.target, count: params.tasks?.length ?? 0 });
|
|
2308
2317
|
if (!identity) throw new Error("coms not initialised");
|
|
2309
2318
|
if (!params.tasks || params.tasks.length === 0) throw new Error("coms_tasks_create requires at least one task");
|
|
2310
2319
|
const target = await resolveTarget(params.target);
|
|
@@ -2320,7 +2329,7 @@ Do not respond to this message.`;
|
|
|
2320
2329
|
if (identity.endpoint) meta.sender_endpoint = identity.endpoint;
|
|
2321
2330
|
|
|
2322
2331
|
try {
|
|
2323
|
-
const { createTasksForSession, listTasksForSession, updateTaskForSession } =
|
|
2332
|
+
const { createTasksForSession, listTasksForSession, updateTaskForSession } = await import("../pitasks/index.js");
|
|
2324
2333
|
const targetPiSessionId = target.pi_session_id || target.coms_session_id;
|
|
2325
2334
|
|
|
2326
2335
|
// Create all tasks in one batch
|
|
@@ -2401,12 +2410,13 @@ Do not respond to this message.`;
|
|
|
2401
2410
|
task_id: Type.String({ description: "Task ID to delete." }),
|
|
2402
2411
|
}),
|
|
2403
2412
|
async execute(_callId, params) {
|
|
2413
|
+
log.debug("coms_task_delete_start", { target: params.target, taskId: params.task_id });
|
|
2404
2414
|
if (!identity) throw new Error("coms not initialised");
|
|
2405
2415
|
const target = await resolveTarget(params.target);
|
|
2406
2416
|
if (!target) throw new Error(`coms: no live agent matching "${params.target}"`);
|
|
2407
2417
|
|
|
2408
2418
|
try {
|
|
2409
|
-
const { getTaskForSession, deleteTaskForSession } =
|
|
2419
|
+
const { getTaskForSession, deleteTaskForSession } = await import("../pitasks/index.js");
|
|
2410
2420
|
const targetPiSessionId = target.pi_session_id || target.coms_session_id;
|
|
2411
2421
|
const task = getTaskForSession(targetPiSessionId, params.task_id, target.cwd);
|
|
2412
2422
|
if (!task) throw new Error(`Task #${params.task_id} not found`);
|
|
@@ -2440,12 +2450,13 @@ Do not respond to this message.`;
|
|
|
2440
2450
|
target: Type.String({ description: "Peer name or session_id." }),
|
|
2441
2451
|
}),
|
|
2442
2452
|
async execute(_callId, params) {
|
|
2453
|
+
log.debug("coms_task_list_start", { target: params.target });
|
|
2443
2454
|
if (!identity) throw new Error("coms not initialised");
|
|
2444
2455
|
const target = await resolveTarget(params.target);
|
|
2445
2456
|
if (!target) throw new Error(`coms: no live agent matching "${params.target}"`);
|
|
2446
2457
|
|
|
2447
2458
|
try {
|
|
2448
|
-
const { listTasksForSession } =
|
|
2459
|
+
const { listTasksForSession } = await import("../pitasks/index.js");
|
|
2449
2460
|
const targetPiSessionId = target.pi_session_id || target.coms_session_id;
|
|
2450
2461
|
const tasks = listTasksForSession(targetPiSessionId, target.cwd);
|
|
2451
2462
|
log.debug("coms_task_list", target.name, "tasks", tasks?.length ?? 0);
|
|
@@ -2494,12 +2505,13 @@ Do not respond to this message.`;
|
|
|
2494
2505
|
task_id: Type.String({ description: "Task ID to retrieve." }),
|
|
2495
2506
|
}),
|
|
2496
2507
|
async execute(_callId, params) {
|
|
2508
|
+
log.debug("coms_task_get_start", { target: params.target, taskId: params.task_id });
|
|
2497
2509
|
if (!identity) throw new Error("coms not initialised");
|
|
2498
2510
|
const target = await resolveTarget(params.target);
|
|
2499
2511
|
if (!target) throw new Error(`coms: no live agent matching "${params.target}"`);
|
|
2500
2512
|
|
|
2501
2513
|
try {
|
|
2502
|
-
const { getTaskForSession } =
|
|
2514
|
+
const { getTaskForSession, listTasksForSession } = await import("../pitasks/index.js");
|
|
2503
2515
|
const targetPiSessionId = target.pi_session_id || target.coms_session_id;
|
|
2504
2516
|
const task = getTaskForSession(targetPiSessionId, params.task_id, target.cwd);
|
|
2505
2517
|
if (!task) throw new Error(`Task #${params.task_id} not found on ${target.name}`);
|
|
@@ -2512,7 +2524,6 @@ Do not respond to this message.`;
|
|
|
2512
2524
|
if (task.owner) lines.push(`Owner: ${task.owner}`);
|
|
2513
2525
|
lines.push(`Description: ${desc}`);
|
|
2514
2526
|
if (task.blockedBy?.length > 0) {
|
|
2515
|
-
const { listTasksForSession } = require("../pitasks/index.js");
|
|
2516
2527
|
const allTasks = listTasksForSession(targetPiSessionId, target.cwd);
|
|
2517
2528
|
const openBlockers = task.blockedBy.filter((bid: string) => {
|
|
2518
2529
|
const blocker = allTasks.find((bt: any) => bt.id === bid);
|
|
@@ -2549,12 +2560,13 @@ Do not respond to this message.`;
|
|
|
2549
2560
|
addBlockedBy: Type.Optional(Type.Array(Type.String(), { description: "Task IDs that block this task" })),
|
|
2550
2561
|
}),
|
|
2551
2562
|
async execute(_callId, params) {
|
|
2563
|
+
log.debug("coms_task_update_start", { target: params.target, taskId: params.task_id });
|
|
2552
2564
|
if (!identity) throw new Error("coms not initialised");
|
|
2553
2565
|
const target = await resolveTarget(params.target);
|
|
2554
2566
|
if (!target) throw new Error(`coms: no live agent matching "${params.target}"`);
|
|
2555
2567
|
|
|
2556
2568
|
try {
|
|
2557
|
-
const { getTaskForSession, updateTaskForSession } =
|
|
2569
|
+
const { getTaskForSession, updateTaskForSession } = await import("../pitasks/index.js");
|
|
2558
2570
|
const targetPiSessionId = target.pi_session_id || target.coms_session_id;
|
|
2559
2571
|
const task = getTaskForSession(targetPiSessionId, params.task_id, target.cwd);
|
|
2560
2572
|
if (!task) throw new Error(`Task #${params.task_id} not found on ${target.name}`);
|
|
@@ -461,9 +461,10 @@ export function readFrontmatterFromArgv(argv: string[]): { name?: string; descri
|
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
-
export function readTaskSummary(_cwd: string, _sessionId?: string): { total: number; completed: number; in_progress: number } | null {
|
|
464
|
+
export async function readTaskSummary(_cwd: string, _sessionId?: string): Promise<{ total: number; completed: number; in_progress: number } | null> {
|
|
465
|
+
log.debug("read_task_summary", { hasSessionId: !!_sessionId });
|
|
465
466
|
try {
|
|
466
|
-
const { listTasks } =
|
|
467
|
+
const { listTasks } = await import("../pitasks/index.js");
|
|
467
468
|
const tasks = listTasks();
|
|
468
469
|
if (!tasks || tasks.length === 0) return null;
|
|
469
470
|
let total = 0, completed = 0, in_progress = 0;
|
|
@@ -650,17 +651,18 @@ const MAX_TASK_FIELD_LEN = 2000;
|
|
|
650
651
|
* Runs on the SENDER side — uses createTaskForSession with the target's session ID.
|
|
651
652
|
* TaskStore handles locking, file format, everything.
|
|
652
653
|
*/
|
|
653
|
-
export function createComsInboundTasks(
|
|
654
|
+
export async function createComsInboundTasks(
|
|
654
655
|
tasks: Array<{ subject: string; description: string }>,
|
|
655
656
|
origin: ComsOrigin,
|
|
656
657
|
targetSessionId: string,
|
|
657
658
|
targetCwd?: string,
|
|
658
|
-
): number {
|
|
659
|
+
): Promise<number> {
|
|
660
|
+
log.debug("create_coms_inbound_tasks", { targetSessionId, count: tasks?.length ?? 0 });
|
|
659
661
|
if (!tasks || tasks.length === 0 || !targetSessionId) return 0;
|
|
660
662
|
|
|
661
663
|
let createTaskForSession: any;
|
|
662
664
|
try {
|
|
663
|
-
createTaskForSession =
|
|
665
|
+
createTaskForSession = (await import("../pitasks/index.js")).createTaskForSession;
|
|
664
666
|
} catch { return 0; }
|
|
665
667
|
if (!createTaskForSession) return 0;
|
|
666
668
|
|