cc-peer 1.3.5 → 1.4.1
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 +26 -0
- package/dist/adapters/node/alias-worker.cjs +42 -0
- package/dist/adapters/node/alias-worker.d.cts +1 -0
- package/dist/adapters/node/alias-worker.d.mts +1 -0
- package/dist/adapters/node/alias-worker.mjs +41 -0
- package/dist/alias-ipc-Cjs5yivH.cjs +48 -0
- package/dist/alias-ipc-DkaozCo7.mjs +31 -0
- package/dist/alias-pool.cjs +162 -0
- package/dist/alias-pool.d.cts +51 -0
- package/dist/alias-pool.d.mts +51 -0
- package/dist/alias-pool.mjs +160 -0
- package/dist/bin/cc-peer.cjs +10 -30
- package/dist/bin/cc-peer.mjs +2 -1
- package/dist/{cc-peer-CJqStHIL.mjs → cc-peer-CbnScbXe.mjs} +2 -46
- package/dist/cc-peer-DFoi9JJV.d.cts +310 -0
- package/dist/cc-peer-DFoi9JJV.d.mts +310 -0
- package/dist/{cc-peer-CXzxAUE4.cjs → cc-peer-D_3Bw_NE.cjs} +28 -78
- package/dist/cc-peer.cjs +1 -1
- package/dist/cc-peer.d.cts +2 -309
- package/dist/cc-peer.d.mts +2 -309
- package/dist/cc-peer.mjs +1 -1
- package/dist/errors-Dcqq2MIW.mjs +53 -0
- package/dist/errors-Dl_lSq1N.cjs +88 -0
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/docs/PROTOCOL.md +9 -0
- package/package.json +12 -2
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/adapters/node/paths.d.ts
|
|
4
|
+
interface PathConfig {
|
|
5
|
+
homeDir?: string;
|
|
6
|
+
socketDir?: string;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/ports/transport.d.ts
|
|
10
|
+
/** Transport port: per-exchange connections and the listening inbox. */
|
|
11
|
+
interface Transport {
|
|
12
|
+
/**
|
|
13
|
+
* One connection, one write of the given lines (each newline-terminated), then close after a short linger. Mirrors the reference client's `Pe`.
|
|
14
|
+
*/
|
|
15
|
+
connectWrite: (socketPath: string, lines: readonly string[], lingerMs?: number) => Promise<void>;
|
|
16
|
+
/** Probe whether a socket accepts connections (roster admission uses this). */
|
|
17
|
+
probe: (socketPath: string) => Promise<boolean>;
|
|
18
|
+
listen: (socketPath: string, onConnection: (conn: Readonly<InboundConnection>) => void) => Promise<ListeningSocket>;
|
|
19
|
+
}
|
|
20
|
+
interface InboundConnection {
|
|
21
|
+
/** Resolves once the kernel reports the connecting process's pid (macOS). */
|
|
22
|
+
peerPid: () => number | undefined;
|
|
23
|
+
readLines: () => AsyncIterable<string>;
|
|
24
|
+
close: () => void;
|
|
25
|
+
}
|
|
26
|
+
interface ListeningSocket {
|
|
27
|
+
socketPath: string;
|
|
28
|
+
close: () => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/schemas/registry.d.ts
|
|
32
|
+
/** One entry of the ~/.claude/sessions/<pid>.json registry. */
|
|
33
|
+
declare const RegistryEntrySchema: z.ZodObject<{
|
|
34
|
+
pid: z.ZodNumber;
|
|
35
|
+
sessionId: z.ZodString;
|
|
36
|
+
cwd: z.ZodString;
|
|
37
|
+
startedAt: z.ZodNumber;
|
|
38
|
+
procStart: z.ZodString;
|
|
39
|
+
version: z.ZodString;
|
|
40
|
+
peerProtocol: z.ZodNumber;
|
|
41
|
+
peerFeatures: z.ZodArray<z.ZodEnum<{
|
|
42
|
+
notify_idle: "notify_idle";
|
|
43
|
+
reply_across_default_dirs: "reply_across_default_dirs";
|
|
44
|
+
artifact_yield: "artifact_yield";
|
|
45
|
+
}> & {
|
|
46
|
+
is(value: unknown): value is "notify_idle" | "reply_across_default_dirs" | "artifact_yield";
|
|
47
|
+
}>;
|
|
48
|
+
kind: z.ZodEnum<{
|
|
49
|
+
interactive: "interactive";
|
|
50
|
+
bg: "bg";
|
|
51
|
+
daemon: "daemon";
|
|
52
|
+
"daemon-worker": "daemon-worker";
|
|
53
|
+
}> & {
|
|
54
|
+
is(value: unknown): value is "interactive" | "bg" | "daemon" | "daemon-worker";
|
|
55
|
+
};
|
|
56
|
+
entrypoint: z.ZodString;
|
|
57
|
+
pidDomain: z.ZodString;
|
|
58
|
+
messagingSocketPath: z.ZodString;
|
|
59
|
+
name: z.ZodOptional<z.ZodString>;
|
|
60
|
+
nameSource: z.ZodOptional<z.ZodEnum<{
|
|
61
|
+
user: "user";
|
|
62
|
+
peer: "peer";
|
|
63
|
+
derived: "derived";
|
|
64
|
+
collision: "collision";
|
|
65
|
+
auto: "auto";
|
|
66
|
+
hook: "hook";
|
|
67
|
+
}> & {
|
|
68
|
+
is(value: unknown): value is "user" | "peer" | "derived" | "collision" | "auto" | "hook";
|
|
69
|
+
}>;
|
|
70
|
+
nameSince: z.ZodOptional<z.ZodNumber>;
|
|
71
|
+
updatedAt: z.ZodNumber;
|
|
72
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
73
|
+
idle: "idle";
|
|
74
|
+
busy: "busy";
|
|
75
|
+
shell: "shell";
|
|
76
|
+
waiting: "waiting";
|
|
77
|
+
}> & {
|
|
78
|
+
is(value: unknown): value is "idle" | "busy" | "shell" | "waiting";
|
|
79
|
+
}>;
|
|
80
|
+
statusUpdatedAt: z.ZodOptional<z.ZodNumber>;
|
|
81
|
+
bridgeSessionId: z.ZodOptional<z.ZodString>;
|
|
82
|
+
}, z.core.$strip> & {
|
|
83
|
+
is(value: unknown): value is {
|
|
84
|
+
pid: number;
|
|
85
|
+
sessionId: string;
|
|
86
|
+
cwd: string;
|
|
87
|
+
startedAt: number;
|
|
88
|
+
procStart: string;
|
|
89
|
+
version: string;
|
|
90
|
+
peerProtocol: number;
|
|
91
|
+
peerFeatures: ("notify_idle" | "reply_across_default_dirs" | "artifact_yield")[];
|
|
92
|
+
kind: "interactive" | "bg" | "daemon" | "daemon-worker";
|
|
93
|
+
entrypoint: string;
|
|
94
|
+
pidDomain: string;
|
|
95
|
+
messagingSocketPath: string;
|
|
96
|
+
updatedAt: number;
|
|
97
|
+
name?: string | undefined;
|
|
98
|
+
nameSource?: "user" | "peer" | "derived" | "collision" | "auto" | "hook" | undefined;
|
|
99
|
+
nameSince?: number | undefined;
|
|
100
|
+
status?: "idle" | "busy" | "shell" | "waiting" | undefined;
|
|
101
|
+
statusUpdatedAt?: number | undefined;
|
|
102
|
+
bridgeSessionId?: string | undefined;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
type RegistryEntry = z.infer<typeof RegistryEntrySchema>;
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/ports/registry-store.d.ts
|
|
108
|
+
/** Registry port: the ~/.claude/sessions/<pid>.json store. */
|
|
109
|
+
interface RegistryStore {
|
|
110
|
+
list: () => Promise<RegistryEntry[]>;
|
|
111
|
+
read: (pid: number) => Promise<RegistryEntry | undefined>;
|
|
112
|
+
write: (entry: RegistryEntry) => Promise<void>;
|
|
113
|
+
/** Heartbeat: bump updatedAt/statusUpdatedAt without rewriting the rest. */
|
|
114
|
+
touch: (pid: number) => Promise<void>;
|
|
115
|
+
remove: (pid: number) => Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/schemas/keyfile.d.ts
|
|
119
|
+
/** The auth key a session publishes next to its socket. */
|
|
120
|
+
declare const PeerKeyFileSchema: z.ZodObject<{
|
|
121
|
+
peerToken: z.ZodString;
|
|
122
|
+
procStart: z.ZodString;
|
|
123
|
+
pidDomain: z.ZodString;
|
|
124
|
+
}, z.core.$strip> & {
|
|
125
|
+
is(value: unknown): value is {
|
|
126
|
+
peerToken: string;
|
|
127
|
+
procStart: string;
|
|
128
|
+
pidDomain: string;
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
type PeerKeyFile = z.infer<typeof PeerKeyFileSchema>;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/ports/key-store.d.ts
|
|
134
|
+
/** Key-store port: auth keys published next to each session socket. */
|
|
135
|
+
interface KeyStore {
|
|
136
|
+
readForSocket: (socketPath: string) => Promise<PeerKeyFile | undefined>;
|
|
137
|
+
/** Write our own key file for the socket we own. */
|
|
138
|
+
writeForSocket: (socketPath: string, keyFile: Readonly<PeerKeyFile>) => Promise<void>;
|
|
139
|
+
removeForSocket: (socketPath: string) => Promise<void>;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/ports/proc-info.d.ts
|
|
143
|
+
/** Process-info port: the liveness and proc-start facts the roster needs. */
|
|
144
|
+
interface ProcInfo {
|
|
145
|
+
alive: (pid: number) => Promise<boolean>;
|
|
146
|
+
/**
|
|
147
|
+
* The process start string, byte-equal to `LC_ALL=C TZ=UTC ps -o lstart=` output — the exact value the receiver's registry byte-compares against.
|
|
148
|
+
*/
|
|
149
|
+
lstart: (pid: number) => Promise<string | undefined>;
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/ports/clock.d.ts
|
|
153
|
+
/** Clock port: injectable time for pacer/refill and freshness windows. */
|
|
154
|
+
interface Clock {
|
|
155
|
+
nowMs: () => number;
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region src/schemas/wire.d.ts
|
|
159
|
+
declare const PeerMessageStatusSchema: z.ZodObject<{
|
|
160
|
+
type: z.ZodLiteral<"control">;
|
|
161
|
+
action: z.ZodLiteral<"peer_message_status">;
|
|
162
|
+
status: z.ZodEnum<{
|
|
163
|
+
held: "held";
|
|
164
|
+
delivered: "delivered";
|
|
165
|
+
denied: "denied";
|
|
166
|
+
expired: "expired";
|
|
167
|
+
dropped: "dropped";
|
|
168
|
+
}>;
|
|
169
|
+
reason: z.ZodString;
|
|
170
|
+
from: z.ZodString;
|
|
171
|
+
orig_msg_id: z.ZodString;
|
|
172
|
+
status_detail: z.ZodOptional<z.ZodString>;
|
|
173
|
+
drop_reason: z.ZodOptional<z.ZodEnum<{
|
|
174
|
+
"rate-limited": "rate-limited";
|
|
175
|
+
duplicate: "duplicate";
|
|
176
|
+
"hop-loop": "hop-loop";
|
|
177
|
+
"hop-runaway": "hop-runaway";
|
|
178
|
+
"queue-full": "queue-full";
|
|
179
|
+
}> & {
|
|
180
|
+
is(value: unknown): value is "rate-limited" | "duplicate" | "hop-loop" | "hop-runaway" | "queue-full";
|
|
181
|
+
}>;
|
|
182
|
+
dropped_msg_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
183
|
+
msgV: z.ZodNumber;
|
|
184
|
+
msg_id: z.ZodString;
|
|
185
|
+
}, z.core.$strip> & {
|
|
186
|
+
is(value: unknown): value is {
|
|
187
|
+
type: "control";
|
|
188
|
+
action: "peer_message_status";
|
|
189
|
+
status: "held" | "delivered" | "denied" | "expired" | "dropped";
|
|
190
|
+
reason: string;
|
|
191
|
+
from: string;
|
|
192
|
+
orig_msg_id: string;
|
|
193
|
+
msgV: number;
|
|
194
|
+
msg_id: string;
|
|
195
|
+
status_detail?: string | undefined;
|
|
196
|
+
drop_reason?: "rate-limited" | "duplicate" | "hop-loop" | "hop-runaway" | "queue-full" | undefined;
|
|
197
|
+
dropped_msg_ids?: string[] | undefined;
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
type PeerMessageStatus = z.infer<typeof PeerMessageStatusSchema>;
|
|
201
|
+
declare const PeerIdleNoticeSchema: z.ZodObject<{
|
|
202
|
+
type: z.ZodLiteral<"control">;
|
|
203
|
+
action: z.ZodLiteral<"peer_idle_notice">;
|
|
204
|
+
orig_msg_id: z.ZodString;
|
|
205
|
+
state: z.ZodEnum<{
|
|
206
|
+
idle: "idle";
|
|
207
|
+
exited: "exited";
|
|
208
|
+
}>;
|
|
209
|
+
finished_at: z.ZodNumber;
|
|
210
|
+
detail: z.ZodOptional<z.ZodString>;
|
|
211
|
+
from: z.ZodString;
|
|
212
|
+
from_mode: z.ZodOptional<z.ZodEnum<{
|
|
213
|
+
bypass: "bypass";
|
|
214
|
+
prompting: "prompting";
|
|
215
|
+
}>>;
|
|
216
|
+
msgV: z.ZodNumber;
|
|
217
|
+
msg_id: z.ZodString;
|
|
218
|
+
}, z.core.$strip> & {
|
|
219
|
+
is(value: unknown): value is {
|
|
220
|
+
type: "control";
|
|
221
|
+
action: "peer_idle_notice";
|
|
222
|
+
orig_msg_id: string;
|
|
223
|
+
state: "idle" | "exited";
|
|
224
|
+
finished_at: number;
|
|
225
|
+
from: string;
|
|
226
|
+
msgV: number;
|
|
227
|
+
msg_id: string;
|
|
228
|
+
detail?: string | undefined;
|
|
229
|
+
from_mode?: "bypass" | "prompting" | undefined;
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
type PeerIdleNotice = z.infer<typeof PeerIdleNoticeSchema>;
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/cc-peer.d.ts
|
|
235
|
+
/** Package version placeholder until semantic-release owns it. */
|
|
236
|
+
declare const CC_PEER_VERSION = "0.0.0";
|
|
237
|
+
/** How a target can be addressed. */
|
|
238
|
+
type PeerRef = {
|
|
239
|
+
pid: number;
|
|
240
|
+
} | {
|
|
241
|
+
name: string;
|
|
242
|
+
} | {
|
|
243
|
+
address: string;
|
|
244
|
+
};
|
|
245
|
+
interface CcPeerOptions extends PathConfig {
|
|
246
|
+
name?: string;
|
|
247
|
+
sessionId?: string;
|
|
248
|
+
heartbeatMs?: number;
|
|
249
|
+
logger?: (message: string) => void;
|
|
250
|
+
}
|
|
251
|
+
interface SendOptions {
|
|
252
|
+
priority?: "next" | "later";
|
|
253
|
+
/** Attaches from-mode attestation; false deliberately sends unattested (recipient holds it). */
|
|
254
|
+
fromMode?: "bypass" | "prompting" | false;
|
|
255
|
+
/** When set, must match the receiver's sessionId or the frame is silently dropped. */
|
|
256
|
+
sessionId?: string;
|
|
257
|
+
}
|
|
258
|
+
interface InboundMessage {
|
|
259
|
+
from?: string;
|
|
260
|
+
fromSession?: string;
|
|
261
|
+
fromName?: string;
|
|
262
|
+
fromMode?: "bypass" | "prompting";
|
|
263
|
+
hopChain?: string[];
|
|
264
|
+
body: string;
|
|
265
|
+
msgId: string;
|
|
266
|
+
}
|
|
267
|
+
type Receipt = PeerMessageStatus;
|
|
268
|
+
type IdleNotice = PeerIdleNotice;
|
|
269
|
+
interface Deps {
|
|
270
|
+
transport: Transport;
|
|
271
|
+
registry: RegistryStore;
|
|
272
|
+
keys: KeyStore;
|
|
273
|
+
procInfo: ProcInfo;
|
|
274
|
+
clock: Clock;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* A registered peer on Claude Code's cross-session mesh. Receipts and idle notices only reach the process that owns the listening socket (the protocol verifies return addresses via kernel peer pids), so do not split sending and listening across differently-owned processes.
|
|
278
|
+
*/
|
|
279
|
+
declare class CcPeer extends EventEmitter {
|
|
280
|
+
private readonly options;
|
|
281
|
+
private readonly deps;
|
|
282
|
+
private listening;
|
|
283
|
+
private heartbeatTimer;
|
|
284
|
+
private ownKey;
|
|
285
|
+
private readonly pacer;
|
|
286
|
+
private readonly log;
|
|
287
|
+
private stopped;
|
|
288
|
+
constructor(options: Readonly<CcPeerOptions>, deps: Deps);
|
|
289
|
+
static create(options?: Readonly<CcPeerOptions>): Promise<CcPeer>;
|
|
290
|
+
/**
|
|
291
|
+
* Bind, publish key and registry, and begin listening. Public rather than private because dependency-injected construction (this constructor takes the full Deps) needs to trigger it explicitly; everyday callers use the static create(), which wires the real node adapters.
|
|
292
|
+
*/
|
|
293
|
+
start(): Promise<void>;
|
|
294
|
+
/** procStart is a required parameter, not read from this.ownKey: start() already guarantees a non-empty value before this is called, so the type checker enforces it rather than a runtime fallback that can never actually fire. */
|
|
295
|
+
private buildRegistryEntry;
|
|
296
|
+
roster(): Promise<RegistryEntry[]>;
|
|
297
|
+
send(target: PeerRef, body: string, options?: Readonly<SendOptions>): Promise<{
|
|
298
|
+
msgId: string;
|
|
299
|
+
}>;
|
|
300
|
+
private pacedSend;
|
|
301
|
+
subscribeIdle(target: PeerRef): Promise<{
|
|
302
|
+
msgId: string;
|
|
303
|
+
}>;
|
|
304
|
+
private resolveTarget;
|
|
305
|
+
/** ownToken is passed explicitly rather than read from this.ownKey: the listener callback that invokes this is only ever registered after start() has set ownKey, so the parameter records that guarantee at the type level instead of a runtime guard that can never actually be false. */
|
|
306
|
+
private handleConnection;
|
|
307
|
+
stop(): Promise<void>;
|
|
308
|
+
}
|
|
309
|
+
//#endregion
|
|
310
|
+
export { InboundMessage as a, SendOptions as c, IdleNotice as i, PathConfig as l, CcPeer as n, PeerRef as o, CcPeerOptions as r, Receipt as s, CC_PEER_VERSION as t };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_errors = require("./errors-Dl_lSq1N.cjs");
|
|
1
2
|
let node_events = require("node:events");
|
|
2
3
|
let node_crypto = require("node:crypto");
|
|
3
4
|
let node_net = require("node:net");
|
|
@@ -129,16 +130,6 @@ var SystemClock = class {
|
|
|
129
130
|
return Date.now();
|
|
130
131
|
}
|
|
131
132
|
};
|
|
132
|
-
//#endregion
|
|
133
|
-
//#region src/schemas/define-schema.ts
|
|
134
|
-
/**
|
|
135
|
-
* Attach an `.is()` type guard to a Zod schema so schema, inferred type, and runtime guard derive from one definition (single source of truth). `Schema.parse()` at JSON boundaries; `Schema.is()` for narrowing.
|
|
136
|
-
*/
|
|
137
|
-
function defineSchema(schema) {
|
|
138
|
-
return Object.assign(schema, { is(value) {
|
|
139
|
-
return schema.safeParse(value).success;
|
|
140
|
-
} });
|
|
141
|
-
}
|
|
142
133
|
const hex = (bytes) => bytes * 2;
|
|
143
134
|
const PEER_TOKEN_HEX_LENGTH = hex(16);
|
|
144
135
|
const HOP_ID_HEX_LENGTH = hex(12);
|
|
@@ -150,7 +141,7 @@ const count = (n) => String(n);
|
|
|
150
141
|
//#endregion
|
|
151
142
|
//#region src/schemas/keyfile.ts
|
|
152
143
|
/** The auth key a session publishes next to its socket. */
|
|
153
|
-
const PeerKeyFileSchema = defineSchema(zod.z.object({
|
|
144
|
+
const PeerKeyFileSchema = require_errors.defineSchema(zod.z.object({
|
|
154
145
|
peerToken: zod.z.string().regex(new RegExp(`^[0-9a-f]{${count(PEER_TOKEN_HEX_LENGTH)}}$`)),
|
|
155
146
|
procStart: zod.z.string().min(1),
|
|
156
147
|
pidDomain: zod.z.string().min(1)
|
|
@@ -260,7 +251,7 @@ var FsKeyStore = class {
|
|
|
260
251
|
//#endregion
|
|
261
252
|
//#region src/schemas/registry.ts
|
|
262
253
|
/** Whitelist the receiver applies on read; other values parse to undefined. */
|
|
263
|
-
const NameSourceSchema = defineSchema(zod.z.enum([
|
|
254
|
+
const NameSourceSchema = require_errors.defineSchema(zod.z.enum([
|
|
264
255
|
"user",
|
|
265
256
|
"peer",
|
|
266
257
|
"derived",
|
|
@@ -268,25 +259,25 @@ const NameSourceSchema = defineSchema(zod.z.enum([
|
|
|
268
259
|
"auto",
|
|
269
260
|
"hook"
|
|
270
261
|
]));
|
|
271
|
-
const PeerStatusSchema = defineSchema(zod.z.enum([
|
|
262
|
+
const PeerStatusSchema = require_errors.defineSchema(zod.z.enum([
|
|
272
263
|
"busy",
|
|
273
264
|
"shell",
|
|
274
265
|
"idle",
|
|
275
266
|
"waiting"
|
|
276
267
|
]));
|
|
277
|
-
const SessionKindSchema = defineSchema(zod.z.enum([
|
|
268
|
+
const SessionKindSchema = require_errors.defineSchema(zod.z.enum([
|
|
278
269
|
"interactive",
|
|
279
270
|
"bg",
|
|
280
271
|
"daemon",
|
|
281
272
|
"daemon-worker"
|
|
282
273
|
]));
|
|
283
|
-
const PeerFeatureSchema = defineSchema(zod.z.enum([
|
|
274
|
+
const PeerFeatureSchema = require_errors.defineSchema(zod.z.enum([
|
|
284
275
|
"notify_idle",
|
|
285
276
|
"reply_across_default_dirs",
|
|
286
277
|
"artifact_yield"
|
|
287
278
|
]));
|
|
288
279
|
/** One entry of the ~/.claude/sessions/<pid>.json registry. */
|
|
289
|
-
const RegistryEntrySchema = defineSchema(zod.z.object({
|
|
280
|
+
const RegistryEntrySchema = require_errors.defineSchema(zod.z.object({
|
|
290
281
|
pid: zod.z.number().int().positive(),
|
|
291
282
|
sessionId: zod.z.string().min(1),
|
|
292
283
|
cwd: zod.z.string(),
|
|
@@ -479,10 +470,10 @@ var WinProcInfo = class {
|
|
|
479
470
|
/**
|
|
480
471
|
* Grammar of the <cross-session-message> envelope attributes, mirroring the receiver's own parser. The serialized attribute ORDER is canonical (from, from-session, hop-chain, from-name, from-mode): the receiver's regex matches that sequence only, so any other order parses as nothing.
|
|
481
472
|
*/
|
|
482
|
-
const EnvelopeAddressSchema = defineSchema(zod.z.string().regex(new RegExp(`^[A-Za-z0-9%:_/.\\\\-]{1,${count(300)}}$`)));
|
|
483
|
-
const FromModeSchema = defineSchema(zod.z.enum(["bypass", "prompting"]));
|
|
473
|
+
const EnvelopeAddressSchema = require_errors.defineSchema(zod.z.string().regex(new RegExp(`^[A-Za-z0-9%:_/.\\\\-]{1,${count(300)}}$`)));
|
|
474
|
+
const FromModeSchema = require_errors.defineSchema(zod.z.enum(["bypass", "prompting"]));
|
|
484
475
|
const HopIdSchema = zod.z.string().regex(new RegExp(`^[0-9a-f]{${count(HOP_ID_HEX_LENGTH)}}$`));
|
|
485
|
-
const EnvelopeAttributesSchema = defineSchema(zod.z.object({
|
|
476
|
+
const EnvelopeAttributesSchema = require_errors.defineSchema(zod.z.object({
|
|
486
477
|
from: EnvelopeAddressSchema,
|
|
487
478
|
fromSession: zod.z.string().regex(new RegExp(`^[A-Za-z0-9_-]{1,${count(80)}}$`)).optional(),
|
|
488
479
|
/** Parsed hop chain: at most 32 ids at the grammar level. */
|
|
@@ -616,12 +607,12 @@ async function checkEntry(entry, probes) {
|
|
|
616
607
|
//#endregion
|
|
617
608
|
//#region src/schemas/wire.ts
|
|
618
609
|
/** Line 1 of every connection: the receiver's own peerToken (peer class) or childToken (self-sent class). */
|
|
619
|
-
const AuthLineSchema = defineSchema(zod.z.object({
|
|
610
|
+
const AuthLineSchema = require_errors.defineSchema(zod.z.object({
|
|
620
611
|
type: zod.z.literal("auth"),
|
|
621
612
|
token: zod.z.string().regex(new RegExp(`^[0-9a-f]{${count(PEER_TOKEN_HEX_LENGTH)}}$`))
|
|
622
613
|
}));
|
|
623
|
-
const PrioritySchema = defineSchema(zod.z.enum(["next", "later"]));
|
|
624
|
-
const FileAttachmentSchema = defineSchema(zod.z.object({
|
|
614
|
+
const PrioritySchema = require_errors.defineSchema(zod.z.enum(["next", "later"]));
|
|
615
|
+
const FileAttachmentSchema = require_errors.defineSchema(zod.z.object({
|
|
625
616
|
path: zod.z.string().min(1),
|
|
626
617
|
file_name: zod.z.string().min(1),
|
|
627
618
|
file_size: zod.z.number().int().nonnegative(),
|
|
@@ -629,7 +620,7 @@ const FileAttachmentSchema = defineSchema(zod.z.object({
|
|
|
629
620
|
media_type: zod.z.string().optional()
|
|
630
621
|
}));
|
|
631
622
|
/** A user-turn message. `"type": "user"` is load-bearing: any other value is silently dropped. */
|
|
632
|
-
const UserFrameSchema = defineSchema(zod.z.object({
|
|
623
|
+
const UserFrameSchema = require_errors.defineSchema(zod.z.object({
|
|
633
624
|
msgV: zod.z.number().int(),
|
|
634
625
|
msg_id: zod.z.string().min(1),
|
|
635
626
|
type: zod.z.literal("user"),
|
|
@@ -643,14 +634,14 @@ const UserFrameSchema = defineSchema(zod.z.object({
|
|
|
643
634
|
session_id: zod.z.string().optional(),
|
|
644
635
|
file_attachments: zod.z.array(FileAttachmentSchema).max(16).optional()
|
|
645
636
|
}));
|
|
646
|
-
const DropReasonSchema = defineSchema(zod.z.enum([
|
|
637
|
+
const DropReasonSchema = require_errors.defineSchema(zod.z.enum([
|
|
647
638
|
"rate-limited",
|
|
648
639
|
"duplicate",
|
|
649
640
|
"hop-loop",
|
|
650
641
|
"hop-runaway",
|
|
651
642
|
"queue-full"
|
|
652
643
|
]));
|
|
653
|
-
const PeerMessageStatusSchema = defineSchema(zod.z.object({
|
|
644
|
+
const PeerMessageStatusSchema = require_errors.defineSchema(zod.z.object({
|
|
654
645
|
type: zod.z.literal("control"),
|
|
655
646
|
action: zod.z.literal("peer_message_status"),
|
|
656
647
|
status: zod.z.enum([
|
|
@@ -669,7 +660,7 @@ const PeerMessageStatusSchema = defineSchema(zod.z.object({
|
|
|
669
660
|
msgV: zod.z.number().int(),
|
|
670
661
|
msg_id: zod.z.string().min(1)
|
|
671
662
|
}));
|
|
672
|
-
const NotifyWhenIdleSchema = defineSchema(zod.z.object({
|
|
663
|
+
const NotifyWhenIdleSchema = require_errors.defineSchema(zod.z.object({
|
|
673
664
|
type: zod.z.literal("control"),
|
|
674
665
|
action: zod.z.literal("notify_when_idle"),
|
|
675
666
|
from: zod.z.string().regex(new RegExp(`^[A-Za-z0-9%:_/.\\\\-]{1,${count(300)}}$`)),
|
|
@@ -677,7 +668,7 @@ const NotifyWhenIdleSchema = defineSchema(zod.z.object({
|
|
|
677
668
|
msgV: zod.z.number().int(),
|
|
678
669
|
msg_id: zod.z.string().min(1)
|
|
679
670
|
}));
|
|
680
|
-
const PeerIdleNoticeSchema = defineSchema(zod.z.object({
|
|
671
|
+
const PeerIdleNoticeSchema = require_errors.defineSchema(zod.z.object({
|
|
681
672
|
type: zod.z.literal("control"),
|
|
682
673
|
action: zod.z.literal("peer_idle_notice"),
|
|
683
674
|
orig_msg_id: zod.z.string().min(1),
|
|
@@ -691,7 +682,7 @@ const PeerIdleNoticeSchema = defineSchema(zod.z.object({
|
|
|
691
682
|
}));
|
|
692
683
|
/** Bare enum, exported separately so a test can assert its own membership directly rather than through the object field's .catch("claim") fallback, which would otherwise mask a corrupted "claim" member by coincidentally recovering the same value. */
|
|
693
684
|
const YieldReasonSchema = zod.z.enum(["resume", "claim"]);
|
|
694
|
-
const YieldArtifactRepliesSchema = defineSchema(zod.z.object({
|
|
685
|
+
const YieldArtifactRepliesSchema = require_errors.defineSchema(zod.z.object({
|
|
695
686
|
type: zod.z.literal("control"),
|
|
696
687
|
action: zod.z.literal("yield_artifact_replies"),
|
|
697
688
|
from: zod.z.string().max(512),
|
|
@@ -707,7 +698,7 @@ const YieldArtifactRepliesSchema = defineSchema(zod.z.object({
|
|
|
707
698
|
}).optional(),
|
|
708
699
|
msgV: zod.z.number().int()
|
|
709
700
|
}));
|
|
710
|
-
const ArtifactRepliesYieldedSchema = defineSchema(zod.z.object({
|
|
701
|
+
const ArtifactRepliesYieldedSchema = require_errors.defineSchema(zod.z.object({
|
|
711
702
|
type: zod.z.literal("control"),
|
|
712
703
|
action: zod.z.literal("artifact_replies_yielded"),
|
|
713
704
|
orig_msg_id: zod.z.string().max(128),
|
|
@@ -718,7 +709,7 @@ const ArtifactRepliesYieldedSchema = defineSchema(zod.z.object({
|
|
|
718
709
|
msg_id: zod.z.string().min(1),
|
|
719
710
|
from: zod.z.string().optional()
|
|
720
711
|
}));
|
|
721
|
-
const UnyieldArtifactRepliesSchema = defineSchema(zod.z.object({
|
|
712
|
+
const UnyieldArtifactRepliesSchema = require_errors.defineSchema(zod.z.object({
|
|
722
713
|
type: zod.z.literal("control"),
|
|
723
714
|
action: zod.z.literal("unyield_artifact_replies"),
|
|
724
715
|
orig_msg_id: zod.z.string().max(128),
|
|
@@ -738,41 +729,6 @@ const ControlFrameSchema = zod.z.union([
|
|
|
738
729
|
]);
|
|
739
730
|
const WireFrameSchema = zod.z.union([UserFrameSchema, ControlFrameSchema]);
|
|
740
731
|
//#endregion
|
|
741
|
-
//#region src/errors.ts
|
|
742
|
-
/** Base error for every cc-peer failure; `code` is machine-readable. */
|
|
743
|
-
var CcPeerError = class extends Error {
|
|
744
|
-
code;
|
|
745
|
-
constructor(code, message) {
|
|
746
|
-
super(message);
|
|
747
|
-
this.code = code;
|
|
748
|
-
this.name = "CcPeerError";
|
|
749
|
-
}
|
|
750
|
-
};
|
|
751
|
-
var NoLiveInboxError = class extends CcPeerError {
|
|
752
|
-
constructor(message) {
|
|
753
|
-
super("NO_LIVE_INBOX", message);
|
|
754
|
-
this.name = "NoLiveInboxError";
|
|
755
|
-
}
|
|
756
|
-
};
|
|
757
|
-
var UnknownPeerError = class extends CcPeerError {
|
|
758
|
-
constructor(message) {
|
|
759
|
-
super("UNKNOWN_PEER", message);
|
|
760
|
-
this.name = "UnknownPeerError";
|
|
761
|
-
}
|
|
762
|
-
};
|
|
763
|
-
var MessageTooLargeError = class extends CcPeerError {
|
|
764
|
-
constructor(message) {
|
|
765
|
-
super("MESSAGE_TOO_LARGE", message);
|
|
766
|
-
this.name = "MessageTooLargeError";
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
var NotStartedError = class extends CcPeerError {
|
|
770
|
-
constructor(message) {
|
|
771
|
-
super("NOT_STARTED", message);
|
|
772
|
-
this.name = "NotStartedError";
|
|
773
|
-
}
|
|
774
|
-
};
|
|
775
|
-
//#endregion
|
|
776
732
|
//#region src/cc-peer.ts
|
|
777
733
|
/** Package version placeholder until semantic-release owns it. */
|
|
778
734
|
const CC_PEER_VERSION = "0.0.0";
|
|
@@ -823,7 +779,7 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
|
|
|
823
779
|
procStart: await this.deps.procInfo.lstart(process.pid) ?? "",
|
|
824
780
|
pidDomain: process.platform
|
|
825
781
|
};
|
|
826
|
-
if (this.ownKey.procStart === "") throw new NotStartedError("could not read own procStart via ps");
|
|
782
|
+
if (this.ownKey.procStart === "") throw new require_errors.NotStartedError("could not read own procStart via ps");
|
|
827
783
|
await this.deps.keys.writeForSocket(socketPath, this.ownKey);
|
|
828
784
|
if (!isWindows()) await (0, node_fs_promises.mkdir)((0, node_path.dirname)(socketPath), {
|
|
829
785
|
recursive: true,
|
|
@@ -875,7 +831,7 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
|
|
|
875
831
|
});
|
|
876
832
|
}
|
|
877
833
|
async send(target, body, options = {}) {
|
|
878
|
-
if (this.stopped || this.listening === void 0 || this.ownKey === void 0) throw new NotStartedError("peer is not running");
|
|
834
|
+
if (this.stopped || this.listening === void 0 || this.ownKey === void 0) throw new require_errors.NotStartedError("peer is not running");
|
|
879
835
|
const socketPath = await this.resolveTarget(target);
|
|
880
836
|
const key = await this.deps.keys.readForSocket(socketPath);
|
|
881
837
|
const msgId = newMsgId();
|
|
@@ -897,13 +853,13 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
|
|
|
897
853
|
priority: options.priority ?? "next",
|
|
898
854
|
from
|
|
899
855
|
};
|
|
900
|
-
if (key === void 0) throw new NoLiveInboxError(`no auth key published for ${socketPath}`);
|
|
856
|
+
if (key === void 0) throw new require_errors.NoLiveInboxError(`no auth key published for ${socketPath}`);
|
|
901
857
|
const auth = AuthLineSchema.parse({
|
|
902
858
|
type: "auth",
|
|
903
859
|
token: key.peerToken
|
|
904
860
|
});
|
|
905
861
|
const line = JSON.stringify(frame);
|
|
906
|
-
if (line.length > MAX_FRAME_CHARS) throw new MessageTooLargeError(`serialized frame is ${line.length.toString()} chars, cap ${MAX_FRAME_CHARS.toString()}`);
|
|
862
|
+
if (line.length > MAX_FRAME_CHARS) throw new require_errors.MessageTooLargeError(`serialized frame is ${line.length.toString()} chars, cap ${MAX_FRAME_CHARS.toString()}`);
|
|
907
863
|
await this.pacedSend(socketPath, [JSON.stringify(auth), line]);
|
|
908
864
|
return { msgId };
|
|
909
865
|
}
|
|
@@ -918,10 +874,10 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
|
|
|
918
874
|
await this.deps.transport.connectWrite(socketPath, lines);
|
|
919
875
|
}
|
|
920
876
|
async subscribeIdle(target) {
|
|
921
|
-
if (this.stopped || this.listening === void 0 || this.ownKey === void 0) throw new NotStartedError("peer is not running");
|
|
877
|
+
if (this.stopped || this.listening === void 0 || this.ownKey === void 0) throw new require_errors.NotStartedError("peer is not running");
|
|
922
878
|
const socketPath = await this.resolveTarget(target);
|
|
923
879
|
const key = await this.deps.keys.readForSocket(socketPath);
|
|
924
|
-
if (key === void 0) throw new NoLiveInboxError(`no auth key published for ${socketPath}`);
|
|
880
|
+
if (key === void 0) throw new require_errors.NoLiveInboxError(`no auth key published for ${socketPath}`);
|
|
925
881
|
const msgId = newMsgId();
|
|
926
882
|
const frame = {
|
|
927
883
|
msgV: 1,
|
|
@@ -942,7 +898,7 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
|
|
|
942
898
|
if ("pid" in target) return socketPathForPid(target.pid, this.options);
|
|
943
899
|
if ("address" in target) return target.address.replace(/^uds:/, "");
|
|
944
900
|
const match = (await this.roster()).find((entry) => entry.name === target.name);
|
|
945
|
-
if (match === void 0) throw new UnknownPeerError(`no roster entry named ${target.name}`);
|
|
901
|
+
if (match === void 0) throw new require_errors.UnknownPeerError(`no roster entry named ${target.name}`);
|
|
946
902
|
return match.messagingSocketPath;
|
|
947
903
|
}
|
|
948
904
|
/** ownToken is passed explicitly rather than read from this.ownKey: the listener callback that invokes this is only ever registered after start() has set ownKey, so the parameter records that guarantee at the type level instead of a runtime guard that can never actually be false. */
|
|
@@ -1019,9 +975,3 @@ Object.defineProperty(exports, "RegistryEntrySchema", {
|
|
|
1019
975
|
return RegistryEntrySchema;
|
|
1020
976
|
}
|
|
1021
977
|
});
|
|
1022
|
-
Object.defineProperty(exports, "defineSchema", {
|
|
1023
|
-
enumerable: true,
|
|
1024
|
-
get: function() {
|
|
1025
|
-
return defineSchema;
|
|
1026
|
-
}
|
|
1027
|
-
});
|
package/dist/cc-peer.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_cc_peer = require("./cc-peer-
|
|
2
|
+
const require_cc_peer = require("./cc-peer-D_3Bw_NE.cjs");
|
|
3
3
|
exports.CC_PEER_VERSION = require_cc_peer.CC_PEER_VERSION;
|
|
4
4
|
exports.CcPeer = require_cc_peer.CcPeer;
|