pi-crew 0.9.46 → 0.9.48
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 +83 -0
- package/README.md +16 -2
- package/dist/build-meta.json +289 -164
- package/dist/index.mjs +1744 -2732
- package/dist/index.mjs.map +4 -4
- package/docs/decisions/2026-07-21-broker-phase4-default-on.md +77 -0
- package/docs/decisions/2026-07-21-broker-windows-perms.md +91 -0
- package/docs/decisions/2026-07-22-broker-phase4-gated-on.md +99 -0
- package/docs/decisions/README.md +3 -0
- package/docs/publishing.md +29 -0
- package/package.json +3 -1
- package/scripts/build-bundle.mjs +7 -0
- package/scripts/postinstall.mjs +60 -1
- package/scripts/pty_probe.py +174 -0
- package/skills/real-test-pi-crew/SKILL.md +659 -0
- package/src/config/config.ts +42 -1
- package/src/config/defaults.ts +45 -1
- package/src/config/types.ts +19 -0
- package/src/extension/register.ts +6 -1
- package/src/extension/registration/context-builder.ts +4 -0
- package/src/extension/registration/lifecycle-handlers.ts +166 -3
- package/src/extension/registration/registration-types.ts +9 -0
- package/src/prompt/prompt-runtime.ts +108 -0
- package/src/runtime/broker-issuer.ts +37 -0
- package/src/runtime/child-pi-spawn.ts +53 -0
- package/src/runtime/child-pi.ts +42 -11
- package/src/runtime/crew-broker-child.ts +88 -0
- package/src/runtime/crew-broker-client.ts +673 -0
- package/src/runtime/crew-broker-tokens.ts +84 -0
- package/src/runtime/crew-broker.ts +1276 -0
- package/src/runtime/dynamic-workflow-context.ts +7 -3
- package/src/runtime/dynamic-workflow-runner.ts +1 -1
- package/src/runtime/plan-templates.ts +8 -6
- package/src/schema/config-schema.ts +14 -0
- package/src/state/mailbox.ts +43 -0
- package/src/ui/key-utils.ts +42 -0
- package/src/ui/keybinding-map.ts +29 -3
- package/src/ui/run-dashboard.ts +28 -0
- package/src/ui/settings-overlay.ts +42 -22
- package/src/utils/ndjson.ts +115 -0
- package/src/utils/session-utils.ts +30 -0
- package/src/utils/socket-path.ts +127 -0
- package/workflows/default.workflow.md +1 -1
- package/workflows/fast-fix.workflow.md +1 -1
- package/workflows/plan-execute.workflow.md +1 -1
- package/workflows/review.workflow.md +1 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* crew-broker-tokens.ts — Per-run token registry for the broker.
|
|
3
|
+
*
|
|
4
|
+
* The token map is HEAP ONLY. It lives on the CrewBroker instance and is
|
|
5
|
+
* cleared on `stop()`. It is never serialized to disk, never written to
|
|
6
|
+
* the run directory, never logged, and never exposed via a broker method.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from crew-broker.ts to keep the orchestrator file focused on
|
|
9
|
+
* connection / dispatch logic and to make the registry's invariants
|
|
10
|
+
* independently testable.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { randomUUID, timingSafeEqual } from "node:crypto";
|
|
14
|
+
|
|
15
|
+
/** Length guard: tokens are 128-bit-class (UUID v4). */
|
|
16
|
+
export type BrokerToken = string;
|
|
17
|
+
|
|
18
|
+
/** Generate a fresh per-run token. */
|
|
19
|
+
export function newBrokerToken(): BrokerToken {
|
|
20
|
+
return randomUUID();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A small registry mapping runId → token. Operations are O(1) Map.
|
|
25
|
+
* Constant-time compare (`timingSafeEqual`) prevents side-channel
|
|
26
|
+
* comparison leakage of the secret. The compare normalizes both sides
|
|
27
|
+
* to the same byte length — differing-length inputs return false
|
|
28
|
+
* immediately without entering the timing-safe path (length itself is
|
|
29
|
+
* not a secret, only the bytes are).
|
|
30
|
+
*/
|
|
31
|
+
export class BrokerTokenRegistry {
|
|
32
|
+
private readonly map = new Map<string, BrokerToken>();
|
|
33
|
+
|
|
34
|
+
/** Issue a token for `runId`. Idempotent per run: if a token already
|
|
35
|
+
* exists for this runId, the existing token is returned unchanged so that
|
|
36
|
+
* concurrent sibling tasks sharing a runId all authenticate with the same
|
|
37
|
+
* per-run token (the spec's per-run token model). Pass an explicit
|
|
38
|
+
* `token` only in tests that need a deterministic value. */
|
|
39
|
+
issue(runId: string, token?: BrokerToken): BrokerToken {
|
|
40
|
+
if (typeof runId !== "string" || runId.length === 0) {
|
|
41
|
+
throw new Error("BrokerTokenRegistry.issue: runId must be a non-empty string");
|
|
42
|
+
}
|
|
43
|
+
if (token === undefined) {
|
|
44
|
+
const existing = this.map.get(runId);
|
|
45
|
+
if (existing !== undefined) return existing;
|
|
46
|
+
const fresh = newBrokerToken();
|
|
47
|
+
this.map.set(runId, fresh);
|
|
48
|
+
return fresh;
|
|
49
|
+
}
|
|
50
|
+
this.map.set(runId, token);
|
|
51
|
+
return token;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Look up the token for `runId`. Returns undefined if absent. */
|
|
55
|
+
get(runId: string): BrokerToken | undefined {
|
|
56
|
+
return this.map.get(runId);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Constant-time equality check. Returns false on length mismatch. */
|
|
60
|
+
matches(runId: string, candidate: unknown): boolean {
|
|
61
|
+
const expected = this.map.get(runId);
|
|
62
|
+
if (expected === undefined) return false;
|
|
63
|
+
if (typeof candidate !== "string" || candidate.length === 0) return false;
|
|
64
|
+
const a = Buffer.from(expected, "utf8");
|
|
65
|
+
const b = Buffer.from(candidate, "utf8");
|
|
66
|
+
if (a.length !== b.length) return false;
|
|
67
|
+
return timingSafeEqual(a, b);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Remove the token for `runId`. */
|
|
71
|
+
revoke(runId: string): void {
|
|
72
|
+
this.map.delete(runId);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Wipe every token. Called from CrewBroker.stop(). */
|
|
76
|
+
clear(): void {
|
|
77
|
+
this.map.clear();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Diagnostic — count of registered tokens. Never returns the tokens. */
|
|
81
|
+
get size(): number {
|
|
82
|
+
return this.map.size;
|
|
83
|
+
}
|
|
84
|
+
}
|