cc-peer 1.5.3 → 1.6.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 CHANGED
@@ -78,11 +78,19 @@ aliases.on("message", (m) => {
78
78
  // time, give it a reply-able name (idempotent; a no-op if already active).
79
79
  await aliases.ensure("alice");
80
80
 
81
+ // Deliver alice's message to the relayed session from alice's own alias
82
+ // (starting it if needed), so the session sees alice as the sender and its
83
+ // own reply-to-sender comes back on the "message" handler above rather than
84
+ // to the relay. Rejects if the alias cannot start, or if it cannot send.
85
+ const { msgId } = await aliases.send("alice", { pid: relayedSessionPid }, "ping");
86
+
81
87
  // …later, once a correspondent is no longer relevant:
82
88
  await aliases.retire("alice");
83
89
  await aliases.stopAll();
84
90
  ```
85
91
 
92
+ Sending from the alias rather than from the relay's own peer is what makes a relayed session's natural reply reach the right correspondent: a session replies to whoever sent it a message, so a message delivered from the relay comes back to the relay with nothing to say which correspondent it answers.
93
+
86
94
  ## Limitations
87
95
 
88
96
  - **Same-process constraint**: receipts and idle notices only reach the process that owns the peer's listening socket (the protocol verifies return addresses via kernel peer-pids). Do not split `CcPeer` listening and sending across processes or differently-owned workers.
@@ -1,6 +1,7 @@
1
1
  const require_rolldown_runtime = require("../../rolldown-runtime-VH7oDXx4.cjs");
2
- const require_cc_peer = require("../../cc-peer-CPPV05My.cjs");
3
- const require_alias_ipc = require("../../alias-ipc-Cjs5yivH.cjs");
2
+ const require_cc_peer = require("../../cc-peer-BvoaikwI.cjs");
3
+ const require_errors = require("../../errors-BAbklcGw.cjs");
4
+ const require_alias_ipc = require("../../alias-ipc-BPc2wfmz.cjs");
4
5
  let node_process = require("node:process");
5
6
  node_process = require_rolldown_runtime.__toESM(node_process, 1);
6
7
  //#region src/adapters/node/alias-worker.ts
@@ -11,11 +12,25 @@ let peer;
11
12
  node_process.default.on("message", (raw) => {
12
13
  handleCommand(raw);
13
14
  });
15
+ node_process.default.on("disconnect", () => {
16
+ shutdown();
17
+ });
18
+ async function shutdown() {
19
+ await peer?.stop();
20
+ node_process.default.exit(0);
21
+ }
22
+ /** Relays an event to the parent unless its channel has already closed, since a send on a closed channel raises an error event on the process that nothing handles. */
23
+ function relay(message) {
24
+ if (node_process.default.connected) node_process.default.send?.(message);
25
+ }
14
26
  async function handleCommand(raw) {
15
27
  if (!require_alias_ipc.AliasCommandSchema.is(raw)) return;
16
28
  if (raw.type === "stop") {
17
- await peer?.stop();
18
- node_process.default.exit(0);
29
+ await shutdown();
30
+ return;
31
+ }
32
+ if (raw.type === "send") {
33
+ await handleSend(raw);
19
34
  return;
20
35
  }
21
36
  let created;
@@ -32,11 +47,38 @@ async function handleCommand(raw) {
32
47
  }
33
48
  peer = created;
34
49
  peer.on("message", (message) => {
35
- node_process.default.send?.({
50
+ relay({
36
51
  type: "message",
37
52
  ...message
38
53
  });
39
54
  });
40
- node_process.default.send?.({ type: "started" });
55
+ relay({ type: "started" });
56
+ }
57
+ async function handleSend(command) {
58
+ const active = peer;
59
+ if (active === void 0) {
60
+ relay({
61
+ type: "send_failed",
62
+ requestId: command.requestId,
63
+ code: "NOT_STARTED",
64
+ message: "alias peer has not started"
65
+ });
66
+ return;
67
+ }
68
+ try {
69
+ const { msgId } = await active.send(command.target, command.body);
70
+ relay({
71
+ type: "sent",
72
+ requestId: command.requestId,
73
+ msgId
74
+ });
75
+ } catch (error) {
76
+ relay({
77
+ type: "send_failed",
78
+ requestId: command.requestId,
79
+ code: error instanceof require_errors.CcPeerError ? error.code : "UNKNOWN",
80
+ message: error instanceof Error ? error.message : "unknown alias send failure"
81
+ });
82
+ }
41
83
  }
42
84
  //#endregion
@@ -1,5 +1,6 @@
1
- import { n as CcPeer } from "../../cc-peer-D3maNn_Z.mjs";
2
- import { t as AliasCommandSchema } from "../../alias-ipc-DkaozCo7.mjs";
1
+ import { n as CcPeer } from "../../cc-peer-CQV4Qv_H.mjs";
2
+ import { r as CcPeerError } from "../../errors-KYBco8pU.mjs";
3
+ import { t as AliasCommandSchema } from "../../alias-ipc-BSh7Q4LL.mjs";
3
4
  import process from "node:process";
4
5
  //#region src/adapters/node/alias-worker.ts
5
6
  /**
@@ -9,11 +10,25 @@ let peer;
9
10
  process.on("message", (raw) => {
10
11
  handleCommand(raw);
11
12
  });
13
+ process.on("disconnect", () => {
14
+ shutdown();
15
+ });
16
+ async function shutdown() {
17
+ await peer?.stop();
18
+ process.exit(0);
19
+ }
20
+ /** Relays an event to the parent unless its channel has already closed, since a send on a closed channel raises an error event on the process that nothing handles. */
21
+ function relay(message) {
22
+ if (process.connected) process.send?.(message);
23
+ }
12
24
  async function handleCommand(raw) {
13
25
  if (!AliasCommandSchema.is(raw)) return;
14
26
  if (raw.type === "stop") {
15
- await peer?.stop();
16
- process.exit(0);
27
+ await shutdown();
28
+ return;
29
+ }
30
+ if (raw.type === "send") {
31
+ await handleSend(raw);
17
32
  return;
18
33
  }
19
34
  let created;
@@ -30,12 +45,39 @@ async function handleCommand(raw) {
30
45
  }
31
46
  peer = created;
32
47
  peer.on("message", (message) => {
33
- process.send?.({
48
+ relay({
34
49
  type: "message",
35
50
  ...message
36
51
  });
37
52
  });
38
- process.send?.({ type: "started" });
53
+ relay({ type: "started" });
54
+ }
55
+ async function handleSend(command) {
56
+ const active = peer;
57
+ if (active === void 0) {
58
+ relay({
59
+ type: "send_failed",
60
+ requestId: command.requestId,
61
+ code: "NOT_STARTED",
62
+ message: "alias peer has not started"
63
+ });
64
+ return;
65
+ }
66
+ try {
67
+ const { msgId } = await active.send(command.target, command.body);
68
+ relay({
69
+ type: "sent",
70
+ requestId: command.requestId,
71
+ msgId
72
+ });
73
+ } catch (error) {
74
+ relay({
75
+ type: "send_failed",
76
+ requestId: command.requestId,
77
+ code: error instanceof CcPeerError ? error.code : "UNKNOWN",
78
+ message: error instanceof Error ? error.message : "unknown alias send failure"
79
+ });
80
+ }
39
81
  }
40
82
  //#endregion
41
83
  export {};
@@ -0,0 +1,97 @@
1
+ const require_errors = require("./errors-BAbklcGw.cjs");
2
+ let zod = require("zod");
3
+ //#region src/schemas/alias-ipc.ts
4
+ /**
5
+ * The parent-to-child and child-to-parent IPC contract `AliasPool`'s Node adapter (`adapters/node/forked-alias-process.ts`) and worker (`adapters/node/alias-worker.ts`) exchange over `child_process.fork()`'s built-in channel. This is deliberately independent of the wire protocol schemas in `wire.ts`: it never touches a socket, it only carries commands and events between a pool and the real OS process backing one reply alias.
6
+ */
7
+ const AliasStartCommandSchema = require_errors.defineSchema(zod.z.object({
8
+ type: zod.z.literal("start"),
9
+ name: zod.z.string().min(1),
10
+ homeDir: zod.z.string().optional(),
11
+ socketDir: zod.z.string().optional(),
12
+ sessionId: zod.z.string().optional()
13
+ }));
14
+ const AliasStopCommandSchema = require_errors.defineSchema(zod.z.object({ type: zod.z.literal("stop") }));
15
+ /**
16
+ * How an alias addresses an outbound send, mirroring `CcPeer`'s own `PeerRef` union. Each variant is strict so a target carrying fields from more than one variant is rejected outright rather than resolved by whichever branch happens to match first.
17
+ */
18
+ const AliasSendTargetSchema = require_errors.defineSchema(zod.z.union([
19
+ zod.z.strictObject({ pid: zod.z.number() }),
20
+ zod.z.strictObject({ name: zod.z.string().min(1) }),
21
+ zod.z.strictObject({ address: zod.z.string().min(1) })
22
+ ]));
23
+ /** Asks the alias's own CcPeer to send `body` to `target`; the worker answers with a sent or send_failed event carrying the same `requestId`. */
24
+ const AliasSendCommandSchema = require_errors.defineSchema(zod.z.object({
25
+ type: zod.z.literal("send"),
26
+ requestId: zod.z.string().min(1),
27
+ target: AliasSendTargetSchema,
28
+ body: zod.z.string()
29
+ }));
30
+ const AliasCommandSchema = require_errors.defineSchema(zod.z.union([
31
+ AliasStartCommandSchema,
32
+ AliasStopCommandSchema,
33
+ AliasSendCommandSchema
34
+ ]));
35
+ /** Sent once the worker's own CcPeer is listening and registered. */
36
+ const AliasStartedEventSchema = require_errors.defineSchema(zod.z.object({ type: zod.z.literal("started") }));
37
+ /** Mirrors CcPeer's own InboundMessage shape, carried over IPC instead of an EventEmitter within one process. */
38
+ const AliasMessageEventSchema = require_errors.defineSchema(zod.z.object({
39
+ type: zod.z.literal("message"),
40
+ from: zod.z.string().optional(),
41
+ fromSession: zod.z.string().optional(),
42
+ fromName: zod.z.string().optional(),
43
+ fromMode: zod.z.enum(["bypass", "prompting"]).optional(),
44
+ hopChain: zod.z.array(zod.z.string()).optional(),
45
+ body: zod.z.string(),
46
+ msgId: zod.z.string()
47
+ }));
48
+ /** Acknowledges the send command with the same `requestId`, carrying the id the alias's own peer gave the message. */
49
+ const AliasSentEventSchema = require_errors.defineSchema(zod.z.object({
50
+ type: zod.z.literal("sent"),
51
+ requestId: zod.z.string().min(1),
52
+ msgId: zod.z.string().min(1)
53
+ }));
54
+ /** Reports a send the alias could not make; `code` is the originating `CcPeerError`'s own machine-readable code where one was thrown. */
55
+ const AliasSendFailedEventSchema = require_errors.defineSchema(zod.z.object({
56
+ type: zod.z.literal("send_failed"),
57
+ requestId: zod.z.string().min(1),
58
+ code: zod.z.string().min(1),
59
+ message: zod.z.string()
60
+ }));
61
+ require_errors.defineSchema(zod.z.union([
62
+ AliasStartedEventSchema,
63
+ AliasMessageEventSchema,
64
+ AliasSentEventSchema,
65
+ AliasSendFailedEventSchema
66
+ ]));
67
+ //#endregion
68
+ Object.defineProperty(exports, "AliasCommandSchema", {
69
+ enumerable: true,
70
+ get: function() {
71
+ return AliasCommandSchema;
72
+ }
73
+ });
74
+ Object.defineProperty(exports, "AliasMessageEventSchema", {
75
+ enumerable: true,
76
+ get: function() {
77
+ return AliasMessageEventSchema;
78
+ }
79
+ });
80
+ Object.defineProperty(exports, "AliasSendFailedEventSchema", {
81
+ enumerable: true,
82
+ get: function() {
83
+ return AliasSendFailedEventSchema;
84
+ }
85
+ });
86
+ Object.defineProperty(exports, "AliasSentEventSchema", {
87
+ enumerable: true,
88
+ get: function() {
89
+ return AliasSentEventSchema;
90
+ }
91
+ });
92
+ Object.defineProperty(exports, "AliasStartedEventSchema", {
93
+ enumerable: true,
94
+ get: function() {
95
+ return AliasStartedEventSchema;
96
+ }
97
+ });
@@ -0,0 +1,68 @@
1
+ import { l as defineSchema } from "./errors-KYBco8pU.mjs";
2
+ import { z } from "zod";
3
+ //#region src/schemas/alias-ipc.ts
4
+ /**
5
+ * The parent-to-child and child-to-parent IPC contract `AliasPool`'s Node adapter (`adapters/node/forked-alias-process.ts`) and worker (`adapters/node/alias-worker.ts`) exchange over `child_process.fork()`'s built-in channel. This is deliberately independent of the wire protocol schemas in `wire.ts`: it never touches a socket, it only carries commands and events between a pool and the real OS process backing one reply alias.
6
+ */
7
+ const AliasStartCommandSchema = defineSchema(z.object({
8
+ type: z.literal("start"),
9
+ name: z.string().min(1),
10
+ homeDir: z.string().optional(),
11
+ socketDir: z.string().optional(),
12
+ sessionId: z.string().optional()
13
+ }));
14
+ const AliasStopCommandSchema = defineSchema(z.object({ type: z.literal("stop") }));
15
+ /**
16
+ * How an alias addresses an outbound send, mirroring `CcPeer`'s own `PeerRef` union. Each variant is strict so a target carrying fields from more than one variant is rejected outright rather than resolved by whichever branch happens to match first.
17
+ */
18
+ const AliasSendTargetSchema = defineSchema(z.union([
19
+ z.strictObject({ pid: z.number() }),
20
+ z.strictObject({ name: z.string().min(1) }),
21
+ z.strictObject({ address: z.string().min(1) })
22
+ ]));
23
+ /** Asks the alias's own CcPeer to send `body` to `target`; the worker answers with a sent or send_failed event carrying the same `requestId`. */
24
+ const AliasSendCommandSchema = defineSchema(z.object({
25
+ type: z.literal("send"),
26
+ requestId: z.string().min(1),
27
+ target: AliasSendTargetSchema,
28
+ body: z.string()
29
+ }));
30
+ const AliasCommandSchema = defineSchema(z.union([
31
+ AliasStartCommandSchema,
32
+ AliasStopCommandSchema,
33
+ AliasSendCommandSchema
34
+ ]));
35
+ /** Sent once the worker's own CcPeer is listening and registered. */
36
+ const AliasStartedEventSchema = defineSchema(z.object({ type: z.literal("started") }));
37
+ /** Mirrors CcPeer's own InboundMessage shape, carried over IPC instead of an EventEmitter within one process. */
38
+ const AliasMessageEventSchema = defineSchema(z.object({
39
+ type: z.literal("message"),
40
+ from: z.string().optional(),
41
+ fromSession: z.string().optional(),
42
+ fromName: z.string().optional(),
43
+ fromMode: z.enum(["bypass", "prompting"]).optional(),
44
+ hopChain: z.array(z.string()).optional(),
45
+ body: z.string(),
46
+ msgId: z.string()
47
+ }));
48
+ /** Acknowledges the send command with the same `requestId`, carrying the id the alias's own peer gave the message. */
49
+ const AliasSentEventSchema = defineSchema(z.object({
50
+ type: z.literal("sent"),
51
+ requestId: z.string().min(1),
52
+ msgId: z.string().min(1)
53
+ }));
54
+ /** Reports a send the alias could not make; `code` is the originating `CcPeerError`'s own machine-readable code where one was thrown. */
55
+ const AliasSendFailedEventSchema = defineSchema(z.object({
56
+ type: z.literal("send_failed"),
57
+ requestId: z.string().min(1),
58
+ code: z.string().min(1),
59
+ message: z.string()
60
+ }));
61
+ defineSchema(z.union([
62
+ AliasStartedEventSchema,
63
+ AliasMessageEventSchema,
64
+ AliasSentEventSchema,
65
+ AliasSendFailedEventSchema
66
+ ]));
67
+ //#endregion
68
+ export { AliasStartedEventSchema as a, AliasSentEventSchema as i, AliasMessageEventSchema as n, AliasSendFailedEventSchema as r, AliasCommandSchema as t };
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_errors = require("./errors-Dl_lSq1N.cjs");
3
- const require_alias_ipc = require("./alias-ipc-Cjs5yivH.cjs");
2
+ const require_errors = require("./errors-BAbklcGw.cjs");
3
+ const require_alias_ipc = require("./alias-ipc-BPc2wfmz.cjs");
4
4
  let node_events = require("node:events");
5
5
  let node_child_process = require("node:child_process");
6
6
  let node_url = require("node:url");
@@ -12,6 +12,7 @@ var ForkedAliasProcess = class {
12
12
  events = new node_events.EventEmitter();
13
13
  forkFn;
14
14
  workerPath;
15
+ pendingSends = /* @__PURE__ */ new Map();
15
16
  child;
16
17
  constructor(deps) {
17
18
  this.forkFn = deps.fork ?? node_child_process.fork;
@@ -21,9 +22,14 @@ var ForkedAliasProcess = class {
21
22
  const child = this.forkFn(this.workerPath, [], {});
22
23
  this.child = child;
23
24
  child.on("message", (raw) => {
24
- if (require_alias_ipc.AliasMessageEventSchema.is(raw)) this.events.emit("message", toInboundMessage(raw));
25
+ if (require_alias_ipc.AliasMessageEventSchema.is(raw)) {
26
+ this.events.emit("message", toInboundMessage(raw));
27
+ return;
28
+ }
29
+ this.settleSend(raw);
25
30
  });
26
31
  child.on("exit", () => {
32
+ this.failPendingSends("alias worker exited before the send was acknowledged");
27
33
  this.events.emit("exit");
28
34
  });
29
35
  await new Promise((resolve, reject) => {
@@ -49,10 +55,51 @@ var ForkedAliasProcess = class {
49
55
  });
50
56
  });
51
57
  }
52
- async stop() {
58
+ async send(target, body) {
59
+ const child = this.runningChild();
60
+ if (child === void 0) throw new require_errors.AliasSendError("alias worker is not running");
61
+ const requestId = require_errors.newMsgId();
62
+ return new Promise((resolve, reject) => {
63
+ this.pendingSends.set(requestId, {
64
+ resolve,
65
+ reject
66
+ });
67
+ child.send({
68
+ type: "send",
69
+ requestId,
70
+ target,
71
+ body
72
+ });
73
+ });
74
+ }
75
+ /** Settles the one in-flight send an acknowledgement names. An acknowledgement for an unknown request is ignored: the send it belongs to was already settled by the worker exiting. */
76
+ settleSend(raw) {
77
+ if (require_alias_ipc.AliasSentEventSchema.is(raw)) {
78
+ this.takePendingSend(raw.requestId)?.resolve({ msgId: raw.msgId });
79
+ return;
80
+ }
81
+ if (require_alias_ipc.AliasSendFailedEventSchema.is(raw)) this.takePendingSend(raw.requestId)?.reject(new require_errors.AliasSendError(`${raw.code}: ${raw.message}`));
82
+ }
83
+ takePendingSend(requestId) {
84
+ const pending = this.pendingSends.get(requestId);
85
+ this.pendingSends.delete(requestId);
86
+ return pending;
87
+ }
88
+ failPendingSends(reason) {
89
+ const pending = [...this.pendingSends.values()];
90
+ this.pendingSends.clear();
91
+ for (const send of pending) send.reject(new require_errors.AliasSendError(reason));
92
+ }
93
+ /** The forked child while it is still running, or undefined before start() and once it has ended: a command written past that point reaches a channel nothing is reading. */
94
+ runningChild() {
53
95
  const child = this.child;
96
+ if (child === void 0) return void 0;
97
+ if (child.exitCode !== null || child.signalCode !== null) return void 0;
98
+ return child;
99
+ }
100
+ async stop() {
101
+ const child = this.runningChild();
54
102
  if (child === void 0) return;
55
- if (child.exitCode !== null || child.signalCode !== null) return;
56
103
  await new Promise((resolve) => {
57
104
  child.once("exit", () => {
58
105
  resolve();
@@ -106,16 +153,24 @@ var AliasPool = class AliasPool extends node_events.EventEmitter {
106
153
  }
107
154
  /** Idempotent: a no-op if the alias is already active, and dedup'd if another ensure() for the same name is already in flight. */
108
155
  async ensure(name) {
109
- if (this.active.has(name)) return;
156
+ await this.acquire(name);
157
+ }
158
+ /**
159
+ * Sends `body` to `target` from the named alias's own peer identity, starting that alias first if it is not already running, so the recipient sees the correspondent rather than the relay as the sender. Resolves with the id the alias gave the message; rejects with an `AliasStartError` if the alias could not be started, or an `AliasSendError` if it refused the send or its process ended before acknowledging it.
160
+ */
161
+ async send(name, target, body) {
162
+ return (await this.acquire(name)).send(target, body);
163
+ }
164
+ /** The single start path behind ensure() and send(): returns the running process for the name, starting one only if neither an active nor an in-flight process already exists. */
165
+ async acquire(name) {
166
+ const active = this.active.get(name);
167
+ if (active !== void 0) return active;
110
168
  const inFlight = this.pending.get(name);
111
- if (inFlight !== void 0) {
112
- await inFlight;
113
- return;
114
- }
169
+ if (inFlight !== void 0) return inFlight;
115
170
  const started = this.startAlias(name);
116
171
  this.pending.set(name, started);
117
172
  try {
118
- await started;
173
+ return await started;
119
174
  } finally {
120
175
  this.pending.delete(name);
121
176
  }
@@ -139,6 +194,7 @@ var AliasPool = class AliasPool extends node_events.EventEmitter {
139
194
  });
140
195
  this.active.set(name, proc);
141
196
  this.log(`alias ${name} active`);
197
+ return proc;
142
198
  }
143
199
  /** Waits for any in-flight ensure() of the same name to settle first, so a retire() issued while an alias is still starting stops it once (and if) it becomes active. A no-op for a name that is neither active nor pending. */
144
200
  async retire(name) {
@@ -1,4 +1,4 @@
1
- import { a as InboundMessage, l as PathConfig } from "./cc-peer-B3i4ZlKV.cjs";
1
+ import { a as InboundMessage, l as PathConfig, o as PeerRef } from "./cc-peer-mYIVwlKe.cjs";
2
2
  import { EventEmitter } from "node:events";
3
3
  //#region src/ports/alias-process.d.ts
4
4
  interface AliasStartOptions extends PathConfig {
@@ -11,6 +11,12 @@ interface AliasStartOptions extends PathConfig {
11
11
  interface AliasProcess {
12
12
  readonly events: EventEmitter;
13
13
  start: (options: Readonly<AliasStartOptions>) => Promise<void>;
14
+ /**
15
+ * Sends `body` to `target` from the alias's own peer identity, so the recipient sees the alias as the sender and replies to it natively. Resolves with the id the alias's peer gave the message; rejects with an `AliasSendError` when the alias refuses the send or its process ends before acknowledging it.
16
+ */
17
+ send: (target: Readonly<PeerRef>, body: string) => Promise<{
18
+ msgId: string;
19
+ }>;
14
20
  stop: () => Promise<void>;
15
21
  }
16
22
  //#endregion
@@ -42,6 +48,14 @@ export declare class AliasPool extends EventEmitter {
42
48
  static create(options?: Readonly<AliasPoolOptions>): AliasPool;
43
49
  /** Idempotent: a no-op if the alias is already active, and dedup'd if another ensure() for the same name is already in flight. */
44
50
  ensure(name: string): Promise<void>;
51
+ /**
52
+ * Sends `body` to `target` from the named alias's own peer identity, starting that alias first if it is not already running, so the recipient sees the correspondent rather than the relay as the sender. Resolves with the id the alias gave the message; rejects with an `AliasStartError` if the alias could not be started, or an `AliasSendError` if it refused the send or its process ended before acknowledging it.
53
+ */
54
+ send(name: string, target: Readonly<PeerRef>, body: string): Promise<{
55
+ msgId: string;
56
+ }>;
57
+ /** The single start path behind ensure() and send(): returns the running process for the name, starting one only if neither an active nor an in-flight process already exists. */
58
+ private acquire;
45
59
  private startAlias;
46
60
  /** Waits for any in-flight ensure() of the same name to settle first, so a retire() issued while an alias is still starting stops it once (and if) it becomes active. A no-op for a name that is neither active nor pending. */
47
61
  retire(name: string): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { a as InboundMessage, l as PathConfig } from "./cc-peer-B3i4ZlKV.mjs";
1
+ import { a as InboundMessage, l as PathConfig, o as PeerRef } from "./cc-peer-mYIVwlKe.mjs";
2
2
  import { EventEmitter } from "node:events";
3
3
  //#region src/ports/alias-process.d.ts
4
4
  interface AliasStartOptions extends PathConfig {
@@ -11,6 +11,12 @@ interface AliasStartOptions extends PathConfig {
11
11
  interface AliasProcess {
12
12
  readonly events: EventEmitter;
13
13
  start: (options: Readonly<AliasStartOptions>) => Promise<void>;
14
+ /**
15
+ * Sends `body` to `target` from the alias's own peer identity, so the recipient sees the alias as the sender and replies to it natively. Resolves with the id the alias's peer gave the message; rejects with an `AliasSendError` when the alias refuses the send or its process ends before acknowledging it.
16
+ */
17
+ send: (target: Readonly<PeerRef>, body: string) => Promise<{
18
+ msgId: string;
19
+ }>;
14
20
  stop: () => Promise<void>;
15
21
  }
16
22
  //#endregion
@@ -42,6 +48,14 @@ export declare class AliasPool extends EventEmitter {
42
48
  static create(options?: Readonly<AliasPoolOptions>): AliasPool;
43
49
  /** Idempotent: a no-op if the alias is already active, and dedup'd if another ensure() for the same name is already in flight. */
44
50
  ensure(name: string): Promise<void>;
51
+ /**
52
+ * Sends `body` to `target` from the named alias's own peer identity, starting that alias first if it is not already running, so the recipient sees the correspondent rather than the relay as the sender. Resolves with the id the alias gave the message; rejects with an `AliasStartError` if the alias could not be started, or an `AliasSendError` if it refused the send or its process ended before acknowledging it.
53
+ */
54
+ send(name: string, target: Readonly<PeerRef>, body: string): Promise<{
55
+ msgId: string;
56
+ }>;
57
+ /** The single start path behind ensure() and send(): returns the running process for the name, starting one only if neither an active nor an in-flight process already exists. */
58
+ private acquire;
45
59
  private startAlias;
46
60
  /** Waits for any in-flight ensure() of the same name to settle first, so a retire() issued while an alias is still starting stops it once (and if) it becomes active. A no-op for a name that is neither active nor pending. */
47
61
  retire(name: string): Promise<void>;
@@ -1,5 +1,5 @@
1
- import { t as AliasStartError } from "./errors-Dcqq2MIW.mjs";
2
- import { n as AliasMessageEventSchema, r as AliasStartedEventSchema } from "./alias-ipc-DkaozCo7.mjs";
1
+ import { c as newMsgId, n as AliasStartError, t as AliasSendError } from "./errors-KYBco8pU.mjs";
2
+ import { a as AliasStartedEventSchema, i as AliasSentEventSchema, n as AliasMessageEventSchema, r as AliasSendFailedEventSchema } from "./alias-ipc-BSh7Q4LL.mjs";
3
3
  import { EventEmitter } from "node:events";
4
4
  import { fork } from "node:child_process";
5
5
  import { fileURLToPath } from "node:url";
@@ -11,6 +11,7 @@ var ForkedAliasProcess = class {
11
11
  events = new EventEmitter();
12
12
  forkFn;
13
13
  workerPath;
14
+ pendingSends = /* @__PURE__ */ new Map();
14
15
  child;
15
16
  constructor(deps) {
16
17
  this.forkFn = deps.fork ?? fork;
@@ -20,9 +21,14 @@ var ForkedAliasProcess = class {
20
21
  const child = this.forkFn(this.workerPath, [], {});
21
22
  this.child = child;
22
23
  child.on("message", (raw) => {
23
- if (AliasMessageEventSchema.is(raw)) this.events.emit("message", toInboundMessage(raw));
24
+ if (AliasMessageEventSchema.is(raw)) {
25
+ this.events.emit("message", toInboundMessage(raw));
26
+ return;
27
+ }
28
+ this.settleSend(raw);
24
29
  });
25
30
  child.on("exit", () => {
31
+ this.failPendingSends("alias worker exited before the send was acknowledged");
26
32
  this.events.emit("exit");
27
33
  });
28
34
  await new Promise((resolve, reject) => {
@@ -48,10 +54,51 @@ var ForkedAliasProcess = class {
48
54
  });
49
55
  });
50
56
  }
51
- async stop() {
57
+ async send(target, body) {
58
+ const child = this.runningChild();
59
+ if (child === void 0) throw new AliasSendError("alias worker is not running");
60
+ const requestId = newMsgId();
61
+ return new Promise((resolve, reject) => {
62
+ this.pendingSends.set(requestId, {
63
+ resolve,
64
+ reject
65
+ });
66
+ child.send({
67
+ type: "send",
68
+ requestId,
69
+ target,
70
+ body
71
+ });
72
+ });
73
+ }
74
+ /** Settles the one in-flight send an acknowledgement names. An acknowledgement for an unknown request is ignored: the send it belongs to was already settled by the worker exiting. */
75
+ settleSend(raw) {
76
+ if (AliasSentEventSchema.is(raw)) {
77
+ this.takePendingSend(raw.requestId)?.resolve({ msgId: raw.msgId });
78
+ return;
79
+ }
80
+ if (AliasSendFailedEventSchema.is(raw)) this.takePendingSend(raw.requestId)?.reject(new AliasSendError(`${raw.code}: ${raw.message}`));
81
+ }
82
+ takePendingSend(requestId) {
83
+ const pending = this.pendingSends.get(requestId);
84
+ this.pendingSends.delete(requestId);
85
+ return pending;
86
+ }
87
+ failPendingSends(reason) {
88
+ const pending = [...this.pendingSends.values()];
89
+ this.pendingSends.clear();
90
+ for (const send of pending) send.reject(new AliasSendError(reason));
91
+ }
92
+ /** The forked child while it is still running, or undefined before start() and once it has ended: a command written past that point reaches a channel nothing is reading. */
93
+ runningChild() {
52
94
  const child = this.child;
95
+ if (child === void 0) return void 0;
96
+ if (child.exitCode !== null || child.signalCode !== null) return void 0;
97
+ return child;
98
+ }
99
+ async stop() {
100
+ const child = this.runningChild();
53
101
  if (child === void 0) return;
54
- if (child.exitCode !== null || child.signalCode !== null) return;
55
102
  await new Promise((resolve) => {
56
103
  child.once("exit", () => {
57
104
  resolve();
@@ -105,16 +152,24 @@ var AliasPool = class AliasPool extends EventEmitter {
105
152
  }
106
153
  /** Idempotent: a no-op if the alias is already active, and dedup'd if another ensure() for the same name is already in flight. */
107
154
  async ensure(name) {
108
- if (this.active.has(name)) return;
155
+ await this.acquire(name);
156
+ }
157
+ /**
158
+ * Sends `body` to `target` from the named alias's own peer identity, starting that alias first if it is not already running, so the recipient sees the correspondent rather than the relay as the sender. Resolves with the id the alias gave the message; rejects with an `AliasStartError` if the alias could not be started, or an `AliasSendError` if it refused the send or its process ended before acknowledging it.
159
+ */
160
+ async send(name, target, body) {
161
+ return (await this.acquire(name)).send(target, body);
162
+ }
163
+ /** The single start path behind ensure() and send(): returns the running process for the name, starting one only if neither an active nor an in-flight process already exists. */
164
+ async acquire(name) {
165
+ const active = this.active.get(name);
166
+ if (active !== void 0) return active;
109
167
  const inFlight = this.pending.get(name);
110
- if (inFlight !== void 0) {
111
- await inFlight;
112
- return;
113
- }
168
+ if (inFlight !== void 0) return inFlight;
114
169
  const started = this.startAlias(name);
115
170
  this.pending.set(name, started);
116
171
  try {
117
- await started;
172
+ return await started;
118
173
  } finally {
119
174
  this.pending.delete(name);
120
175
  }
@@ -138,6 +193,7 @@ var AliasPool = class AliasPool extends EventEmitter {
138
193
  });
139
194
  this.active.set(name, proc);
140
195
  this.log(`alias ${name} active`);
196
+ return proc;
141
197
  }
142
198
  /** Waits for any in-flight ensure() of the same name to settle first, so a retire() issued while an alias is still starting stops it once (and if) it becomes active. A no-op for a name that is neither active nor pending. */
143
199
  async retire(name) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  const require_rolldown_runtime = require("../rolldown-runtime-VH7oDXx4.cjs");
3
- const require_cc_peer = require("../cc-peer-CPPV05My.cjs");
4
- const require_errors = require("../errors-Dl_lSq1N.cjs");
3
+ const require_cc_peer = require("../cc-peer-BvoaikwI.cjs");
4
+ const require_errors = require("../errors-BAbklcGw.cjs");
5
5
  let node_crypto = require("node:crypto");
6
6
  let zod = require("zod");
7
7
  let node_process = require("node:process");
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { i as RegistryEntrySchema, n as CcPeer, r as PrioritySchema } from "../cc-peer-D3maNn_Z.mjs";
3
- import { o as defineSchema } from "../errors-Dcqq2MIW.mjs";
2
+ import { i as RegistryEntrySchema, n as CcPeer, r as PrioritySchema } from "../cc-peer-CQV4Qv_H.mjs";
3
+ import { l as defineSchema } from "../errors-KYBco8pU.mjs";
4
4
  import { randomBytes } from "node:crypto";
5
5
  import { z } from "zod";
6
6
  import process from "node:process";
@@ -1,4 +1,4 @@
1
- const require_errors = require("./errors-Dl_lSq1N.cjs");
1
+ const require_errors = require("./errors-BAbklcGw.cjs");
2
2
  let node_events = require("node:events");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_net = require("node:net");
@@ -8,7 +8,7 @@ let zod = require("zod");
8
8
  let node_os = require("node:os");
9
9
  let node_child_process = require("node:child_process");
10
10
  //#region package.json
11
- var version = "1.5.3";
11
+ var version = "1.6.1";
12
12
  //#endregion
13
13
  //#region src/adapters/node/uds-transport.ts
14
14
  /** macOS linger before close, matching the reference client's ~150ms. */
@@ -564,12 +564,6 @@ var Pacer = class {
564
564
  }
565
565
  };
566
566
  //#endregion
567
- //#region src/domain/ids.ts
568
- /** Message ids are UUID v4, matching the reference client's `qM()`. */
569
- function newMsgId() {
570
- return (0, node_crypto.randomUUID)();
571
- }
572
- //#endregion
573
567
  //#region src/domain/roster.ts
574
568
  /**
575
569
  * The receiver's own admission rules, verified live: an entry is listed when it has a socket, is not the caller's own, is not spare/parked, its socket accepts a live connect probe, and its pid is alive with a procStart that byte-matches the ps output. Mismatches classify as recycled and are silently skipped by the reference roster builder.
@@ -807,7 +801,7 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
807
801
  const now = this.deps.clock.nowMs();
808
802
  return {
809
803
  pid: process.pid,
810
- sessionId: this.options.sessionId ?? newMsgId(),
804
+ sessionId: this.options.sessionId ?? require_errors.newMsgId(),
811
805
  cwd: process.cwd(),
812
806
  startedAt: now,
813
807
  procStart,
@@ -840,7 +834,7 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
840
834
  if (this.stopped || this.listening === void 0 || this.ownKey === void 0) throw new require_errors.NotStartedError("peer is not running");
841
835
  const socketPath = await this.resolveTarget(target);
842
836
  const key = await this.deps.keys.readForSocket(socketPath);
843
- const msgId = newMsgId();
837
+ const msgId = require_errors.newMsgId();
844
838
  const from = `uds:${this.listening.socketPath}`;
845
839
  const frame = {
846
840
  msgV: 1,
@@ -884,7 +878,7 @@ var CcPeer = class CcPeer extends node_events.EventEmitter {
884
878
  const socketPath = await this.resolveTarget(target);
885
879
  const key = await this.deps.keys.readForSocket(socketPath);
886
880
  if (key === void 0) throw new require_errors.NoLiveInboxError(`no auth key published for ${socketPath}`);
887
- const msgId = newMsgId();
881
+ const msgId = require_errors.newMsgId();
888
882
  const frame = {
889
883
  msgV: 1,
890
884
  msg_id: msgId,
@@ -1,6 +1,6 @@
1
- import { a as UnknownPeerError, i as NotStartedError, n as MessageTooLargeError, o as defineSchema, r as NoLiveInboxError } from "./errors-Dcqq2MIW.mjs";
1
+ import { a as NoLiveInboxError, c as newMsgId, i as MessageTooLargeError, l as defineSchema, o as NotStartedError, s as UnknownPeerError } from "./errors-KYBco8pU.mjs";
2
2
  import { EventEmitter } from "node:events";
3
- import { createHash, randomBytes, randomUUID } from "node:crypto";
3
+ import { createHash, randomBytes } from "node:crypto";
4
4
  import { connect, createServer } from "node:net";
5
5
  import { mkdir, readFile, readdir, rename, unlink, writeFile } from "node:fs/promises";
6
6
  import { dirname, join } from "node:path";
@@ -8,7 +8,7 @@ import { z } from "zod";
8
8
  import { homedir } from "node:os";
9
9
  import { spawn } from "node:child_process";
10
10
  //#region package.json
11
- var version = "1.5.3";
11
+ var version = "1.6.1";
12
12
  //#endregion
13
13
  //#region src/adapters/node/uds-transport.ts
14
14
  /** macOS linger before close, matching the reference client's ~150ms. */
@@ -564,12 +564,6 @@ var Pacer = class {
564
564
  }
565
565
  };
566
566
  //#endregion
567
- //#region src/domain/ids.ts
568
- /** Message ids are UUID v4, matching the reference client's `qM()`. */
569
- function newMsgId() {
570
- return randomUUID();
571
- }
572
- //#endregion
573
567
  //#region src/domain/roster.ts
574
568
  /**
575
569
  * The receiver's own admission rules, verified live: an entry is listed when it has a socket, is not the caller's own, is not spare/parked, its socket accepts a live connect probe, and its pid is alive with a procStart that byte-matches the ps output. Mismatches classify as recycled and are silently skipped by the reference roster builder.
@@ -71,12 +71,12 @@ declare const RegistryEntrySchema: z.ZodObject<{
71
71
  nameSince: z.ZodOptional<z.ZodNumber>;
72
72
  updatedAt: z.ZodNumber;
73
73
  status: z.ZodOptional<z.ZodEnum<{
74
- idle: "idle";
75
74
  busy: "busy";
76
75
  shell: "shell";
76
+ idle: "idle";
77
77
  waiting: "waiting";
78
78
  }> & {
79
- is(value: unknown): value is "idle" | "busy" | "shell" | "waiting";
79
+ is(value: unknown): value is "busy" | "shell" | "idle" | "waiting";
80
80
  }>;
81
81
  statusUpdatedAt: z.ZodOptional<z.ZodNumber>;
82
82
  bridgeSessionId: z.ZodOptional<z.ZodString>;
@@ -99,7 +99,7 @@ declare const RegistryEntrySchema: z.ZodObject<{
99
99
  name?: string | undefined;
100
100
  nameSource?: "user" | "peer" | "derived" | "collision" | "auto" | "hook" | undefined;
101
101
  nameSince?: number | undefined;
102
- status?: "idle" | "busy" | "shell" | "waiting" | undefined;
102
+ status?: "busy" | "shell" | "idle" | "waiting" | undefined;
103
103
  statusUpdatedAt?: number | undefined;
104
104
  bridgeSessionId?: string | undefined;
105
105
  };
@@ -71,12 +71,12 @@ declare const RegistryEntrySchema: z.ZodObject<{
71
71
  nameSince: z.ZodOptional<z.ZodNumber>;
72
72
  updatedAt: z.ZodNumber;
73
73
  status: z.ZodOptional<z.ZodEnum<{
74
- idle: "idle";
75
74
  busy: "busy";
76
75
  shell: "shell";
76
+ idle: "idle";
77
77
  waiting: "waiting";
78
78
  }> & {
79
- is(value: unknown): value is "idle" | "busy" | "shell" | "waiting";
79
+ is(value: unknown): value is "busy" | "shell" | "idle" | "waiting";
80
80
  }>;
81
81
  statusUpdatedAt: z.ZodOptional<z.ZodNumber>;
82
82
  bridgeSessionId: z.ZodOptional<z.ZodString>;
@@ -99,7 +99,7 @@ declare const RegistryEntrySchema: z.ZodObject<{
99
99
  name?: string | undefined;
100
100
  nameSource?: "user" | "peer" | "derived" | "collision" | "auto" | "hook" | undefined;
101
101
  nameSince?: number | undefined;
102
- status?: "idle" | "busy" | "shell" | "waiting" | undefined;
102
+ status?: "busy" | "shell" | "idle" | "waiting" | undefined;
103
103
  statusUpdatedAt?: number | undefined;
104
104
  bridgeSessionId?: string | undefined;
105
105
  };
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-CPPV05My.cjs");
2
+ const require_cc_peer = require("./cc-peer-BvoaikwI.cjs");
3
3
  exports.CC_PEER_VERSION = require_cc_peer.CC_PEER_VERSION;
4
4
  exports.CcPeer = require_cc_peer.CcPeer;
@@ -1,2 +1,2 @@
1
- import { a as InboundMessage, c as SendOptions, i as IdleNotice, n as CcPeer, o as PeerRef, r as CcPeerOptions, s as Receipt, t as CC_PEER_VERSION } from "./cc-peer-B3i4ZlKV.cjs";
1
+ import { a as InboundMessage, c as SendOptions, i as IdleNotice, n as CcPeer, o as PeerRef, r as CcPeerOptions, s as Receipt, t as CC_PEER_VERSION } from "./cc-peer-mYIVwlKe.cjs";
2
2
  export { CC_PEER_VERSION, CcPeer, CcPeerOptions, IdleNotice, InboundMessage, PeerRef, Receipt, SendOptions };
@@ -1,2 +1,2 @@
1
- import { a as InboundMessage, c as SendOptions, i as IdleNotice, n as CcPeer, o as PeerRef, r as CcPeerOptions, s as Receipt, t as CC_PEER_VERSION } from "./cc-peer-B3i4ZlKV.mjs";
1
+ import { a as InboundMessage, c as SendOptions, i as IdleNotice, n as CcPeer, o as PeerRef, r as CcPeerOptions, s as Receipt, t as CC_PEER_VERSION } from "./cc-peer-mYIVwlKe.mjs";
2
2
  export { CC_PEER_VERSION, CcPeer, CcPeerOptions, IdleNotice, InboundMessage, PeerRef, Receipt, SendOptions };
package/dist/cc-peer.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as CcPeer, t as CC_PEER_VERSION } from "./cc-peer-D3maNn_Z.mjs";
1
+ import { n as CcPeer, t as CC_PEER_VERSION } from "./cc-peer-CQV4Qv_H.mjs";
2
2
  export { CC_PEER_VERSION, CcPeer };
@@ -1,3 +1,4 @@
1
+ let node_crypto = require("node:crypto");
1
2
  //#region src/schemas/define-schema.ts
2
3
  /**
3
4
  * 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.
@@ -8,6 +9,12 @@ function defineSchema(schema) {
8
9
  } });
9
10
  }
10
11
  //#endregion
12
+ //#region src/domain/ids.ts
13
+ /** Message ids are UUID v4, matching the reference client's `qM()`. */
14
+ function newMsgId() {
15
+ return (0, node_crypto.randomUUID)();
16
+ }
17
+ //#endregion
11
18
  //#region src/errors.ts
12
19
  /** Base error for every cc-peer failure; `code` is machine-readable. */
13
20
  var CcPeerError = class extends Error {
@@ -49,13 +56,32 @@ var AliasStartError = class extends CcPeerError {
49
56
  this.name = "AliasStartError";
50
57
  }
51
58
  };
59
+ /** A message could not be sent from a reply alias: its own peer refused the send, or its worker process was gone (or went away) before acknowledging the command. */
60
+ var AliasSendError = class extends CcPeerError {
61
+ constructor(message) {
62
+ super("ALIAS_SEND_FAILED", message);
63
+ this.name = "AliasSendError";
64
+ }
65
+ };
52
66
  //#endregion
67
+ Object.defineProperty(exports, "AliasSendError", {
68
+ enumerable: true,
69
+ get: function() {
70
+ return AliasSendError;
71
+ }
72
+ });
53
73
  Object.defineProperty(exports, "AliasStartError", {
54
74
  enumerable: true,
55
75
  get: function() {
56
76
  return AliasStartError;
57
77
  }
58
78
  });
79
+ Object.defineProperty(exports, "CcPeerError", {
80
+ enumerable: true,
81
+ get: function() {
82
+ return CcPeerError;
83
+ }
84
+ });
59
85
  Object.defineProperty(exports, "MessageTooLargeError", {
60
86
  enumerable: true,
61
87
  get: function() {
@@ -86,3 +112,9 @@ Object.defineProperty(exports, "defineSchema", {
86
112
  return defineSchema;
87
113
  }
88
114
  });
115
+ Object.defineProperty(exports, "newMsgId", {
116
+ enumerable: true,
117
+ get: function() {
118
+ return newMsgId;
119
+ }
120
+ });
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  //#region src/schemas/define-schema.ts
2
3
  /**
3
4
  * 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.
@@ -8,6 +9,12 @@ function defineSchema(schema) {
8
9
  } });
9
10
  }
10
11
  //#endregion
12
+ //#region src/domain/ids.ts
13
+ /** Message ids are UUID v4, matching the reference client's `qM()`. */
14
+ function newMsgId() {
15
+ return randomUUID();
16
+ }
17
+ //#endregion
11
18
  //#region src/errors.ts
12
19
  /** Base error for every cc-peer failure; `code` is machine-readable. */
13
20
  var CcPeerError = class extends Error {
@@ -49,5 +56,12 @@ var AliasStartError = class extends CcPeerError {
49
56
  this.name = "AliasStartError";
50
57
  }
51
58
  };
59
+ /** A message could not be sent from a reply alias: its own peer refused the send, or its worker process was gone (or went away) before acknowledging the command. */
60
+ var AliasSendError = class extends CcPeerError {
61
+ constructor(message) {
62
+ super("ALIAS_SEND_FAILED", message);
63
+ this.name = "AliasSendError";
64
+ }
65
+ };
52
66
  //#endregion
53
- export { UnknownPeerError as a, NotStartedError as i, MessageTooLargeError as n, defineSchema as o, NoLiveInboxError as r, AliasStartError as t };
67
+ export { NoLiveInboxError as a, newMsgId as c, MessageTooLargeError as i, defineSchema as l, AliasStartError as n, NotStartedError as o, CcPeerError as r, UnknownPeerError as s, AliasSendError as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-peer",
3
- "version": "1.5.3",
3
+ "version": "1.6.1",
4
4
  "description": "Communicate with local Claude Code instances over their native cross-session peer messaging: send and receive messages, register as a named discoverable peer, receipts, idle subscriptions, and a REST facade via `npx cc-peer`.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,48 +0,0 @@
1
- const require_errors = require("./errors-Dl_lSq1N.cjs");
2
- let zod = require("zod");
3
- //#region src/schemas/alias-ipc.ts
4
- /**
5
- * The parent-to-child and child-to-parent IPC contract `AliasPool`'s Node adapter (`adapters/node/forked-alias-process.ts`) and worker (`adapters/node/alias-worker.ts`) exchange over `child_process.fork()`'s built-in channel. This is deliberately independent of the wire protocol schemas in `wire.ts`: it never touches a socket, it only carries commands and events between a pool and the real OS process backing one reply alias.
6
- */
7
- const AliasStartCommandSchema = require_errors.defineSchema(zod.z.object({
8
- type: zod.z.literal("start"),
9
- name: zod.z.string().min(1),
10
- homeDir: zod.z.string().optional(),
11
- socketDir: zod.z.string().optional(),
12
- sessionId: zod.z.string().optional()
13
- }));
14
- const AliasStopCommandSchema = require_errors.defineSchema(zod.z.object({ type: zod.z.literal("stop") }));
15
- const AliasCommandSchema = require_errors.defineSchema(zod.z.union([AliasStartCommandSchema, AliasStopCommandSchema]));
16
- /** Sent once the worker's own CcPeer is listening and registered. */
17
- const AliasStartedEventSchema = require_errors.defineSchema(zod.z.object({ type: zod.z.literal("started") }));
18
- /** Mirrors CcPeer's own InboundMessage shape, carried over IPC instead of an EventEmitter within one process. */
19
- const AliasMessageEventSchema = require_errors.defineSchema(zod.z.object({
20
- type: zod.z.literal("message"),
21
- from: zod.z.string().optional(),
22
- fromSession: zod.z.string().optional(),
23
- fromName: zod.z.string().optional(),
24
- fromMode: zod.z.enum(["bypass", "prompting"]).optional(),
25
- hopChain: zod.z.array(zod.z.string()).optional(),
26
- body: zod.z.string(),
27
- msgId: zod.z.string()
28
- }));
29
- require_errors.defineSchema(zod.z.union([AliasStartedEventSchema, AliasMessageEventSchema]));
30
- //#endregion
31
- Object.defineProperty(exports, "AliasCommandSchema", {
32
- enumerable: true,
33
- get: function() {
34
- return AliasCommandSchema;
35
- }
36
- });
37
- Object.defineProperty(exports, "AliasMessageEventSchema", {
38
- enumerable: true,
39
- get: function() {
40
- return AliasMessageEventSchema;
41
- }
42
- });
43
- Object.defineProperty(exports, "AliasStartedEventSchema", {
44
- enumerable: true,
45
- get: function() {
46
- return AliasStartedEventSchema;
47
- }
48
- });
@@ -1,31 +0,0 @@
1
- import { o as defineSchema } from "./errors-Dcqq2MIW.mjs";
2
- import { z } from "zod";
3
- //#region src/schemas/alias-ipc.ts
4
- /**
5
- * The parent-to-child and child-to-parent IPC contract `AliasPool`'s Node adapter (`adapters/node/forked-alias-process.ts`) and worker (`adapters/node/alias-worker.ts`) exchange over `child_process.fork()`'s built-in channel. This is deliberately independent of the wire protocol schemas in `wire.ts`: it never touches a socket, it only carries commands and events between a pool and the real OS process backing one reply alias.
6
- */
7
- const AliasStartCommandSchema = defineSchema(z.object({
8
- type: z.literal("start"),
9
- name: z.string().min(1),
10
- homeDir: z.string().optional(),
11
- socketDir: z.string().optional(),
12
- sessionId: z.string().optional()
13
- }));
14
- const AliasStopCommandSchema = defineSchema(z.object({ type: z.literal("stop") }));
15
- const AliasCommandSchema = defineSchema(z.union([AliasStartCommandSchema, AliasStopCommandSchema]));
16
- /** Sent once the worker's own CcPeer is listening and registered. */
17
- const AliasStartedEventSchema = defineSchema(z.object({ type: z.literal("started") }));
18
- /** Mirrors CcPeer's own InboundMessage shape, carried over IPC instead of an EventEmitter within one process. */
19
- const AliasMessageEventSchema = defineSchema(z.object({
20
- type: z.literal("message"),
21
- from: z.string().optional(),
22
- fromSession: z.string().optional(),
23
- fromName: z.string().optional(),
24
- fromMode: z.enum(["bypass", "prompting"]).optional(),
25
- hopChain: z.array(z.string()).optional(),
26
- body: z.string(),
27
- msgId: z.string()
28
- }));
29
- defineSchema(z.union([AliasStartedEventSchema, AliasMessageEventSchema]));
30
- //#endregion
31
- export { AliasMessageEventSchema as n, AliasStartedEventSchema as r, AliasCommandSchema as t };