@fitchmultz/pi-subagents 0.0.0-stage → 0.44.5
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/CHANGELOG.md +1654 -0
- package/LICENSE +21 -0
- package/README.md +1533 -2
- package/agents/context-builder.md +97 -0
- package/agents/debugger.md +51 -0
- package/agents/delegate.md +13 -0
- package/agents/fixer.md +37 -0
- package/agents/oracle.md +71 -0
- package/agents/planner.md +72 -0
- package/agents/researcher.md +51 -0
- package/agents/reviewer-claude.md +69 -0
- package/agents/reviewer-gpt.md +68 -0
- package/agents/reviewer-ponytail.md +82 -0
- package/agents/reviewer-security.md +81 -0
- package/agents/reviewer.md +69 -0
- package/agents/scout.md +66 -0
- package/agents/ui-designer.md +51 -0
- package/agents/watcher.md +26 -0
- package/agents/worker.md +46 -0
- package/agents/writer.md +36 -0
- package/dist/agents/agent-management.js +923 -0
- package/dist/agents/agent-scope.js +7 -0
- package/dist/agents/agent-selection.js +20 -0
- package/dist/agents/agent-serializer.js +100 -0
- package/dist/agents/agents.js +752 -0
- package/dist/agents/chain-serializer.js +367 -0
- package/dist/agents/frontmatter.js +21 -0
- package/dist/agents/identity.js +29 -0
- package/dist/agents/skills.js +570 -0
- package/dist/extension/build-info.js +1 -0
- package/dist/extension/compact-tools.js +112 -0
- package/dist/extension/config.js +22 -0
- package/dist/extension/control-notices.js +29 -0
- package/dist/extension/doctor.js +143 -0
- package/dist/extension/fanout-child.js +326 -0
- package/dist/extension/index.js +577 -0
- package/dist/extension/schemas.js +416 -0
- package/dist/extension/tool-input.js +20 -0
- package/dist/extension/tool-result.js +14 -0
- package/dist/history/canonical-result.js +81 -0
- package/dist/history/database.js +72 -0
- package/dist/history/index.js +199 -0
- package/dist/history/ingest.js +468 -0
- package/dist/history/queries.js +350 -0
- package/dist/history/store.js +216 -0
- package/dist/history/types.js +4 -0
- package/dist/history/worker.js +466 -0
- package/dist/intercom/intercom-bridge.js +112 -0
- package/dist/intercom/live-intercom.js +94 -0
- package/dist/intercom/result-intercom.js +373 -0
- package/dist/pi-intercom/agent-dir.js +10 -0
- package/dist/pi-intercom/bridge.js +750 -0
- package/dist/pi-intercom/broker/broker.js +426 -0
- package/dist/pi-intercom/broker/client.js +492 -0
- package/dist/pi-intercom/broker/framing.js +65 -0
- package/dist/pi-intercom/broker/paths.js +42 -0
- package/dist/pi-intercom/broker/pid.js +66 -0
- package/dist/pi-intercom/broker/spawn.js +221 -0
- package/dist/pi-intercom/config.js +102 -0
- package/dist/pi-intercom/index.js +2942 -0
- package/dist/pi-intercom/reply-tracker.js +182 -0
- package/dist/pi-intercom/session-targets.js +128 -0
- package/dist/pi-intercom/subagent-live-events.js +132 -0
- package/dist/pi-intercom/topics.js +157 -0
- package/dist/pi-intercom/types.js +163 -0
- package/dist/pi-intercom/ui/compose.js +269 -0
- package/dist/pi-intercom/ui/inline-message.js +80 -0
- package/dist/pi-intercom/ui/session-list.js +124 -0
- package/dist/runs/background/async-control.js +95 -0
- package/dist/runs/background/async-execution.js +676 -0
- package/dist/runs/background/async-job-tracker.js +383 -0
- package/dist/runs/background/async-result-file.js +58 -0
- package/dist/runs/background/async-resume.js +305 -0
- package/dist/runs/background/async-status.js +442 -0
- package/dist/runs/background/completion-dedupe.js +69 -0
- package/dist/runs/background/completion-delivery.js +245 -0
- package/dist/runs/background/notify.js +71 -0
- package/dist/runs/background/parallel-groups.js +55 -0
- package/dist/runs/background/result-watcher.js +426 -0
- package/dist/runs/background/run-id-resolver.js +64 -0
- package/dist/runs/background/run-status.js +382 -0
- package/dist/runs/background/stale-run-reconciler.js +335 -0
- package/dist/runs/background/subagent-runner-launcher.js +55 -0
- package/dist/runs/background/subagent-runner.js +1872 -0
- package/dist/runs/background/top-level-async.js +5 -0
- package/dist/runs/foreground/chain-clarify.js +1152 -0
- package/dist/runs/foreground/clarify-invocation.js +72 -0
- package/dist/runs/foreground/execution-input.js +423 -0
- package/dist/runs/foreground/foreground-control.js +817 -0
- package/dist/runs/foreground/question-control.js +88 -0
- package/dist/runs/foreground/run-async-path.js +205 -0
- package/dist/runs/foreground/subagent-executor.js +442 -0
- package/dist/runs/foreground/subagent-params.js +165 -0
- package/dist/runs/foreground/wait-run.js +141 -0
- package/dist/runs/shared/acceptance-contract.js +253 -0
- package/dist/runs/shared/acceptance-evaluation.js +256 -0
- package/dist/runs/shared/acceptance-finalization.js +280 -0
- package/dist/runs/shared/acceptance-reports.js +147 -0
- package/dist/runs/shared/acceptance.js +4 -0
- package/dist/runs/shared/chain-outputs.js +110 -0
- package/dist/runs/shared/child-attempt.js +693 -0
- package/dist/runs/shared/child-execution-cwd.js +96 -0
- package/dist/runs/shared/child-observations.js +114 -0
- package/dist/runs/shared/claude-code.js +199 -0
- package/dist/runs/shared/completion-guard.js +31 -0
- package/dist/runs/shared/dynamic-fanout.js +274 -0
- package/dist/runs/shared/history-index.js +72 -0
- package/dist/runs/shared/mcp-direct-tool-allowlist.js +334 -0
- package/dist/runs/shared/model-fallback.js +185 -0
- package/dist/runs/shared/mutating-tool-guard.js +170 -0
- package/dist/runs/shared/native-finalization.js +101 -0
- package/dist/runs/shared/native-usage.js +153 -0
- package/dist/runs/shared/nested-events.js +700 -0
- package/dist/runs/shared/nested-path.js +48 -0
- package/dist/runs/shared/nested-render.js +108 -0
- package/dist/runs/shared/parallel-utils.js +61 -0
- package/dist/runs/shared/parent-receipts.js +68 -0
- package/dist/runs/shared/parent-usage.js +121 -0
- package/dist/runs/shared/pi-args.js +310 -0
- package/dist/runs/shared/pi-spawn.js +52 -0
- package/dist/runs/shared/run-history-queries.js +45 -0
- package/dist/runs/shared/run-history.js +110 -0
- package/dist/runs/shared/run-id-ambiguity.js +4 -0
- package/dist/runs/shared/run-records.js +679 -0
- package/dist/runs/shared/session-cwd-preload.js +33 -0
- package/dist/runs/shared/single-output.js +222 -0
- package/dist/runs/shared/streaming-text.js +15 -0
- package/dist/runs/shared/structured-output.js +55 -0
- package/dist/runs/shared/subagent-control.js +179 -0
- package/dist/runs/shared/subagent-prompt-runtime.js +197 -0
- package/dist/runs/shared/subagent-tool-loop-guard.js +66 -0
- package/dist/runs/shared/supervisor-questions.js +350 -0
- package/dist/runs/shared/workflow-graph.js +214 -0
- package/dist/runs/shared/workflow-policy.js +84 -0
- package/dist/runs/shared/worktree.js +525 -0
- package/dist/shared/agent-context-policy.js +126 -0
- package/dist/shared/artifacts.js +96 -0
- package/dist/shared/atomic-json.js +13 -0
- package/dist/shared/cooperative.js +20 -0
- package/dist/shared/execution-cwd.js +14 -0
- package/dist/shared/file-coalescer.js +21 -0
- package/dist/shared/fork-context.js +49 -0
- package/dist/shared/formatters.js +85 -0
- package/dist/shared/journal-reader.js +407 -0
- package/dist/shared/lazy-tools.js +32 -0
- package/dist/shared/model-info.js +68 -0
- package/dist/shared/native-session.js +15 -0
- package/dist/shared/native-tui.js +18 -0
- package/dist/shared/native-typebox.js +20 -0
- package/dist/shared/post-exit-stdio-guard.js +197 -0
- package/dist/shared/prompt-sections.js +8 -0
- package/dist/shared/session-entries.js +52 -0
- package/dist/shared/session-identity.js +14 -0
- package/dist/shared/settings.js +254 -0
- package/dist/shared/status-format.js +111 -0
- package/dist/shared/temp-root.js +114 -0
- package/dist/shared/types.js +207 -0
- package/dist/shared/ui-mode.js +3 -0
- package/dist/shared/utils.js +334 -0
- package/dist/slash/prompt-template-bridge.js +298 -0
- package/dist/slash/slash-bridge.js +116 -0
- package/dist/slash/slash-commands.js +607 -0
- package/dist/slash/slash-live-state.js +246 -0
- package/dist/tui/action-hints.js +75 -0
- package/dist/tui/agent-history.js +197 -0
- package/dist/tui/agent-view.js +1656 -0
- package/dist/tui/render.js +1515 -0
- package/docs/intercom-bridge.md +212 -0
- package/docs/intercom.md +581 -0
- package/docs/performance.md +121 -0
- package/package.json +102 -4
- package/prompts/gather-context-and-clarify.md +14 -0
- package/prompts/parallel-cleanup.md +62 -0
- package/prompts/parallel-context-build.md +56 -0
- package/prompts/parallel-handoff-plan.md +62 -0
- package/prompts/parallel-research.md +51 -0
- package/prompts/parallel-review.md +59 -0
- package/prompts/review-loop.md +42 -0
- package/scripts/build.mjs +134 -0
- package/scripts/check-compat.mjs +48 -0
- package/scripts/compat-host.mjs +19 -0
- package/scripts/intercom-bridge-credentials.mjs +143 -0
- package/scripts/intercom-remote.mjs +103 -0
- package/scripts/linux-smoke.sh +51 -0
- package/scripts/local-install-smoke.mjs +66 -0
- package/scripts/native-package-smoke.mjs +82 -0
- package/scripts/package-smoke.mjs +209 -0
- package/scripts/prepare.mjs +67 -0
- package/scripts/real-pi-smoke.mjs +415 -0
- package/scripts/run-tests.mjs +149 -0
- package/skills/pi-intercom/SKILL.md +113 -0
- package/skills/pi-intercom/evals/evals.json +29 -0
- package/skills/pi-intercom/evals/trigger-evals.json +47 -0
- package/skills/pi-intercom/references/peer-sessions.md +69 -0
- package/skills/pi-subagents/SKILL.md +76 -0
- package/skills/pi-subagents/evals/evals.json +29 -0
- package/skills/pi-subagents/evals/trigger-evals.json +42 -0
- package/skills/pi-subagents/references/full-orchestration-guide.md +863 -0
- package/src/agents/agent-management.ts +813 -0
- package/src/agents/agent-scope.ts +7 -0
- package/src/agents/agent-selection.ts +23 -0
- package/src/agents/agent-serializer.ts +99 -0
- package/src/agents/agents.ts +916 -0
- package/src/agents/chain-serializer.ts +329 -0
- package/src/agents/frontmatter.ts +21 -0
- package/src/agents/identity.ts +30 -0
- package/src/agents/skills.ts +637 -0
- package/src/extension/build-info.ts +2 -0
- package/src/extension/compact-tools.ts +114 -0
- package/src/extension/config.ts +23 -0
- package/src/extension/control-notices.ts +47 -0
- package/src/extension/doctor.ts +171 -0
- package/src/extension/fanout-child.ts +312 -0
- package/src/extension/index.ts +649 -0
- package/src/extension/schemas.ts +444 -0
- package/src/extension/tool-input.ts +19 -0
- package/src/extension/tool-result.ts +16 -0
- package/src/history/canonical-result.ts +62 -0
- package/src/history/database.ts +59 -0
- package/src/history/index.ts +156 -0
- package/src/history/ingest.ts +349 -0
- package/src/history/queries.ts +241 -0
- package/src/history/store.ts +203 -0
- package/src/history/types.ts +166 -0
- package/src/history/worker.ts +321 -0
- package/src/intercom/intercom-bridge.ts +123 -0
- package/src/intercom/live-intercom.ts +104 -0
- package/src/intercom/result-intercom.ts +429 -0
- package/src/pi-intercom/agent-dir.ts +9 -0
- package/src/pi-intercom/bridge.ts +668 -0
- package/src/pi-intercom/broker/broker.ts +463 -0
- package/src/pi-intercom/broker/client.ts +558 -0
- package/src/pi-intercom/broker/framing.ts +77 -0
- package/src/pi-intercom/broker/paths.ts +47 -0
- package/src/pi-intercom/broker/pid.ts +59 -0
- package/src/pi-intercom/broker/spawn.ts +248 -0
- package/src/pi-intercom/config.ts +142 -0
- package/src/pi-intercom/index.ts +2929 -0
- package/src/pi-intercom/reply-tracker.ts +211 -0
- package/src/pi-intercom/session-targets.ts +172 -0
- package/src/pi-intercom/subagent-live-events.ts +133 -0
- package/src/pi-intercom/topics.ts +125 -0
- package/src/pi-intercom/types.ts +271 -0
- package/src/pi-intercom/ui/compose.ts +289 -0
- package/src/pi-intercom/ui/inline-message.ts +92 -0
- package/src/pi-intercom/ui/session-list.ts +139 -0
- package/src/runs/background/async-control.ts +89 -0
- package/src/runs/background/async-execution.ts +850 -0
- package/src/runs/background/async-job-tracker.ts +385 -0
- package/src/runs/background/async-result-file.ts +62 -0
- package/src/runs/background/async-resume.ts +333 -0
- package/src/runs/background/async-status.ts +481 -0
- package/src/runs/background/completion-dedupe.ts +79 -0
- package/src/runs/background/completion-delivery.ts +195 -0
- package/src/runs/background/notify.ts +123 -0
- package/src/runs/background/parallel-groups.ts +53 -0
- package/src/runs/background/result-watcher.ts +423 -0
- package/src/runs/background/run-id-resolver.ts +69 -0
- package/src/runs/background/run-status.ts +384 -0
- package/src/runs/background/stale-run-reconciler.ts +369 -0
- package/src/runs/background/subagent-runner-launcher.ts +56 -0
- package/src/runs/background/subagent-runner.ts +2053 -0
- package/src/runs/background/top-level-async.ts +13 -0
- package/src/runs/foreground/chain-clarify.ts +1340 -0
- package/src/runs/foreground/clarify-invocation.ts +77 -0
- package/src/runs/foreground/execution-input.ts +467 -0
- package/src/runs/foreground/foreground-control.ts +821 -0
- package/src/runs/foreground/question-control.ts +82 -0
- package/src/runs/foreground/run-async-path.ts +243 -0
- package/src/runs/foreground/subagent-executor.ts +501 -0
- package/src/runs/foreground/subagent-params.ts +320 -0
- package/src/runs/foreground/wait-run.ts +124 -0
- package/src/runs/shared/acceptance-contract.ts +257 -0
- package/src/runs/shared/acceptance-evaluation.ts +275 -0
- package/src/runs/shared/acceptance-finalization.ts +353 -0
- package/src/runs/shared/acceptance-reports.ts +152 -0
- package/src/runs/shared/acceptance.ts +33 -0
- package/src/runs/shared/chain-outputs.ts +114 -0
- package/src/runs/shared/child-attempt.ts +623 -0
- package/src/runs/shared/child-execution-cwd.ts +91 -0
- package/src/runs/shared/child-observations.ts +99 -0
- package/src/runs/shared/claude-code.ts +243 -0
- package/src/runs/shared/completion-guard.ts +35 -0
- package/src/runs/shared/dynamic-fanout.ts +295 -0
- package/src/runs/shared/history-index.ts +69 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +376 -0
- package/src/runs/shared/model-fallback.ts +219 -0
- package/src/runs/shared/mutating-tool-guard.ts +194 -0
- package/src/runs/shared/native-finalization.ts +128 -0
- package/src/runs/shared/native-usage.ts +113 -0
- package/src/runs/shared/nested-events.ts +752 -0
- package/src/runs/shared/nested-path.ts +52 -0
- package/src/runs/shared/nested-render.ts +119 -0
- package/src/runs/shared/parallel-utils.ts +153 -0
- package/src/runs/shared/parent-receipts.ts +59 -0
- package/src/runs/shared/parent-usage.ts +121 -0
- package/src/runs/shared/pi-args.ts +350 -0
- package/src/runs/shared/pi-spawn.ts +52 -0
- package/src/runs/shared/run-history-queries.ts +44 -0
- package/src/runs/shared/run-history.ts +100 -0
- package/src/runs/shared/run-id-ambiguity.ts +4 -0
- package/src/runs/shared/run-records.ts +607 -0
- package/src/runs/shared/session-cwd-preload.ts +27 -0
- package/src/runs/shared/single-output.ts +267 -0
- package/src/runs/shared/streaming-text.ts +18 -0
- package/src/runs/shared/structured-output.ts +68 -0
- package/src/runs/shared/subagent-control.ts +219 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +201 -0
- package/src/runs/shared/subagent-tool-loop-guard.ts +89 -0
- package/src/runs/shared/supervisor-questions.ts +415 -0
- package/src/runs/shared/workflow-graph.ts +220 -0
- package/src/runs/shared/workflow-policy.ts +125 -0
- package/src/runs/shared/worktree.ts +635 -0
- package/src/shared/agent-context-policy.ts +184 -0
- package/src/shared/artifacts.ts +95 -0
- package/src/shared/atomic-json.ts +16 -0
- package/src/shared/cooperative.ts +21 -0
- package/src/shared/execution-cwd.ts +14 -0
- package/src/shared/file-coalescer.ts +29 -0
- package/src/shared/fork-context.ts +68 -0
- package/src/shared/formatters.ts +84 -0
- package/src/shared/journal-reader.ts +333 -0
- package/src/shared/lazy-tools.ts +36 -0
- package/src/shared/model-info.ts +81 -0
- package/src/shared/native-session.ts +8 -0
- package/src/shared/native-tui.ts +10 -0
- package/src/shared/native-typebox.ts +14 -0
- package/src/shared/post-exit-stdio-guard.ts +204 -0
- package/src/shared/prompt-sections.ts +10 -0
- package/src/shared/session-entries.ts +49 -0
- package/src/shared/session-identity.ts +18 -0
- package/src/shared/settings.ts +384 -0
- package/src/shared/status-format.ts +123 -0
- package/src/shared/temp-root.ts +107 -0
- package/src/shared/types.ts +1260 -0
- package/src/shared/ui-mode.ts +5 -0
- package/src/shared/utils.ts +342 -0
- package/src/slash/prompt-template-bridge.ts +408 -0
- package/src/slash/slash-bridge.ts +178 -0
- package/src/slash/slash-commands.ts +617 -0
- package/src/slash/slash-live-state.ts +292 -0
- package/src/tui/action-hints.ts +69 -0
- package/src/tui/agent-history.ts +210 -0
- package/src/tui/agent-view.ts +1323 -0
- package/src/tui/render.ts +1550 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Secure remote Intercom bridge
|
|
2
|
+
|
|
3
|
+
Optional HTTPS messaging proxy for a remote agent such as **Grok Bot**. Pi-intercom's broker remains same-machine Unix IPC. Nothing is added to the Pi extension loader, and starting Pi alone never starts this proxy.
|
|
4
|
+
|
|
5
|
+
## Design note
|
|
6
|
+
|
|
7
|
+
**Transport:** a Mac-local Node HTTPS server bound to **127.0.0.1**, carried by a Mac-initiated **SSH reverse TCP forward** to the Linux box's loopback interface. Grok calls HTTPS on its own loopback. Unlike a Unix-socket tunnel, only the proxy opens `broker.sock`; neither the remote nor SSH can issue raw broker frames. This choice needs no cloud account, public DNS, inbound Mac SSH, or per-call laptop approval. An existing SSH account on Linux is the only tunnel prerequisite. SSH authenticates the tunnel host; end-to-end mTLS authenticates both application endpoints even to other processes on Linux.
|
|
8
|
+
|
|
9
|
+
**Threat model:** deny unauthenticated local/network callers, stolen credentials after revocation/expiry, identity spoofing, arbitrary broker commands, forged replies, accidental LAN exposure, and unbounded waits/resource use. The Mac user, local broker, OS, private CA, and approved remote host are trusted. A compromised authorized Grok credential can read peer metadata and send agent-visible text to local peers (including instructions); mTLS does not sandbox those agents or make the content trustworthy. Listed peers can be in other projects. Approve only a host allowed to see that metadata and message those peers. Root/compromised endpoints and denial of service beyond fixed connection/request limits are outside this boundary.
|
|
10
|
+
|
|
11
|
+
**Auth/authority:** TLS 1.2+ with client certificates issued by a private CA **and** an explicit SHA-256 certificate fingerprint allowlist. Each allowlisted certificate fixes the peer name and Mac project directory; remote payloads cannot change identity, cwd, socket, shell commands, or presence. Certificates last seven days. TLS verifies the server CA and loopback SAN; never use `curl -k` or disable certificate checks. The proxy exposes only register/list/send/ask/reply, plus inbox/ack receipt plumbing needed to receive messages and answer local asks. No broker admin, topic operations, file reads, or shell endpoint.
|
|
12
|
+
|
|
13
|
+
**Socket discovery:** reuse the actual `IntercomClient`, `getBrokerSocketPath()` and framing code. With the same Mac uid, `PI_CODING_AGENT_DIR` (default `~/.pi/agent`) and `TMPDIR` as Pi, the preferred path is `$TMPDIR/pi-intercom-<sha256(uid:agentDir)[0:16]>/broker.sock`; long paths fall back to `/tmp`. The client's existing owned-socket legacy fallback is retained. No hardcoded `/var/folders` path, chmod, broker spawn, PID-file operation, or broker restart. An unavailable broker returns an error; start a normal Pi session to bring it up.
|
|
14
|
+
|
|
15
|
+
**Delivery/lifecycle:** one broker peer per authorized certificate, registered lazily on the first API call, with a five-minute inactivity lease. Poll inbox to maintain presence. Send returns broker acceptance, not proof a model consumed it. Ask steers the recipient and waits at most two minutes for both the exact recipient ID and exact `replyTo`. One outgoing ask per identity. Revocation/expiry/shutdown/client disconnect terminate waits. Inbox is bounded and volatile; overflow is reported, not silently described as successful receipt. Restarting the helper loses inbox contents and pending replies. Upgrade to a durable inbox journal if restart recovery is required; existing Pi recipients still save their own messages normally.
|
|
16
|
+
|
|
17
|
+
**Audit:** JSONL metadata on stdout: request/connection identity, certificate fingerprint, operation, peer/message IDs and outcome. Message/attachment bodies and keys are not logged. Protect logs (0700 directory, 0600 files); rotate them with your normal log tooling. Never publish private config/keys or raw inbox/list output as smoke evidence.
|
|
18
|
+
|
|
19
|
+
## Mac setup
|
|
20
|
+
|
|
21
|
+
Requires Node **24.21.0+**, OpenSSL with `req -addext` (Homebrew OpenSSL works), and a connected Pi session with Intercom. Run commands from this checkout/package directory. A runtime-only installed checkout already has `dist/`; for development use `npm ci` first. See the [installation guide](../README.md#installation) before rebuilding an in-use extension. This standalone helper can run from its own installed copy without touching the live Pi runtime.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Use a NEW directory; init refuses to overwrite any existing CA.
|
|
25
|
+
umask 077
|
|
26
|
+
BRIDGE="$HOME/.pi/intercom-bridge"
|
|
27
|
+
node scripts/intercom-bridge-credentials.mjs init "$BRIDGE" --cwd "$PWD"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The last JSON line contains paths to the issued client `cert`/`key`, trusted `ca`, and `config`; it does not print secret contents. Keep those paths for the copy step. Configuration is local-only, owned by the Mac user and private:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"port": 9443,
|
|
35
|
+
"ca": "/Users/mitch/.pi/intercom-bridge/ca.crt",
|
|
36
|
+
"cert": "/Users/mitch/.pi/intercom-bridge/server.crt",
|
|
37
|
+
"key": "/Users/mitch/.pi/intercom-bridge/server.key",
|
|
38
|
+
"clients": [{
|
|
39
|
+
"fingerprint256": "SHA256_FINGERPRINT_FROM_ISSUE",
|
|
40
|
+
"name": "grok-bot",
|
|
41
|
+
"cwd": "/Users/mitch/project"
|
|
42
|
+
}]
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`cwd` controls presence/project association, **not** an authorization restriction. `list` intentionally returns all connected peer identities, omitting topics/subscriptions. Target full IDs or the returned `target` when names collide. Port `0` requests an ephemeral port, reported in the listening log; a fixed port is easier for SSH.
|
|
47
|
+
|
|
48
|
+
Start the helper in a dedicated terminal (or supervise this exact command with launchd):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Match Pi's agent directory and temp environment, especially for launchd.
|
|
52
|
+
export PI_CODING_AGENT_DIR="${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}"
|
|
53
|
+
export TMPDIR="$(getconf DARWIN_USER_TEMP_DIR)"
|
|
54
|
+
node dist/pi-intercom/bridge.js --config "$BRIDGE/config.json" >> "$BRIDGE/audit.jsonl"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The listening record includes the helper PID and port. Record the PID as `HELPER_PID` in your administration terminal; **do not use the broker PID**. Wait for that readiness record before making a request: a running process is not proof its listener is ready. Verify `lsof -nP -iTCP:9443 -sTCP:LISTEN` shows only `127.0.0.1:9443`. Keep the helper running; no per-message approvals are needed.
|
|
58
|
+
|
|
59
|
+
For the installed Mac LaunchAgent (`com.fitchmultz.pi-intercom-bridge`), inspect and administer it with:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
launchctl print "gui/$(id -u)/com.fitchmultz.pi-intercom-bridge"
|
|
63
|
+
# Reload allowlist without restarting:
|
|
64
|
+
launchctl kill SIGHUP "gui/$(id -u)/com.fitchmultz.pi-intercom-bridge"
|
|
65
|
+
# Stop immediately; remove the plist too to disable future login starts:
|
|
66
|
+
launchctl bootout "gui/$(id -u)" "$HOME/Library/LaunchAgents/com.fitchmultz.pi-intercom-bridge.plist"
|
|
67
|
+
# Start again explicitly:
|
|
68
|
+
launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/com.fitchmultz.pi-intercom-bridge.plist"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The installed agent has no `KeepAlive` auto-restart; stopping its helper really stops access. Remove its plist to disable future login starts permanently. Inspect/drain inbox before a planned helper restart because it is volatile.
|
|
72
|
+
|
|
73
|
+
### Tunnel and provision Grok
|
|
74
|
+
|
|
75
|
+
Use the **known, approved** Linux SSH host/account, not an invented example host. Preserve SSH host-key verification and do not forward your SSH agent:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
GROK_SSH='grok@YOUR_LINUX_HOST'
|
|
79
|
+
# On Linux, first inspect effective SSH config with the administrator:
|
|
80
|
+
# sudo sshd -T | grep gatewayports
|
|
81
|
+
# Require GatewayPorts=no (default) or clientspecified, NEVER yes.
|
|
82
|
+
|
|
83
|
+
# On the Mac, dedicated terminal/supervised process:
|
|
84
|
+
ssh -NT -a -o BatchMode=yes -o StrictHostKeyChecking=yes \
|
|
85
|
+
-o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
|
|
86
|
+
-R 127.0.0.1:9443:127.0.0.1:9443 "$GROK_SSH"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**On Linux, verify `ss -ltn '( sport = :9443 )'` shows only `127.0.0.1:9443` before use.** `GatewayPorts=yes` forces wildcard binding even when `-R` requests loopback. If it shows `0.0.0.0`, `*`, or `[::]`, stop the tunnel and correct that SSH policy. Do not open a firewall port. OpenSSH references: [ssh `-R`](https://man.openbsd.org/ssh.1) and [sshd `GatewayPorts`](https://man.openbsd.org/sshd_config.5#GatewayPorts).
|
|
90
|
+
|
|
91
|
+
Transfer **only** the client certificate/key, public `ca.crt`, and the dependency-free remote script through the existing approved SSH/SFTP channel:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Use cert/key paths printed by init/issue, not the CA or server keys.
|
|
95
|
+
CLIENT_CERT='/absolute/path/from/issue/grok-bot-ISSUED.crt'
|
|
96
|
+
CLIENT_KEY='/absolute/path/from/issue/grok-bot-ISSUED.key'
|
|
97
|
+
ssh "$GROK_SSH" 'umask 077; mkdir -p ~/.config/pi-intercom; chmod 700 ~/.config/pi-intercom'
|
|
98
|
+
scp "$CLIENT_CERT" "$GROK_SSH:.config/pi-intercom/client.crt"
|
|
99
|
+
scp "$CLIENT_KEY" "$GROK_SSH:.config/pi-intercom/client.key"
|
|
100
|
+
scp "$BRIDGE/ca.crt" scripts/intercom-remote.mjs "$GROK_SSH:.config/pi-intercom/"
|
|
101
|
+
ssh "$GROK_SSH" 'chmod 600 ~/.config/pi-intercom/*'
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
For a least-privileged dedicated Linux SSH tunnel account, the administrator can restrict its key to remote forwarding with `restrict,port-forwarding,permitlisten="127.0.0.1:9443",command="/bin/false"` and `AllowTcpForwarding remote`, `GatewayPorts no`. `-N` requests no shell. Provision files separately; do not reuse Grok's client key as an SSH key. No SSH login credential for the Mac is given to Grok.
|
|
105
|
+
|
|
106
|
+
## Grok Bot: exact remote commands
|
|
107
|
+
|
|
108
|
+
On Linux, configure Grok's shell environment:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
export INTERCOM_BRIDGE_URL='https://127.0.0.1:9443'
|
|
112
|
+
export INTERCOM_BRIDGE_CA="$HOME/.config/pi-intercom/ca.crt"
|
|
113
|
+
export INTERCOM_BRIDGE_CERT="$HOME/.config/pi-intercom/client.crt"
|
|
114
|
+
export INTERCOM_BRIDGE_KEY="$HOME/.config/pi-intercom/client.key"
|
|
115
|
+
REMOTE="$HOME/.config/pi-intercom/intercom-remote.mjs"
|
|
116
|
+
|
|
117
|
+
node "$REMOTE" register
|
|
118
|
+
node "$REMOTE" list
|
|
119
|
+
node "$REMOTE" send --to planner --message 'Grok checking in. Please send your current status.'
|
|
120
|
+
node "$REMOTE" ask --to planner --message 'What is the current status?' --timeout-ms 120000
|
|
121
|
+
node "$REMOTE" inbox
|
|
122
|
+
node "$REMOTE" reply --reply-to QUESTION_ID_FROM_INBOX --message 'Proceed with the stable API.'
|
|
123
|
+
node "$REMOTE" ack ORDINARY_MESSAGE_ID_FROM_INBOX
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Poll inbox at a reasonable cadence (for example every 5–15 seconds) while Grok is available. Fetch is non-destructive, so retrying a fetch cannot lose messages; persist/consume then ack ordinary messages. Inbound asks remain in the inbox until `reply` succeeds; ack does not discard a reply obligation. Use `send` for most coordination and `ask` only when Grok really needs a blocking answer. The CLI has a hard request deadline (ask timeout + 15 seconds), validates TLS, emits JSON, and exits 1 on errors / 2 on invalid arguments. It never retries mutations automatically.
|
|
127
|
+
|
|
128
|
+
Curl works too, with bounded waiting and the same TLS files:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
curl --fail-with-body --max-time 135 \
|
|
132
|
+
--cacert "$INTERCOM_BRIDGE_CA" --cert "$INTERCOM_BRIDGE_CERT" --key "$INTERCOM_BRIDGE_KEY" \
|
|
133
|
+
-H 'Content-Type: application/json' \
|
|
134
|
+
-d '{"to":"planner","message":"Please reply with your status.","timeoutMs":120000}' \
|
|
135
|
+
"$INTERCOM_BRIDGE_URL/v1/ask"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### JSON API contract
|
|
139
|
+
|
|
140
|
+
All routes require mTLS and the certificate allowlist. Unknown routes/fields, wrong methods, non-JSON bodies, unsafe control characters, and requests larger than 64 KiB are rejected. No CORS; browser-origin requests are rejected. Success is `{ "ok": true, ... }`; application failures are `{ "ok": false, "error": { "code": "...", "message": "..." } }` with a non-2xx status. Certificate/allowlist admission can terminate TLS before HTTP; the CLI reports that as a TLS/transport error. No remote-controlled broker frame or command is passed through.
|
|
141
|
+
|
|
142
|
+
| Route | Request | Success fields |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `POST /v1/register` | `{}` | `sessionId`, `name` (also automatic on other operations) |
|
|
145
|
+
| `GET /v1/list` | none | `sessionId`, `sessions` (metadata + unambiguous targets) |
|
|
146
|
+
| `POST /v1/send` | `{to,message}` | `id`, `accepted`, `delivered` |
|
|
147
|
+
| `POST /v1/ask` | `{to,message,timeoutMs?}` | send receipt and `reply:{from,message}` |
|
|
148
|
+
| `GET /v1/inbox` | none | `messages:[{from,message}]`, `overflow`, `lostMessages` |
|
|
149
|
+
| `POST /v1/reply` | `{replyTo,message}` | send receipt; target derived from the received ask |
|
|
150
|
+
| `POST /v1/ack` | `{ids:[...]}` | `acked`, `retained` |
|
|
151
|
+
|
|
152
|
+
Timeout does **not** retract a delivered ask; a late answer can arrive in inbox. Offline/missing peers, broker outages, ambiguous/self targets, a second concurrent ask, invalid/revoked credentials, timeout, and resource limits have explicit errors. HTTP send/list deadlines are bounded by the real client (8/5 seconds); broker registration by 10 seconds. A lost HTTP response or acknowledgement timeout means **delivery unknown**—inspect inbox/local peer before retrying to avoid duplicate instructions.
|
|
153
|
+
|
|
154
|
+
## Rotate credentials
|
|
155
|
+
|
|
156
|
+
Client renewal replaces its old fingerprint rather than authorizing both indefinitely. Credential commands hold a private directory lock across the complete config read/modify/write and certificate issuance, so concurrent operations fail instead of restoring a revoked fingerprint. After a crashed command, inspect `DIR/.credentials.lock/owner`, confirm that process is gone, then remove that lock and retry; never clear a live command's lock.
|
|
157
|
+
|
|
158
|
+
Renew with:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
node scripts/intercom-bridge-credentials.mjs issue "$BRIDGE" grok-bot
|
|
162
|
+
# Transfer the NEW cert/key using the same private copy commands above.
|
|
163
|
+
kill -HUP "$HELPER_PID"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
SIGHUP rereads the private config, drops removed/changed peers and their TLS connections, and cancels pending waits. Confirm the reload audit record and verify the old certificate is denied. Invalid reload fails closed. Client expiry also applies to existing connections/peer leases, not just new TLS handshakes. Restart Grok's client process if it caches its files.
|
|
167
|
+
|
|
168
|
+
Server certificate expires after one year; CA after ten. To rotate server/CA, create a **new** credential directory with `init`, transfer its new public CA and new client credential, stop/restart **only this helper** with the new config, and retain the old directory briefly as a private rollback. Never restart the shared broker or change its socket permissions for rotation. If the CA key is compromised, replace the entire CA immediately. Old private key files retained by `issue` should be removed only when no rollback is needed.
|
|
169
|
+
|
|
170
|
+
## How to revoke Grok
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
node scripts/intercom-bridge-credentials.mjs revoke "$BRIDGE" grok-bot
|
|
174
|
+
kill -HUP "$HELPER_PID"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Confirm the reload/revocation audit record, that Grok disappears from the local peer list, and that its old cert cannot call `/v1/list`. Stop the SSH forward too if no other client needs it. Remove Grok's saved client key on Linux and obsolete local client keys when no longer needed. Emergency immediate cut-off: stop **the helper process**, not Pi or the broker. Certificate renewal cannot bypass the removed fingerprint; reauthorization requires a new local `issue` + reload.
|
|
178
|
+
|
|
179
|
+
## Verification / smoke transcript
|
|
180
|
+
|
|
181
|
+
The process-boundary integration test uses a private real broker, real TLS certificates, actual HTTPS requests and the remote CLI; it requires no model/provider credentials:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
node --test test/integration/intercom-bridge.test.ts
|
|
185
|
+
# Do not inject host startup diagnostics into native fixture stderr:
|
|
186
|
+
env -u PI_TIMING -u PI_EXTENSION_PERFORMANCE npm run ci
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
For a live smoke, from a separate Mac process and then Linux use the remote CLI to list peers and ask an intentionally selected connected session:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
node "$REMOTE" list
|
|
193
|
+
node "$REMOTE" ask --to KNOWN_FULL_SESSION_ID --message 'Bridge smoke only: reply with bridge-smoke-ok.' --timeout-ms 120000
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Save only a redacted transcript: platform, operation, returned peer names relevant to the test, accepted/delivered, and reply text. Do not publish unrelated cwd/model/topic/message content.
|
|
197
|
+
|
|
198
|
+
Observed **2026-10-06**, from a separate process on the Mac through the installed runtime-only helper to the live broker and a real connected Pi session (not a mocked recipient):
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"platform": "darwin",
|
|
203
|
+
"transport": "loopback HTTPS mTLS",
|
|
204
|
+
"list": {"ok": true, "peers": ["secure-intercom-bridge", "grok-bot"]},
|
|
205
|
+
"ask": {
|
|
206
|
+
"ok": true, "accepted": true, "delivered": true, "replied": true,
|
|
207
|
+
"reply": "bridge-smoke-ok"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Off-box deployment/smoke is not yet verified:** the actual Grok Linux SSH destination/access was unavailable. No credentials were transferred to an unverified host. Once that access is supplied, verify Linux's listener and repeat these exact list/ask commands there.
|