@qodeca/xezar 0.13.0 → 0.14.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 +72 -39
- package/dist/agent-config/account-identity.d.ts +2 -8
- package/dist/agent-config/account-identity.js +54 -10
- package/dist/agent-config/account-identity.js.map +1 -1
- package/dist/agent-config/catalog.d.ts +49 -7
- package/dist/agent-config/catalog.js +107 -0
- package/dist/agent-config/catalog.js.map +1 -1
- package/dist/agent-config/model-settings/pi.d.ts +12 -6
- package/dist/agent-config/model-settings/pi.js +12 -6
- package/dist/agent-config/model-settings/pi.js.map +1 -1
- package/dist/agent-config/seed.js +10 -0
- package/dist/agent-config/seed.js.map +1 -1
- package/dist/contract/github.d.ts +15 -0
- package/dist/contract/index.d.ts +9 -0
- package/dist/contract/index.js +1527 -895
- package/dist/contract/mcp-api-reference.d.ts +174 -0
- package/dist/contract/mcp-audit.d.ts +103 -0
- package/dist/contract/mcp-discovery.d.ts +257 -0
- package/dist/contract/mcp-event-catalog.d.ts +121 -0
- package/dist/contract/mcp-event-catalog.test.d.ts +1 -0
- package/dist/contract/mcp-idempotency.d.ts +200 -0
- package/dist/contract/mcp-journal.d.ts +268 -0
- package/dist/contract/mcp-leader.d.ts +88 -0
- package/dist/contract/mcp-ownership.d.ts +78 -0
- package/dist/contract/mcp-versioning.d.ts +139 -0
- package/dist/contract/runs.d.ts +81 -0
- package/dist/core/agent-profiles.d.ts +15 -4
- package/dist/core/agent-profiles.js +22 -8
- package/dist/core/agent-profiles.js.map +1 -1
- package/dist/core/opencode-server-runner.js +71 -11
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/secret-redaction.d.ts +7 -1
- package/dist/core/secret-redaction.js +44 -10
- package/dist/core/secret-redaction.js.map +1 -1
- package/dist/index.js +138 -27
- package/dist/index.js.map +1 -1
- package/dist/machine-identity.d.ts +66 -0
- package/dist/machine-identity.js +96 -0
- package/dist/machine-identity.js.map +1 -0
- package/dist/mcp/adapters/claude-code.d.ts +41 -0
- package/dist/mcp/adapters/claude-code.js +40 -0
- package/dist/mcp/adapters/claude-code.js.map +1 -0
- package/dist/mcp/adapters/codex.d.ts +140 -0
- package/dist/mcp/adapters/codex.js +323 -0
- package/dist/mcp/adapters/codex.js.map +1 -0
- package/dist/mcp/adapters/opencode.d.ts +148 -0
- package/dist/mcp/adapters/opencode.js +528 -0
- package/dist/mcp/adapters/opencode.js.map +1 -0
- package/dist/mcp/adapters/pi-link.d.ts +102 -0
- package/dist/mcp/adapters/pi-link.js +235 -0
- package/dist/mcp/adapters/pi-link.js.map +1 -0
- package/dist/mcp/adapters/pi.d.ts +188 -0
- package/dist/mcp/adapters/pi.js +418 -0
- package/dist/mcp/adapters/pi.js.map +1 -0
- package/dist/mcp/api-reference.d.ts +26 -0
- package/dist/mcp/api-reference.js +133 -0
- package/dist/mcp/api-reference.js.map +1 -0
- package/dist/mcp/audit-trail.d.ts +162 -0
- package/dist/mcp/audit-trail.js +306 -0
- package/dist/mcp/audit-trail.js.map +1 -0
- package/dist/mcp/bridge.d.ts +81 -0
- package/dist/mcp/bridge.js +407 -0
- package/dist/mcp/bridge.js.map +1 -0
- package/dist/mcp/connection-file.d.ts +49 -0
- package/dist/mcp/connection-file.js +63 -0
- package/dist/mcp/connection-file.js.map +1 -0
- package/dist/mcp/echo-guard.d.ts +94 -0
- package/dist/mcp/echo-guard.js +160 -0
- package/dist/mcp/echo-guard.js.map +1 -0
- package/dist/mcp/event-catalog.d.ts +120 -0
- package/dist/mcp/event-catalog.js +306 -0
- package/dist/mcp/event-catalog.js.map +1 -0
- package/dist/mcp/event-controller.d.ts +230 -0
- package/dist/mcp/event-controller.js +596 -0
- package/dist/mcp/event-controller.js.map +1 -0
- package/dist/mcp/event-journal.d.ts +57 -0
- package/dist/mcp/event-journal.js +423 -0
- package/dist/mcp/event-journal.js.map +1 -0
- package/dist/mcp/index.d.ts +63 -0
- package/dist/mcp/index.js +386 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/ipc.d.ts +202 -0
- package/dist/mcp/ipc.js +206 -0
- package/dist/mcp/ipc.js.map +1 -0
- package/dist/mcp/leader-delivery.d.ts +119 -0
- package/dist/mcp/leader-delivery.js +450 -0
- package/dist/mcp/leader-delivery.js.map +1 -0
- package/dist/mcp/operation-receipts.d.ts +210 -0
- package/dist/mcp/operation-receipts.js +723 -0
- package/dist/mcp/operation-receipts.js.map +1 -0
- package/dist/mcp/project-catalogs.d.ts +23 -0
- package/dist/mcp/project-catalogs.js +25 -0
- package/dist/mcp/project-catalogs.js.map +1 -0
- package/dist/mcp/project-leaders.d.ts +26 -0
- package/dist/mcp/project-leaders.js +17 -0
- package/dist/mcp/project-leaders.js.map +1 -0
- package/dist/mcp/protocol.d.ts +50 -0
- package/dist/mcp/protocol.js +47 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/reconnect.d.ts +297 -0
- package/dist/mcp/reconnect.js +465 -0
- package/dist/mcp/reconnect.js.map +1 -0
- package/dist/mcp/resource-ownership.d.ts +228 -0
- package/dist/mcp/resource-ownership.js +390 -0
- package/dist/mcp/resource-ownership.js.map +1 -0
- package/dist/mcp/service-adapter.d.ts +16488 -0
- package/dist/mcp/service-adapter.js +148 -0
- package/dist/mcp/service-adapter.js.map +1 -0
- package/dist/mcp/service.d.ts +83 -0
- package/dist/mcp/service.js +233 -0
- package/dist/mcp/service.js.map +1 -0
- package/dist/mcp/session-binding.d.ts +105 -0
- package/dist/mcp/session-binding.js +163 -0
- package/dist/mcp/session-binding.js.map +1 -0
- package/dist/mcp/stale-write.d.ts +145 -0
- package/dist/mcp/stale-write.js +219 -0
- package/dist/mcp/stale-write.js.map +1 -0
- package/dist/mcp/tool.d.ts +48 -0
- package/dist/mcp/tool.js +24 -0
- package/dist/mcp/tool.js.map +1 -0
- package/dist/mcp/tools/discovery.d.ts +40 -0
- package/dist/mcp/tools/discovery.js +232 -0
- package/dist/mcp/tools/discovery.js.map +1 -0
- package/dist/mcp/tools/execution-control.d.ts +171 -0
- package/dist/mcp/tools/execution-control.js +513 -0
- package/dist/mcp/tools/execution-control.js.map +1 -0
- package/dist/mcp/tools/handoff-git.d.ts +26 -0
- package/dist/mcp/tools/handoff-git.js +544 -0
- package/dist/mcp/tools/handoff-git.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +2 -0
- package/dist/mcp/tools/index.js +23 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/leader-events.d.ts +46 -0
- package/dist/mcp/tools/leader-events.js +126 -0
- package/dist/mcp/tools/leader-events.js.map +1 -0
- package/dist/mcp/tools/local-handoff.d.ts +102 -0
- package/dist/mcp/tools/local-handoff.js +306 -0
- package/dist/mcp/tools/local-handoff.js.map +1 -0
- package/dist/mcp/tools/project-config.d.ts +340 -0
- package/dist/mcp/tools/project-config.js +1075 -0
- package/dist/mcp/tools/project-config.js.map +1 -0
- package/dist/mcp/tools/results-evidence.d.ts +112 -0
- package/dist/mcp/tools/results-evidence.js +1045 -0
- package/dist/mcp/tools/results-evidence.js.map +1 -0
- package/dist/mcp/tools/task-create.d.ts +70 -0
- package/dist/mcp/tools/task-create.js +473 -0
- package/dist/mcp/tools/task-create.js.map +1 -0
- package/dist/mcp/tools/task-reads.d.ts +102 -0
- package/dist/mcp/tools/task-reads.js +689 -0
- package/dist/mcp/tools/task-reads.js.map +1 -0
- package/dist/mcp/tools/work-organisation.d.ts +2 -0
- package/dist/mcp/tools/work-organisation.js +502 -0
- package/dist/mcp/tools/work-organisation.js.map +1 -0
- package/dist/paths.d.ts +17 -7
- package/dist/paths.js +18 -8
- package/dist/paths.js.map +1 -1
- package/dist/runs/project-writer.js +76 -11
- package/dist/runs/project-writer.js.map +1 -1
- package/dist/runs/retention.d.ts +25 -2
- package/dist/runs/retention.js +63 -2
- package/dist/runs/retention.js.map +1 -1
- package/dist/server/forge/github.js +44 -0
- package/dist/server/forge/github.js.map +1 -1
- package/dist/server/forge/types.d.ts +16 -0
- package/dist/server/project-context.d.ts +81 -8
- package/dist/server/project-context.js +143 -35
- package/dist/server/project-context.js.map +1 -1
- package/dist/server/server.d.ts +1050 -53
- package/dist/server/server.js +326 -120
- package/dist/server/server.js.map +1 -1
- package/dist/server/validators.d.ts +26 -6
- package/dist/server/validators.js +17 -0
- package/dist/server/validators.js.map +1 -1
- package/dist/skills-remote.js +64 -6
- package/dist/skills-remote.js.map +1 -1
- package/dist/workflows/run.d.ts +277 -12
- package/dist/workflows/run.js +599 -79
- package/dist/workflows/run.js.map +1 -1
- package/dist/workspace/agent-profiles.d.ts +30 -3
- package/dist/workspace/agent-profiles.js +39 -4
- package/dist/workspace/agent-profiles.js.map +1 -1
- package/dist/workspace/config.js +25 -4
- package/dist/workspace/config.js.map +1 -1
- package/dist/workspace/project-owner.d.ts +210 -0
- package/dist/workspace/project-owner.js +518 -0
- package/dist/workspace/project-owner.js.map +1 -0
- package/package.json +5 -3
- package/scripts/pi-leader-extension.ts +420 -0
- package/scripts/sync-readme.mjs +83 -2
- package/web/dist/assets/{alert-dialog-BVsVcbFy.js → alert-dialog-D6rP6d39.js} +1 -1
- package/web/dist/assets/arrow-down-DMOfFIzW.js +1 -0
- package/web/dist/assets/arrow-left-C4Ec2BUg.js +1 -0
- package/web/dist/assets/{centered-state-Djgly6Ni.js → centered-state-B0ZqrPaa.js} +12 -12
- package/web/dist/assets/chevron-right-mHJ-crvn.js +1 -0
- package/web/dist/assets/{collapsible-DZ4D-DHG.js → collapsible-DchEHgUM.js} +1 -1
- package/web/dist/assets/{commit-list-B-z1JL9G.js → commit-list-BpMim1Rv.js} +1 -1
- package/web/dist/assets/{compare-variants-CdS8r8E2.js → compare-variants-D5ItQbAq.js} +1 -1
- package/web/dist/assets/{diff-BKew9rQX.js → diff-HqqZ_WDR.js} +2 -2
- package/web/dist/assets/{diff-stat-D0mc5V6Z.js → diff-stat-NsU-3ecr.js} +1 -1
- package/web/dist/assets/{diff-view-xpIcuLIC.js → diff-view-B7c11Xux.js} +1 -1
- package/web/dist/assets/{dropdown-menu-CEQziH7X.js → dropdown-menu-CtTpnyod.js} +1 -1
- package/web/dist/assets/{editable-title-BCX3T2BY.js → editable-title-BXtuGQry.js} +1 -1
- package/web/dist/assets/{ellipsis-vertical-ByVdDc4z.js → ellipsis-vertical-MHtGZSH6.js} +1 -1
- package/web/dist/assets/{file-xBSB5hXO.js → file-DKLw5SOb.js} +1 -1
- package/web/dist/assets/{folder-CldgbZ5A.js → folder-Drw6-ufH.js} +1 -1
- package/web/dist/assets/{git-toolbar-BYlnf4qf.js → git-toolbar-BQH8bORV.js} +1 -1
- package/web/dist/assets/github-ynnpKFCJ.js +1 -0
- package/web/dist/assets/{image-preview-Cv5mZr0n.js → image-preview-DLhMN_R9.js} +1 -1
- package/web/dist/assets/index-BEsrNdXt.js +29 -0
- package/web/dist/assets/index-Da8DOBau.css +2 -0
- package/web/dist/assets/{markdown-CgEEE2ND.js → markdown-q365eN6Y.js} +1 -1
- package/web/dist/assets/{new-task-form-1r2bgsdD.js → new-task-form-CW-hNIWQ.js} +1 -1
- package/web/dist/assets/{pill-q-x22_ej.js → pill-B_TFulXa.js} +1 -1
- package/web/dist/assets/{project-router-VDN4jQM8.js → project-router-CLPc-ImZ.js} +1 -1
- package/web/dist/assets/{prompt-templates-BmZtCe-L.js → prompt-templates-CLc4RxyO.js} +1 -1
- package/web/dist/assets/{repo-git-C2On8SlI.js → repo-git-Is7R6-Tj.js} +1 -1
- package/web/dist/assets/{run-diff-vguEMJzh.js → run-diff-DHMvDlVo.js} +2 -2
- package/web/dist/assets/run-header-DvZJbQ8I.js +1 -0
- package/web/dist/assets/{search-x-QmhaAbg5.js → search-x-Ce2MMetu.js} +1 -1
- package/web/dist/assets/{skill-empty-hint-BrzUwByZ.js → skill-empty-hint-C_xCSvzB.js} +1 -1
- package/web/dist/assets/skills-CivqD4si.js +1 -0
- package/web/dist/assets/{sparkles-CP8QDOgX.js → sparkles-BCqPoj5g.js} +1 -1
- package/web/dist/assets/{square-terminal-CGypshSD.js → square-terminal-ikj5g-oK.js} +1 -1
- package/web/dist/assets/{tab-link-D4lFzzI1.js → tab-link-VsEjFV1Y.js} +1 -1
- package/web/dist/assets/{task-changes-6aopqAmV.js → task-changes-CH-E81-_.js} +1 -1
- package/web/dist/assets/{task-commits-u-dwaCyw.js → task-commits-DqfkMFxp.js} +1 -1
- package/web/dist/assets/{task-files-IMOZnIUK.js → task-files-D_nkHZ_a.js} +2 -2
- package/web/dist/assets/task-thread-bxQompxJ.js +9 -0
- package/web/dist/assets/{textarea-CyBCyKIk.js → textarea-xajuW1L_.js} +1 -1
- package/web/dist/assets/{thread-loading-Cuq2jchC.js → thread-loading-C3JQZbIE.js} +1 -1
- package/web/dist/assets/{trash-2-B6Dp3ZNs.js → trash-2-hJrBhpUD.js} +1 -1
- package/web/dist/assets/{triangle-alert-xBya8FUp.js → triangle-alert-D1u82y1a.js} +1 -1
- package/web/dist/assets/{upload-D6MXEB9p.js → upload-Bn6FBZ59.js} +1 -1
- package/web/dist/assets/{use-desktop-fLDKEJoB.js → use-desktop-DOIMfHfY.js} +1 -1
- package/web/dist/assets/{use-submit-shortcut-JTpNzU-u.js → use-submit-shortcut-Dj4DHTdE.js} +1 -1
- package/web/dist/assets/utils-YwBpOoRN.js +64 -0
- package/web/dist/assets/{workflows-BY3KTkFw.js → workflows-CTaAKz2m.js} +3 -3
- package/web/dist/assets/{zoomable-image-GTYwLtkS.js → zoomable-image-C1-6P3tg.js} +1 -1
- package/web/dist/index.html +23 -23
- package/web/dist/assets/arrow-down-CYgAlZtW.js +0 -1
- package/web/dist/assets/arrow-left-BOqE0a3k.js +0 -1
- package/web/dist/assets/chevron-right-Cc9BWnbN.js +0 -1
- package/web/dist/assets/github-CqGK62Lw.js +0 -1
- package/web/dist/assets/index-3nxVmdn5.css +0 -2
- package/web/dist/assets/index-qX7n11FX.js +0 -9
- package/web/dist/assets/refresh-cw-DcNCj2nu.js +0 -1
- package/web/dist/assets/run-header-DM7MiKj9.js +0 -1
- package/web/dist/assets/skills-Bj-uG_Hz.js +0 -1
- package/web/dist/assets/task-thread-CbMPmrWq.js +0 -9
- package/web/dist/assets/utils--z9hRtl3.js +0 -64
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/mcp/adapters/opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { type Socket } from 'node:net';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { PiRpcLink } from './pi.ts';
|
|
4
|
+
/**
|
|
5
|
+
* The thing that was missing (#330 WP2, QA round two): something that PRODUCES a `PiRpcLink`.
|
|
6
|
+
*
|
|
7
|
+
* `adapters/pi.ts` was complete, tested and evidenced, and never constructed in production, because
|
|
8
|
+
* `piReactionTarget` builds an adapter only from a live link and nothing in the repository made one.
|
|
9
|
+
* This module is that producer, and `leader-delivery.ts` is its caller.
|
|
10
|
+
*
|
|
11
|
+
* ## Why a socket the EXTENSION opens, rather than one xezar opens
|
|
12
|
+
*
|
|
13
|
+
* pi's RPC is stdio-only and spawn-only — no port, no socket, no attach (`pi --help` and
|
|
14
|
+
* `docs/rpc.md` on 0.85.1, re-confirmed twice) — and xezar starts no agent process for a leader
|
|
15
|
+
* (owner decision on #311). So the only way into a pi the PERSON runs is from inside it: a pi
|
|
16
|
+
* extension, which may call `pi.sendUserMessage(…)` — documented "Always triggers a turn" — and
|
|
17
|
+
* which runs unsandboxed and may therefore open a socket (`docs/security.md` § No Built-in Sandbox;
|
|
18
|
+
* the already-required `pi-mcp-adapter` opens one today).
|
|
19
|
+
*
|
|
20
|
+
* Given that, the extension is the side that has an address to offer, so IT listens and xezar dials.
|
|
21
|
+
* Three things follow, all of them deliberate:
|
|
22
|
+
*
|
|
23
|
+
* - **xezar opens no new listener.** § Zero config asks that a feature widening exposure be opt-in;
|
|
24
|
+
* dialling a socket that only exists because the person installed and ran the extension is
|
|
25
|
+
* demand-driven by construction. Nothing listens on xezar's side, so there is nothing to secure.
|
|
26
|
+
* - **It is the same shape as OpenCode.** `attach` names a session the person runs. For OpenCode
|
|
27
|
+
* that address is a URL they paste; for pi it is a descriptor the extension writes into the
|
|
28
|
+
* project's own data directory, so the person pastes nothing (§ Zero config: discover it).
|
|
29
|
+
* - **Absent means exactly today's behaviour.** No extension, no descriptor, no link — and
|
|
30
|
+
* `piReactionTarget` answers with the recoverable `pi-not-addressable` blocker, unchanged. This
|
|
31
|
+
* module can only ever ADD a working path; it can never take the old one away.
|
|
32
|
+
*
|
|
33
|
+
* ## Trust
|
|
34
|
+
*
|
|
35
|
+
* The descriptor is read ONLY from the project's own `dataDir`, which is xezar's own state directory
|
|
36
|
+
* (`<repo>/.local/xezar`, gitignored, written by this service). A socket path is taken from it and
|
|
37
|
+
* dialled; nothing else in the file reaches a decision. That is the same trust the MCP connection
|
|
38
|
+
* file already has, in the same directory, and it is why the path is never accepted from a request.
|
|
39
|
+
*
|
|
40
|
+
* Keeping other local accounts OFF that socket is the extension's job, not this file's, and an
|
|
41
|
+
* earlier version of this comment claimed it wrongly: it said the socket "lives in a directory only
|
|
42
|
+
* this user can enter", which on Linux with no `TMPDIR` was `/tmp` at mode `1777` and was false (QA
|
|
43
|
+
* on #358). The extension now creates its own `0700` directory and puts the socket inside — the
|
|
44
|
+
* DIRECTORY is the portable guard, because Linux enforces permissions on a Unix socket and macOS and
|
|
45
|
+
* the BSDs do not. See `scripts/pi-leader-extension.ts` § `makePrivateSocketDir`.
|
|
46
|
+
*/
|
|
47
|
+
/** Additive changes keep version 1 (N-08); an incompatible one bumps it. */
|
|
48
|
+
export declare const PI_LEADER_SCHEMA_VERSION = 1;
|
|
49
|
+
export declare const PI_LEADER_FILE = "pi-leader.json";
|
|
50
|
+
/**
|
|
51
|
+
* What the extension writes once its socket really listens, so the file never names nothing — the
|
|
52
|
+
* same ordering rule D-04 gives the MCP connection file. No secret: which socket the peer reached is
|
|
53
|
+
* the binding (D-01 § 6), and the socket lives in a directory only this user can enter.
|
|
54
|
+
*/
|
|
55
|
+
export declare const piLeaderDescriptorSchema: z.ZodObject<{
|
|
56
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
57
|
+
session: z.ZodObject<{
|
|
58
|
+
pid: z.ZodNumber;
|
|
59
|
+
startedAt: z.ZodString;
|
|
60
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
endpoint: z.ZodObject<{
|
|
63
|
+
socket: z.ZodString;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
export type PiLeaderDescriptor = z.infer<typeof piLeaderDescriptorSchema>;
|
|
67
|
+
export declare function piLeaderPath(dataDir: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Read the descriptor, or say why there is none. Never throws: every failure is a reason a person
|
|
70
|
+
* can act on, because this runs on the `attach` path and the answer is shown to them.
|
|
71
|
+
*/
|
|
72
|
+
export declare function readPiLeaderDescriptor(dataDir: string): {
|
|
73
|
+
ok: true;
|
|
74
|
+
descriptor: PiLeaderDescriptor;
|
|
75
|
+
} | {
|
|
76
|
+
ok: false;
|
|
77
|
+
reason: string;
|
|
78
|
+
};
|
|
79
|
+
export interface PiLeaderLink extends PiRpcLink {
|
|
80
|
+
/** Hang up. The pi process and its session belong to the person; only this socket is dropped. */
|
|
81
|
+
close(): void;
|
|
82
|
+
}
|
|
83
|
+
export interface ConnectPiLeaderOptions {
|
|
84
|
+
/** How long one command may wait for its `response` before it is treated as lost. */
|
|
85
|
+
readonly requestTimeoutMs?: number;
|
|
86
|
+
readonly warn?: (message: string) => void;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Dial the extension's socket and present it as a `PiRpcLink`.
|
|
90
|
+
*
|
|
91
|
+
* The wire is pi's OWN RPC vocabulary — `{id, type:'prompt'|'steer'|'get_state'|'get_messages'}` out,
|
|
92
|
+
* `{type:'response', id, success, data}` and pi's event frames back — so the adapter above is
|
|
93
|
+
* unchanged by this file existing, and a future transport can replace it without touching either.
|
|
94
|
+
* Framing follows `docs/rpc.md`: split on `\n` only, tolerate a trailing `\r`, and never a generic
|
|
95
|
+
* line reader (Node's `readline` also splits on U+2028/U+2029, which are legal inside JSON strings).
|
|
96
|
+
*/
|
|
97
|
+
export declare function connectPiLeaderLink(descriptor: PiLeaderDescriptor, opts?: ConnectPiLeaderOptions): PiLeaderLink;
|
|
98
|
+
/**
|
|
99
|
+
* The half that has nothing to do with `node:net`, so a test can drive it with a pair of pipes and
|
|
100
|
+
* still exercise the real framing, the real correlation and the real close semantics.
|
|
101
|
+
*/
|
|
102
|
+
export declare function wrapPiLeaderSocket(socket: Socket, opts?: ConnectPiLeaderOptions): PiLeaderLink;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { createConnection } from 'node:net';
|
|
2
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
/**
|
|
6
|
+
* The thing that was missing (#330 WP2, QA round two): something that PRODUCES a `PiRpcLink`.
|
|
7
|
+
*
|
|
8
|
+
* `adapters/pi.ts` was complete, tested and evidenced, and never constructed in production, because
|
|
9
|
+
* `piReactionTarget` builds an adapter only from a live link and nothing in the repository made one.
|
|
10
|
+
* This module is that producer, and `leader-delivery.ts` is its caller.
|
|
11
|
+
*
|
|
12
|
+
* ## Why a socket the EXTENSION opens, rather than one xezar opens
|
|
13
|
+
*
|
|
14
|
+
* pi's RPC is stdio-only and spawn-only — no port, no socket, no attach (`pi --help` and
|
|
15
|
+
* `docs/rpc.md` on 0.85.1, re-confirmed twice) — and xezar starts no agent process for a leader
|
|
16
|
+
* (owner decision on #311). So the only way into a pi the PERSON runs is from inside it: a pi
|
|
17
|
+
* extension, which may call `pi.sendUserMessage(…)` — documented "Always triggers a turn" — and
|
|
18
|
+
* which runs unsandboxed and may therefore open a socket (`docs/security.md` § No Built-in Sandbox;
|
|
19
|
+
* the already-required `pi-mcp-adapter` opens one today).
|
|
20
|
+
*
|
|
21
|
+
* Given that, the extension is the side that has an address to offer, so IT listens and xezar dials.
|
|
22
|
+
* Three things follow, all of them deliberate:
|
|
23
|
+
*
|
|
24
|
+
* - **xezar opens no new listener.** § Zero config asks that a feature widening exposure be opt-in;
|
|
25
|
+
* dialling a socket that only exists because the person installed and ran the extension is
|
|
26
|
+
* demand-driven by construction. Nothing listens on xezar's side, so there is nothing to secure.
|
|
27
|
+
* - **It is the same shape as OpenCode.** `attach` names a session the person runs. For OpenCode
|
|
28
|
+
* that address is a URL they paste; for pi it is a descriptor the extension writes into the
|
|
29
|
+
* project's own data directory, so the person pastes nothing (§ Zero config: discover it).
|
|
30
|
+
* - **Absent means exactly today's behaviour.** No extension, no descriptor, no link — and
|
|
31
|
+
* `piReactionTarget` answers with the recoverable `pi-not-addressable` blocker, unchanged. This
|
|
32
|
+
* module can only ever ADD a working path; it can never take the old one away.
|
|
33
|
+
*
|
|
34
|
+
* ## Trust
|
|
35
|
+
*
|
|
36
|
+
* The descriptor is read ONLY from the project's own `dataDir`, which is xezar's own state directory
|
|
37
|
+
* (`<repo>/.local/xezar`, gitignored, written by this service). A socket path is taken from it and
|
|
38
|
+
* dialled; nothing else in the file reaches a decision. That is the same trust the MCP connection
|
|
39
|
+
* file already has, in the same directory, and it is why the path is never accepted from a request.
|
|
40
|
+
*
|
|
41
|
+
* Keeping other local accounts OFF that socket is the extension's job, not this file's, and an
|
|
42
|
+
* earlier version of this comment claimed it wrongly: it said the socket "lives in a directory only
|
|
43
|
+
* this user can enter", which on Linux with no `TMPDIR` was `/tmp` at mode `1777` and was false (QA
|
|
44
|
+
* on #358). The extension now creates its own `0700` directory and puts the socket inside — the
|
|
45
|
+
* DIRECTORY is the portable guard, because Linux enforces permissions on a Unix socket and macOS and
|
|
46
|
+
* the BSDs do not. See `scripts/pi-leader-extension.ts` § `makePrivateSocketDir`.
|
|
47
|
+
*/
|
|
48
|
+
/** Additive changes keep version 1 (N-08); an incompatible one bumps it. */
|
|
49
|
+
export const PI_LEADER_SCHEMA_VERSION = 1;
|
|
50
|
+
export const PI_LEADER_FILE = 'pi-leader.json';
|
|
51
|
+
/**
|
|
52
|
+
* What the extension writes once its socket really listens, so the file never names nothing — the
|
|
53
|
+
* same ordering rule D-04 gives the MCP connection file. No secret: which socket the peer reached is
|
|
54
|
+
* the binding (D-01 § 6), and the socket lives in a directory only this user can enter.
|
|
55
|
+
*/
|
|
56
|
+
export const piLeaderDescriptorSchema = z.object({
|
|
57
|
+
schemaVersion: z.literal(PI_LEADER_SCHEMA_VERSION),
|
|
58
|
+
session: z.object({
|
|
59
|
+
pid: z.number().int().positive(),
|
|
60
|
+
startedAt: z.string(),
|
|
61
|
+
/** pi's own session id, for the cockpit to show. Never the identity anything trusts. */
|
|
62
|
+
sessionId: z.string().max(200).optional(),
|
|
63
|
+
}),
|
|
64
|
+
endpoint: z.object({ socket: z.string().min(1).max(1024) }),
|
|
65
|
+
});
|
|
66
|
+
export function piLeaderPath(dataDir) {
|
|
67
|
+
return join(dataDir, PI_LEADER_FILE);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Read the descriptor, or say why there is none. Never throws: every failure is a reason a person
|
|
71
|
+
* can act on, because this runs on the `attach` path and the answer is shown to them.
|
|
72
|
+
*/
|
|
73
|
+
export function readPiLeaderDescriptor(dataDir) {
|
|
74
|
+
let raw;
|
|
75
|
+
try {
|
|
76
|
+
raw = readFileSync(piLeaderPath(dataDir), 'utf8');
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { ok: false, reason: 'no pi leader has announced itself to this project' };
|
|
80
|
+
}
|
|
81
|
+
let parsed;
|
|
82
|
+
try {
|
|
83
|
+
parsed = JSON.parse(raw);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return { ok: false, reason: `${PI_LEADER_FILE} is not valid JSON` };
|
|
87
|
+
}
|
|
88
|
+
const result = piLeaderDescriptorSchema.safeParse(parsed);
|
|
89
|
+
if (!result.success)
|
|
90
|
+
return { ok: false, reason: `${PI_LEADER_FILE} is not a descriptor this xezar understands` };
|
|
91
|
+
// A descriptor whose socket is gone is a pi that exited without cleaning up. Say that, rather than
|
|
92
|
+
// letting the dial fail with an errno the person cannot read.
|
|
93
|
+
try {
|
|
94
|
+
if (!statSync(result.data.endpoint.socket).isSocket()) {
|
|
95
|
+
return { ok: false, reason: 'the pi leader socket named in ' + PI_LEADER_FILE + ' is not a socket' };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return { ok: false, reason: 'the pi leader that wrote ' + PI_LEADER_FILE + ' is gone (its socket no longer exists)' };
|
|
100
|
+
}
|
|
101
|
+
return { ok: true, descriptor: result.data };
|
|
102
|
+
}
|
|
103
|
+
/** One line is one JSON value, LF-delimited — pi's own RPC framing (`docs/rpc.md` § Framing). */
|
|
104
|
+
const MAX_LINE_BYTES = 1_000_000;
|
|
105
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
106
|
+
/**
|
|
107
|
+
* Dial the extension's socket and present it as a `PiRpcLink`.
|
|
108
|
+
*
|
|
109
|
+
* The wire is pi's OWN RPC vocabulary — `{id, type:'prompt'|'steer'|'get_state'|'get_messages'}` out,
|
|
110
|
+
* `{type:'response', id, success, data}` and pi's event frames back — so the adapter above is
|
|
111
|
+
* unchanged by this file existing, and a future transport can replace it without touching either.
|
|
112
|
+
* Framing follows `docs/rpc.md`: split on `\n` only, tolerate a trailing `\r`, and never a generic
|
|
113
|
+
* line reader (Node's `readline` also splits on U+2028/U+2029, which are legal inside JSON strings).
|
|
114
|
+
*/
|
|
115
|
+
export function connectPiLeaderLink(descriptor, opts = {}) {
|
|
116
|
+
const socket = createConnection({ path: descriptor.endpoint.socket });
|
|
117
|
+
socket.setNoDelay(true);
|
|
118
|
+
socket.setEncoding('utf8');
|
|
119
|
+
return wrapPiLeaderSocket(socket, opts);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The half that has nothing to do with `node:net`, so a test can drive it with a pair of pipes and
|
|
123
|
+
* still exercise the real framing, the real correlation and the real close semantics.
|
|
124
|
+
*/
|
|
125
|
+
export function wrapPiLeaderSocket(socket, opts = {}) {
|
|
126
|
+
const timeoutMs = opts.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
127
|
+
const listeners = new Set();
|
|
128
|
+
const pending = new Map();
|
|
129
|
+
let closed = false;
|
|
130
|
+
let nextId = 0;
|
|
131
|
+
let buffer = '';
|
|
132
|
+
const failAll = (err) => {
|
|
133
|
+
for (const [, entry] of pending) {
|
|
134
|
+
clearTimeout(entry.timer);
|
|
135
|
+
entry.reject(err);
|
|
136
|
+
}
|
|
137
|
+
pending.clear();
|
|
138
|
+
};
|
|
139
|
+
const shutdown = (err) => {
|
|
140
|
+
if (closed)
|
|
141
|
+
return;
|
|
142
|
+
closed = true;
|
|
143
|
+
failAll(err);
|
|
144
|
+
listeners.clear();
|
|
145
|
+
socket.destroy();
|
|
146
|
+
};
|
|
147
|
+
socket.on('data', (chunk) => {
|
|
148
|
+
buffer += chunk;
|
|
149
|
+
// A peer that never sends a newline must not grow this without bound.
|
|
150
|
+
if (buffer.length > MAX_LINE_BYTES) {
|
|
151
|
+
shutdown(new Error('the pi leader sent a line longer than the protocol allows'));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
let nl;
|
|
155
|
+
while ((nl = buffer.indexOf('\n')) >= 0) {
|
|
156
|
+
const line = buffer.slice(0, nl).replace(/\r$/, '');
|
|
157
|
+
buffer = buffer.slice(nl + 1);
|
|
158
|
+
if (!line.trim())
|
|
159
|
+
continue;
|
|
160
|
+
let value;
|
|
161
|
+
try {
|
|
162
|
+
value = JSON.parse(line);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// One unreadable line is not a reason to drop a working leader; pi's own clients skip it.
|
|
166
|
+
opts.warn?.('[xez] a line from the pi leader was not JSON and was ignored');
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (typeof value !== 'object' || value === null)
|
|
170
|
+
continue;
|
|
171
|
+
const message = value;
|
|
172
|
+
const id = typeof message.id === 'string' ? message.id : undefined;
|
|
173
|
+
if (message.type === 'response' && id !== undefined) {
|
|
174
|
+
const entry = pending.get(id);
|
|
175
|
+
if (entry) {
|
|
176
|
+
pending.delete(id);
|
|
177
|
+
clearTimeout(entry.timer);
|
|
178
|
+
entry.resolve({
|
|
179
|
+
success: message.success === true,
|
|
180
|
+
...(isRecord(message.data) ? { data: message.data } : {}),
|
|
181
|
+
...(message.error === undefined ? {} : { error: message.error }),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
// Everything else is one of pi's events, passed through untouched: this file knows the
|
|
187
|
+
// framing, and `adapters/pi.ts` alone knows what the events MEAN.
|
|
188
|
+
for (const listener of [...listeners])
|
|
189
|
+
listener(message);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
socket.on('error', (err) => shutdown(err));
|
|
193
|
+
socket.on('close', () => shutdown(new Error('the pi leader closed its connection to xezar')));
|
|
194
|
+
return {
|
|
195
|
+
get closed() {
|
|
196
|
+
return closed || socket.destroyed;
|
|
197
|
+
},
|
|
198
|
+
subscribe(listener) {
|
|
199
|
+
listeners.add(listener);
|
|
200
|
+
return () => listeners.delete(listener);
|
|
201
|
+
},
|
|
202
|
+
async request(command) {
|
|
203
|
+
if (closed || socket.destroyed)
|
|
204
|
+
throw new Error('the pi leader link is closed');
|
|
205
|
+
const id = `xez-${++nextId}`;
|
|
206
|
+
return await new Promise((resolve, reject) => {
|
|
207
|
+
const timer = setTimeout(() => {
|
|
208
|
+
pending.delete(id);
|
|
209
|
+
// Deliberately a REJECT, not a failed response: "we do not know whether pi saw it" and
|
|
210
|
+
// "pi refused it" are different answers, and the adapter treats only the first as
|
|
211
|
+
// uncertain and re-reads the conversation before it decides (`#uncertain`).
|
|
212
|
+
reject(new Error('the pi leader did not answer in time'));
|
|
213
|
+
}, timeoutMs);
|
|
214
|
+
// `unref` so a hung leader can never hold the process open at shutdown.
|
|
215
|
+
timer.unref?.();
|
|
216
|
+
pending.set(id, { resolve, reject, timer });
|
|
217
|
+
try {
|
|
218
|
+
socket.write(`${JSON.stringify({ ...command, id })}\n`);
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
pending.delete(id);
|
|
222
|
+
clearTimeout(timer);
|
|
223
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
},
|
|
227
|
+
close() {
|
|
228
|
+
shutdown(new Error('xezar closed the pi leader link'));
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function isRecord(value) {
|
|
233
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=pi-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-link.js","sourceRoot":"","sources":["../../../src/mcp/adapters/pi-link.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { type McpJournalRow } from '../../contract/index.js';
|
|
2
|
+
import type { EventDispatch, ReactionAdapter } from '../event-controller.ts';
|
|
3
|
+
/**
|
|
4
|
+
* The pi reaction adapter (#330 WP2, Phase 6 of #67): the client-specific half the non-model event
|
|
5
|
+
* controller (#107, `event-controller.ts`) hands significant events to, for a leader running in pi.
|
|
6
|
+
* The runtime evidence is `docs/features/mcp-server/mcp-adapter-evidence-pi.md` (second half); every
|
|
7
|
+
* behavioural claim below names the scenario that measured it against pi 0.85.1.
|
|
8
|
+
*
|
|
9
|
+
* A CONTROL ADAPTER, NOT A RUNNER. It implements `ReactionAdapter` and adds no backend: it starts no
|
|
10
|
+
* process, owns no session, writes no file and reads no environment variable. `core/pi-runner.ts` is
|
|
11
|
+
* the implementation anchor for speaking pi's RPC (same protocol, `docs/rpc.md`); it is not evidence
|
|
12
|
+
* that this event flow works — the evidence record is. No pi type leaves this file: the controller
|
|
13
|
+
* sees `deliver` and `heartbeat`, and the rest of xezar sees `PiReactionTarget`.
|
|
14
|
+
*
|
|
15
|
+
* THE DELIVERY HIERARCHY (requirements § 12), in order and not reorderable:
|
|
16
|
+
* 1. Native mechanism — NOT ADOPTED. The bridge advertises tools only and sends no notification,
|
|
17
|
+
* and against a stub that did, `notifications/resources/updated` and `notifications/message`
|
|
18
|
+
* started no pi turn (#330 run A; D-05 § 4 for the other three). pi sends no `resources/subscribe`.
|
|
19
|
+
* 2. The official programmatic session interface — ADOPTED: pi's RPC `prompt` when pi is idle, and
|
|
20
|
+
* `steer` when it is busy. Executed on this host (scenario `rpc-probe`): an idle `prompt` put the
|
|
21
|
+
* text into the conversation and the very next model request carried it; a plain `prompt` sent
|
|
22
|
+
* during a turn was REFUSED (`Agent is already processing. Specify streamingBehavior …`); the
|
|
23
|
+
* same text sent as `steer` was queued, delivered when the running turn's tool calls finished,
|
|
24
|
+
* and carried by the following model request. The running turn was not cut short.
|
|
25
|
+
* 3. Terminal text input — REFUSED. Tier 2 works, and nothing here simulates a keystroke.
|
|
26
|
+
*
|
|
27
|
+
* WHOSE PI PROCESS. Only one whose RPC the CALLER already owns, handed in as `PiRpcLink`. This
|
|
28
|
+
* adapter never spawns pi, because xezar starts no agent process for a leader (owner decision on
|
|
29
|
+
* #311), and it never opens a transport of its own.
|
|
30
|
+
*
|
|
31
|
+
* WHO CONSTRUCTS IT, AND FROM WHAT. `LeaderDelivery.#piTarget()`, on
|
|
32
|
+
* `{action:'attach', client:'pi'}`. It gets the link from `adapters/pi-link.ts`, which reads the
|
|
33
|
+
* descriptor xezar's pi leader extension writes into the project's data directory and dials the
|
|
34
|
+
* socket named there. pi's own RPC is stdio-only and spawn-only — no port, no socket, no attach
|
|
35
|
+
* (`pi --help`, `docs/rpc.md` on 0.85.1) — so the address cannot come from outside pi; it comes from
|
|
36
|
+
* INSIDE it, where `ExtensionAPI.sendUserMessage` ("Always triggers a turn") can be reached. Nothing
|
|
37
|
+
* xezar can send over MCP starts a pi turn, so that extension is the only route, and it is the one
|
|
38
|
+
* taken (`scripts/pi-leader-extension.ts`, evidence record § "A-19 for pi: CLOSED").
|
|
39
|
+
*
|
|
40
|
+
* WITH NO EXTENSION RUNNING there is no descriptor and no link, and `piReactionTarget()` answers with
|
|
41
|
+
* the recoverable `pi-not-addressable` blocker naming why — the same standing a Claude Code or Codex
|
|
42
|
+
* session in a terminal has (`leader-delivery.ts`): the rows stay in the journal and the leader reads
|
|
43
|
+
* them with `leader_events`. Push delivery to pi is opt-in, and absent is the pre-extension behaviour
|
|
44
|
+
* unchanged.
|
|
45
|
+
*
|
|
46
|
+
* DELIVERY IS NOT REACTION (F-20, D-05 § 6.6). `deliver` resolves once pi ANSWERED the `prompt` or
|
|
47
|
+
* `steer` with `success: true`: the client application has the rows. The reaction is reported
|
|
48
|
+
* separately through `onReaction`, and only when pi says so — the submission's own text appearing as
|
|
49
|
+
* a `user` message in the conversation (`message_start`/`message_end`). Measured: pi emits that
|
|
50
|
+
* message immediately before the model request that carries it, for an idle `prompt` and for a
|
|
51
|
+
* steered message alike, and never for one that is still sitting in the steering queue. It is
|
|
52
|
+
* therefore observed, never inferred from the `response`.
|
|
53
|
+
*
|
|
54
|
+
* SAFETY RULES, each measured against pi 0.85.1:
|
|
55
|
+
* - Role instruction on EVERY submission. pi keeps no system prompt in its session file, so a
|
|
56
|
+
* resumed session loses `--append-system-prompt` (evidence record, prompt persistence: FAIL). The
|
|
57
|
+
* adapter does not start pi and cannot pass that flag, so it carries xezar's own role text in the
|
|
58
|
+
* message it sends, every time. It is xezar's text, never read from a project file the leader can
|
|
59
|
+
* edit (§ 12). Prompt text is still not enforcement.
|
|
60
|
+
* - Never into a running turn as a plain `prompt`. pi refuses it outright, so the adapter sends
|
|
61
|
+
* `steer` when pi is busy AND falls back to `steer` when a `prompt` is refused anyway. That
|
|
62
|
+
* fallback covers only ONE direction of a stale `busy`, and an earlier version of this comment
|
|
63
|
+
* claimed it covered both (QA on #358). The other direction — believed busy, really idle — is
|
|
64
|
+
* TRANSPORT-DEPENDENT, and an earlier version of this comment stated the worse half as though it
|
|
65
|
+
* were the only half (QA on #358, finding 2). Both halves, measured in one run against real pi
|
|
66
|
+
* 0.85.1 (`idle-steer-result.json`, M1/M2):
|
|
67
|
+
* · Over the leader extension, WHICH IS THE ONLY TRANSPORT ANYTHING IN PRODUCTION USES — the
|
|
68
|
+
* one `PiRpcLink` is built by `LeaderDelivery.#piTarget()` from `pi-link.ts`, which dials the
|
|
69
|
+
* extension's socket — an idle `steer` REACHES THE MODEL AT ONCE: `success: true`, one model
|
|
70
|
+
* request carrying the text, `pendingMessageCount` still 0. The extension turns `steer` into
|
|
71
|
+
* `sendUserMessage(text, { deliverAs: 'steer' })`, and `deliverAs` only chooses how a message
|
|
72
|
+
* enters a turn that is already RUNNING; with pi idle it starts one.
|
|
73
|
+
* · Over pi's raw stdio RPC, which xezar never speaks (it starts no pi and has no other way in),
|
|
74
|
+
* the same command is accepted and PARKED: zero model requests, `pendingMessageCount` 0 -> 1,
|
|
75
|
+
* and the text waits for the person's next turn.
|
|
76
|
+
* So parking is not a property of this feature, and the confirmation below is not what saves it
|
|
77
|
+
* from one. The confirmation stays anyway, and is cheap: it is one `get_state` that makes the
|
|
78
|
+
* adapter correct over a transport that parks, and `success` is acceptance and never hand-over on
|
|
79
|
+
* any transport. A steer this adapter cannot confirm reached the model is never reported as handed
|
|
80
|
+
* over, so the controller hands the row over again. See `#submit`.
|
|
81
|
+
* - Never two turns for one row. Rows already submitted are skipped: from memory within this
|
|
82
|
+
* adapter's life, and from pi's own conversation (`get_messages`, the marker this adapter writes
|
|
83
|
+
* into its text) on the first delivery and after any attempt whose answer was lost — so a
|
|
84
|
+
* restart, or a lost response, does not ask the model twice.
|
|
85
|
+
* - Never a second leader. It speaks only to the link it was given, and creates nothing.
|
|
86
|
+
*
|
|
87
|
+
* AGENTS.md / #329: `PI_CODING_AGENT_DIR` relocates pi's home and its credentials. This module reads
|
|
88
|
+
* no environment variable and sets none, and imports neither `node:fs` nor `node:child_process` —
|
|
89
|
+
* the test file asserts all three.
|
|
90
|
+
*/
|
|
91
|
+
/** One line pi writes on its RPC stdout: a `response` to a command, or an event. */
|
|
92
|
+
export interface PiRpcMessage {
|
|
93
|
+
readonly type?: unknown;
|
|
94
|
+
readonly [key: string]: unknown;
|
|
95
|
+
}
|
|
96
|
+
/** pi's answer to one command (`docs/rpc.md`): `success` is acceptance, not the turn's outcome. */
|
|
97
|
+
export interface PiRpcResponse {
|
|
98
|
+
readonly success: boolean;
|
|
99
|
+
readonly data?: Record<string, unknown>;
|
|
100
|
+
readonly error?: unknown;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* pi's RPC as this adapter uses it: a JSONL command in, pi's event stream out, over a process the
|
|
104
|
+
* CALLER owns. Deliberately transport-free — the adapter never learns whether the stdio behind it is
|
|
105
|
+
* a pipe, a socket or a test double, which is what keeps `node:child_process` out of this file.
|
|
106
|
+
*/
|
|
107
|
+
export interface PiRpcLink {
|
|
108
|
+
/** Send one command and resolve with pi's `response` frame for it. Rejects if it cannot be sent. */
|
|
109
|
+
request(command: Record<string, unknown>): Promise<PiRpcResponse>;
|
|
110
|
+
/** Every line pi writes. Returns the unsubscribe. */
|
|
111
|
+
subscribe(listener: (message: PiRpcMessage) => void): () => void;
|
|
112
|
+
readonly closed: boolean;
|
|
113
|
+
}
|
|
114
|
+
export type PiBlockerCode = 'pi-not-addressable' | 'pi-session-closed' | 'pi-refused' | 'pi-steer-parked';
|
|
115
|
+
/** Why no event can reach pi right now. Always recoverable: nothing is lost while it holds. */
|
|
116
|
+
export interface PiBlocker {
|
|
117
|
+
readonly code: PiBlockerCode;
|
|
118
|
+
readonly recoverable: true;
|
|
119
|
+
readonly message: string;
|
|
120
|
+
readonly fix: string;
|
|
121
|
+
}
|
|
122
|
+
export declare class PiDeliveryBlocked extends Error {
|
|
123
|
+
readonly blocker: PiBlocker;
|
|
124
|
+
constructor(code: PiBlockerCode, message: string, fix: string);
|
|
125
|
+
}
|
|
126
|
+
/** Where a project's leader events go in pi: a live RPC link, or a stated blocker. Never neither. */
|
|
127
|
+
export type PiReactionTarget = {
|
|
128
|
+
readonly kind: 'rpc';
|
|
129
|
+
readonly adapter: PiReactionAdapter;
|
|
130
|
+
} | {
|
|
131
|
+
readonly kind: 'blocked';
|
|
132
|
+
readonly blocker: PiBlocker;
|
|
133
|
+
};
|
|
134
|
+
export interface PiReactionAdapterOptions {
|
|
135
|
+
/** The pi RPC session this adapter speaks to. The caller owns it; this adapter never opens one. */
|
|
136
|
+
link: PiRpcLink;
|
|
137
|
+
/** The bound project. A dispatch for any other project is refused, never delivered. */
|
|
138
|
+
projectId: string;
|
|
139
|
+
/** xezar's role instruction, carried in every submission (§ 12: the leader cannot edit it). */
|
|
140
|
+
roleInstruction: string;
|
|
141
|
+
/** The reaction half of F-20: called once a model request really carried rows up to `journalSeq`. */
|
|
142
|
+
onReaction?: (journalSeq: number) => void;
|
|
143
|
+
/** The F-13 echo guard (D-05 § 6.3): true for an operation this leader has outstanding. */
|
|
144
|
+
isOwnOperation?: (operationId: string) => boolean;
|
|
145
|
+
}
|
|
146
|
+
/** What `status()` says: the route in use, or the blocker holding delivery. For the cockpit. */
|
|
147
|
+
export interface PiAdapterStatus {
|
|
148
|
+
readonly route: 'rpc-prompt' | 'blocked';
|
|
149
|
+
readonly blocker?: PiBlocker;
|
|
150
|
+
readonly submittedRows: number;
|
|
151
|
+
readonly turnsAwaited: number;
|
|
152
|
+
}
|
|
153
|
+
export declare class PiReactionAdapter implements ReactionAdapter {
|
|
154
|
+
#private;
|
|
155
|
+
readonly projectId: string;
|
|
156
|
+
constructor(opts: PiReactionAdapterOptions);
|
|
157
|
+
status(): PiAdapterStatus;
|
|
158
|
+
deliver(dispatch: EventDispatch, signal: AbortSignal): Promise<{
|
|
159
|
+
handedThrough: number | null;
|
|
160
|
+
}>;
|
|
161
|
+
/** Non-model liveness (N-06): pi's own session metadata. Starts no turn and reaches no model. */
|
|
162
|
+
heartbeat(signal: AbortSignal): Promise<void>;
|
|
163
|
+
/** Stop listening. The pi process and its session belong to whoever opened the link. */
|
|
164
|
+
close(): void;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Where a project's leader events go in pi. A live `link`: delivered through it. Absent or closed: a
|
|
168
|
+
* recoverable blocker the cockpit can show, naming WHY there is no link, because since `pi-link.ts`
|
|
169
|
+
* exists that is an answerable question — the leader extension is not running, or the pi that wrote
|
|
170
|
+
* the descriptor is gone — rather than the flat "pi has no address" it used to be. The rows stay in
|
|
171
|
+
* the journal either way, and the leader reads them with `leader_events`.
|
|
172
|
+
*/
|
|
173
|
+
export declare function piReactionTarget(opts: Omit<PiReactionAdapterOptions, 'link'> & {
|
|
174
|
+
link?: PiRpcLink;
|
|
175
|
+
unreachable?: string;
|
|
176
|
+
}): PiReactionTarget;
|
|
177
|
+
/**
|
|
178
|
+
* The text a pi leader receives for one dispatch. Pure: the same inputs always render the same text.
|
|
179
|
+
*
|
|
180
|
+
* It names xezar as the source and says what it is not, before any row — an event must never read as
|
|
181
|
+
* the user's instruction or approval (§ 12). The role instruction rides along because pi keeps no
|
|
182
|
+
* system prompt in a resumed session. Each row's summary is quoted as data, so text inside a summary
|
|
183
|
+
* cannot pose as the adapter's own framing; rows are the journal's own summaries, already scrubbed of
|
|
184
|
+
* secrets (F-15), never a payload. The marker line is how a later look at pi's conversation
|
|
185
|
+
* recognises this submission — `<eventId>@<ts>` per row, because `journalSeq` restarts in a recreated
|
|
186
|
+
* journal and the pair does not.
|
|
187
|
+
*/
|
|
188
|
+
export declare function renderPiDispatch(dispatch: EventDispatch, rows: readonly McpJournalRow[], roleInstruction: string, marker: string): string;
|