@ccmsg/cli 0.11.2 → 0.11.4
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 +8 -12
- package/package.json +1 -1
- package/src/auth/auth.ts +23 -23
- package/src/auth/http.ts +3 -3
- package/src/auth/records.ts +2 -2
- package/src/auth/webauthn.ts +1 -1
- package/src/cli.ts +78 -23
- package/src/daemon/control.ts +1 -1
- package/src/daemon/registry.ts +11 -11
- package/src/daemon/snapshot.ts +1 -1
- package/src/daemon/supervise.ts +4 -4
- package/src/dispatch/caller.ts +1 -1
- package/src/dispatch/dispatch.ts +4 -4
- package/src/dispatch/handler.ts +4 -4
- package/src/dispatch/identity.ts +1 -1
- package/src/dispatch/result.ts +2 -2
- package/src/files/containment.ts +2 -2
- package/src/harness/index.ts +1 -1
- package/src/instance/client.ts +1 -1
- package/src/instance/config.ts +13 -13
- package/src/instance/instance.ts +42 -42
- package/src/instance/lock.ts +2 -2
- package/src/instance/log.ts +1 -1
- package/src/instance/paths.ts +6 -6
- package/src/instance/socket.ts +1 -1
- package/src/kv/store.ts +1 -1
- package/src/mesh/instances.ts +2 -2
- package/src/mesh/keys.ts +7 -7
- package/src/mesh/mesh.ts +67 -67
- package/src/mesh/relay.ts +8 -8
- package/src/mesh/wire.ts +2 -2
- package/src/messaging/delivery.ts +24 -24
- package/src/messaging/direct.ts +23 -23
- package/src/messaging/inbox.ts +6 -6
- package/src/messaging/notify.ts +5 -5
- package/src/plugin/codex.ts +1 -1
- package/src/sessions/classify.ts +6 -6
- package/src/sessions/dump.ts +1 -1
- package/src/sessions/handlers.ts +2 -2
- package/src/sessions/harness.ts +12 -12
- package/src/sessions/last-live.ts +4 -4
- package/src/sessions/registry.ts +32 -32
- package/src/sessions/status.ts +7 -7
- package/src/sessions/terminals.ts +1 -1
- package/src/transcript/files.ts +4 -4
- package/src/transcript/fold.ts +9 -9
- package/src/transcript/items/classify.ts +56 -8
- package/src/transcript/read.ts +1 -1
- package/src/transcript/tail.ts +3 -3
- package/src/transcript/transcripts.ts +7 -7
- package/src/translate/helper.ts +2 -2
- package/src/transport/conn.ts +3 -3
- package/src/transport/dial.ts +1 -1
- package/src/transport/driver.ts +2 -2
- package/src/transport/entry.ts +1 -1
- package/src/transport/framing.ts +1 -1
- package/src/transport/listener.ts +3 -3
- package/src/transport/uds.ts +2 -2
- package/src/transport/ws.ts +2 -2
- package/src/upstream/events.ts +3 -3
- package/src/upstream/gateway.ts +6 -6
- package/src/upstream/json.ts +1 -1
- package/src/upstream/requests.ts +6 -6
- package/src/upstream/stats.ts +1 -1
- package/src/upstream/status.ts +4 -4
- package/src/upstream/usage.ts +1 -1
- package/src/upstream/webhook.ts +1 -1
package/src/instance/paths.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
SUPERVISOR_FILE,
|
|
13
13
|
} from "./config.ts";
|
|
14
14
|
|
|
15
|
-
/** Every path one instance uses, decided in one place (
|
|
15
|
+
/** Every path one instance uses, decided in one place (DESIGN §8.1).
|
|
16
16
|
*
|
|
17
17
|
* All of them are derived from the config home, because the config home is
|
|
18
18
|
* what an instance is (A2): two instances differ in exactly that, so deriving
|
|
@@ -35,7 +35,7 @@ export interface InstancePaths {
|
|
|
35
35
|
readonly endpointsFile: string;
|
|
36
36
|
readonly supervisorFile: string;
|
|
37
37
|
/** Where what has been read and checked is kept, which is the only thing the
|
|
38
|
-
* supervisor and the instances read (§8.2). */
|
|
38
|
+
* supervisor and the instances read (DESIGN §8.2). */
|
|
39
39
|
readonly stateRoot: string;
|
|
40
40
|
readonly satisfiedFile: string;
|
|
41
41
|
/** Where a file is put before it is overwritten by the checked copy. */
|
|
@@ -49,7 +49,7 @@ export interface InstancePaths {
|
|
|
49
49
|
* Bun unlinks the path it listened on when the listener stops (measured
|
|
50
50
|
* against Bun 1.3.13), so binding the stable path directly would mean a
|
|
51
51
|
* departing instance deleting the address its successor had already taken
|
|
52
|
-
* over (§8.5). Binding a path of its own leaves it deleting only its own. */
|
|
52
|
+
* over (DESIGN §8.5). Binding a path of its own leaves it deleting only its own. */
|
|
53
53
|
readonly socketReal: string;
|
|
54
54
|
/** Where both of the above live, so the orphan sweep has one directory. */
|
|
55
55
|
readonly socketDir: string;
|
|
@@ -60,7 +60,7 @@ export interface InstancePaths {
|
|
|
60
60
|
readonly pidFile: string;
|
|
61
61
|
readonly lockFile: string;
|
|
62
62
|
readonly logFile: string;
|
|
63
|
-
/** Where this instance's own id is kept (§
|
|
63
|
+
/** Where this instance's own id is kept (DESIGN §2.5). It lives with the state
|
|
64
64
|
* because moving an instance is moving that directory: the id has to travel
|
|
65
65
|
* with it, since everything the instance issued is keyed by it. */
|
|
66
66
|
readonly instanceIdFile: string;
|
|
@@ -92,7 +92,7 @@ export type Env = Record<string, string | undefined>;
|
|
|
92
92
|
* process belongs to. Reading the config-home variables in a fixed order
|
|
93
93
|
* instead would send a Codex session's commands to the Claude Code instance,
|
|
94
94
|
* because a session started from inside another one inherits its whole
|
|
95
|
-
* environment and so names both homes at once (§
|
|
95
|
+
* environment and so names both homes at once (DESIGN §4.1).
|
|
96
96
|
*
|
|
97
97
|
* With no session claiming the process — a person at a terminal — each
|
|
98
98
|
* harness's own variable is read in turn, and Claude Code's home is the
|
|
@@ -128,7 +128,7 @@ export function resolvePaths(env: Env = process.env): InstancePaths {
|
|
|
128
128
|
* The one to call wherever the config home is decided rather than discovered —
|
|
129
129
|
* a command naming a directory, an install naming an agent's own home. Going
|
|
130
130
|
* through the environment instead would have that answer re-derived from
|
|
131
|
-
* whichever session the process happens to be running inside (§
|
|
131
|
+
* whichever session the process happens to be running inside (DESIGN §4.1), and a
|
|
132
132
|
* command that named a directory would silently act on another one. */
|
|
133
133
|
export function resolvePathsFor(configHome: string, env: Env = process.env): InstancePaths {
|
|
134
134
|
const key = instanceKey(configHome);
|
package/src/instance/socket.ts
CHANGED
|
@@ -29,7 +29,7 @@ export function publishSocket(paths: InstancePaths): void {
|
|
|
29
29
|
*
|
|
30
30
|
* The stable address is never swept. It may already point at a successor, and
|
|
31
31
|
* one pointing at a socket that is gone is the "the unix socket refuses"
|
|
32
|
-
* a client reads as this instance having finished leaving (§8.5). */
|
|
32
|
+
* a client reads as this instance having finished leaving (DESIGN §8.5). */
|
|
33
33
|
export function sweepOrphanSockets(paths: InstancePaths): void {
|
|
34
34
|
let names: string[];
|
|
35
35
|
try {
|
package/src/kv/store.ts
CHANGED
|
@@ -19,7 +19,7 @@ export const KV_DIR = "kv";
|
|
|
19
19
|
|
|
20
20
|
/** The values clients keep here, and the topic that shows them changing.
|
|
21
21
|
*
|
|
22
|
-
* Written down, unlike almost everything else this instance holds (§
|
|
22
|
+
* Written down, unlike almost everything else this instance holds (DESIGN §2.5): a
|
|
23
23
|
* value here was typed by a person and exists nowhere else — the theme a
|
|
24
24
|
* browser is showing is a copy of it, not its source — so losing it on a
|
|
25
25
|
* restart loses what they set. It is not a derived value, which is what M4
|
package/src/mesh/instances.ts
CHANGED
|
@@ -34,7 +34,7 @@ export function clusterView(
|
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
/** The `instances` topic (§7.5).
|
|
37
|
+
/** The `instances` topic (DESIGN §7.5).
|
|
38
38
|
*
|
|
39
39
|
* A link going down reaches a subscriber where it is already listening, rather
|
|
40
40
|
* than only on its next greeting. The value is whole per instance: `reachable`
|
|
@@ -43,7 +43,7 @@ export function clusterView(
|
|
|
43
43
|
* one sender's view entire and leaves every other sender's alone.
|
|
44
44
|
*
|
|
45
45
|
* Nothing is started or stopped by a subscription. The view exists because the
|
|
46
|
-
* mesh exists, and reading it costs a walk over the configured peers (§6.3:
|
|
46
|
+
* mesh exists, and reading it costs a walk over the configured peers (DESIGN §6.3:
|
|
47
47
|
* what subscription drives is a watch, and there is none here). */
|
|
48
48
|
export class Instances implements UpstreamResource {
|
|
49
49
|
constructor(
|
package/src/mesh/keys.ts
CHANGED
|
@@ -16,17 +16,17 @@ export const MESH_VER = 1;
|
|
|
16
16
|
*
|
|
17
17
|
* A set rather than one name, because the JWS header is not trusted: the header
|
|
18
18
|
* names an algorithm and this is what decides whether that name may be used at
|
|
19
|
-
* all, which is what stops `alg: none` and algorithm confusion (§5.7-7). Two
|
|
19
|
+
* all, which is what stops `alg: none` and algorithm confusion (mesh-peer-auth §5.7-7). Two
|
|
20
20
|
* entries have to be expressible for a migration, so it is a set even while it
|
|
21
21
|
* holds one. */
|
|
22
22
|
export const ALLOWED_ALGS: ReadonlySet<string> = new Set(["EdDSA"]);
|
|
23
23
|
|
|
24
|
-
/** How long a proof stays valid (§5.9). A handshake within one region completes
|
|
24
|
+
/** How long a proof stays valid (mesh-peer-auth §5.9). A handshake within one region completes
|
|
25
25
|
* in tens to hundreds of milliseconds, and a peer that cannot manage this could
|
|
26
26
|
* not hold a mesh link anyway. */
|
|
27
27
|
export const PROOF_LIFETIME_MS = 10_000;
|
|
28
28
|
|
|
29
|
-
/** 128 bits, the floor §5.9 sets for both the challenge and the key id: the only
|
|
29
|
+
/** 128 bits, the floor mesh-peer-auth §5.9 sets for both the challenge and the key id: the only
|
|
30
30
|
* requirement on either is that it cannot be predicted. */
|
|
31
31
|
const RANDOM_BYTES = 16;
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ export function randomId(): string {
|
|
|
38
38
|
*
|
|
39
39
|
* The id is on the key because the receiver compares three of them — the
|
|
40
40
|
* greeting's, the proof header's, and this one — and a key that arrived without
|
|
41
|
-
* its own id could not be part of that comparison (§5.7-8). */
|
|
41
|
+
* its own id could not be part of that comparison (mesh-peer-auth §5.7-8). */
|
|
42
42
|
export interface MeshJwk {
|
|
43
43
|
readonly kty: string;
|
|
44
44
|
readonly crv?: string;
|
|
@@ -50,7 +50,7 @@ export interface MeshJwk {
|
|
|
50
50
|
*
|
|
51
51
|
* It lives as long as the handshake it was made for: created when the dial
|
|
52
52
|
* starts, fetched once by the peer, and destroyed when the acknowledgement
|
|
53
|
-
* arrives or the connection goes, whichever comes first (§7). Nothing rotates
|
|
53
|
+
* arrives or the connection goes, whichever comes first (mesh-peer-auth §7). Nothing rotates
|
|
54
54
|
* it because nothing outlives one connection. */
|
|
55
55
|
export class EphemeralKey {
|
|
56
56
|
readonly kid = randomId();
|
|
@@ -67,7 +67,7 @@ export class EphemeralKey {
|
|
|
67
67
|
return { ...(this.#public.export({ format: "jwk" }) as object), kid: this.kid } as MeshJwk;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
/** The proof of §5.4: the challenge, and the two endpoint URLs, signed.
|
|
70
|
+
/** The proof of mesh-peer-auth §5.4: the challenge, and the two endpoint URLs, signed.
|
|
71
71
|
*
|
|
72
72
|
* The URLs are signed even though the greeting already carried them, because
|
|
73
73
|
* the greeting is not signed and therefore states nothing. */
|
|
@@ -102,7 +102,7 @@ export class ProofError extends Error {}
|
|
|
102
102
|
* with an algorithm outside the allowed set.
|
|
103
103
|
*
|
|
104
104
|
* The algorithm is checked here, before the key is even looked at, because the
|
|
105
|
-
* check exists to decide whether the header may be acted on at all (§5.7-7). */
|
|
105
|
+
* check exists to decide whether the header may be acted on at all (mesh-peer-auth §5.7-7). */
|
|
106
106
|
export function parseProof(jws: string): ParsedProof {
|
|
107
107
|
const parts = jws.split(".");
|
|
108
108
|
if (parts.length !== 3) throw new ProofError("a proof is a compact JWS of three parts");
|