@oatelauser/crosschat 1.0.1 → 1.2.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.
@@ -0,0 +1,174 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { dirname, join } from 'node:path';
5
+ import process from 'node:process';
6
+ import { decodeRef, encodeRef, newConversationRef, nextTurnRef, } from './ref.js';
7
+ /**
8
+ * Pair-keyed conversation continuity (B15): `--to` sends continue the pair's
9
+ * latest conversation instead of always starting a new one, so the turn
10
+ * counter is meaningful without either agent having to carry refs by hand
11
+ * (measured 2026-10-02: 30 distinct worker->codex messages all arrived
12
+ * labeled turn=1). Purely local, self-healing state; corrupt/missing data
13
+ * simply falls back to a fresh conversation. Role-free: works for any pair
14
+ * of endpoints in any direction.
15
+ *
16
+ * Storage (B20): one JSON shard per pair in a `conversations/` directory
17
+ * next to the legacy state file (the `rate/<sha256>.json` precedent), so
18
+ * concurrent sends from different pairs no longer read-modify-write one
19
+ * global file. Lazy migration: reads prefer the shard and fall back to the
20
+ * legacy global file (read-only — never rewritten, never deleted); writes
21
+ * only ever touch the shard, so a stale global snapshot is harmless.
22
+ */
23
+ export function defaultConversationsFile() {
24
+ return join(process.env.LOCALAPPDATA ?? homedir(), 'crosschat', 'conversations.json');
25
+ }
26
+ /** Shard directory for a state-file path: its `conversations/` sibling. */
27
+ function shardDirOf(file) {
28
+ return join(dirname(file), 'conversations');
29
+ }
30
+ function shardFileOf(file, pairKey) {
31
+ const name = createHash('sha256').update(pairKey, 'utf8').digest('hex');
32
+ return join(shardDirOf(file), `${name}.json`);
33
+ }
34
+ function parseShard(text) {
35
+ try {
36
+ const parsed = JSON.parse(text);
37
+ if (parsed !== null &&
38
+ typeof parsed === 'object' &&
39
+ typeof parsed.pair === 'string' &&
40
+ typeof parsed.ref === 'string' &&
41
+ typeof parsed.updatedAt === 'number') {
42
+ return { pair: parsed.pair, ref: parsed.ref, updatedAt: parsed.updatedAt };
43
+ }
44
+ }
45
+ catch {
46
+ // corrupt shard: self-heal as absent (isolated to this pair)
47
+ }
48
+ return undefined;
49
+ }
50
+ function readShard(shardFile) {
51
+ try {
52
+ return parseShard(readFileSync(shardFile, 'utf8'));
53
+ }
54
+ catch {
55
+ return undefined; // missing/unreadable shard
56
+ }
57
+ }
58
+ /** The legacy global file, read-only: `{pairs: Record<pairKey, record>}`. */
59
+ function loadLegacyPairs(file) {
60
+ try {
61
+ const parsed = JSON.parse(readFileSync(file, 'utf8'));
62
+ if (parsed !== null && typeof parsed === 'object' && parsed.pairs !== undefined)
63
+ return parsed.pairs;
64
+ }
65
+ catch {
66
+ // missing/corrupt: nothing to fall back to
67
+ }
68
+ return {};
69
+ }
70
+ /** One pair's record: shard first, else its entry in the legacy global file. */
71
+ function loadPair(file, pairKey) {
72
+ const shard = readShard(shardFileOf(file, pairKey));
73
+ if (shard !== undefined)
74
+ return shard;
75
+ return loadLegacyPairs(file)[pairKey];
76
+ }
77
+ function savePair(file, pairKey, record) {
78
+ try {
79
+ const dir = shardDirOf(file);
80
+ mkdirSync(dir, { recursive: true });
81
+ const shard = shardFileOf(file, pairKey);
82
+ // ponytail: no cross-process locking; same-pair millisecond races are
83
+ // last-write-wins — the pair's continuity lags one turn at worst, and
84
+ // refs are self-contained so in-flight replies are unaffected.
85
+ const tmp = `${shard}.${process.pid}.${Date.now()}.tmp`;
86
+ writeFileSync(tmp, JSON.stringify({ pair: pairKey, ...record }), 'utf8');
87
+ renameSync(tmp, shard);
88
+ }
89
+ catch {
90
+ // ponytail: continuity is best-effort; a lost record just starts a new thread.
91
+ }
92
+ }
93
+ /** All pairs' records: every shard, plus legacy records not yet migrated (shard wins). */
94
+ export function loadAllPairs(file) {
95
+ const pairs = loadLegacyPairs(file);
96
+ let names = [];
97
+ try {
98
+ names = readdirSync(shardDirOf(file));
99
+ }
100
+ catch {
101
+ return pairs; // no shard directory yet: legacy view only
102
+ }
103
+ for (const name of names) {
104
+ if (!name.endsWith('.json'))
105
+ continue;
106
+ const shard = readShard(join(shardDirOf(file), name));
107
+ if (shard !== undefined)
108
+ pairs[shard.pair] = shard;
109
+ }
110
+ return pairs;
111
+ }
112
+ function endpointKey(endpoint) {
113
+ return endpoint.p === 'human' ? 'human' : `${endpoint.p}:${endpoint.id}`;
114
+ }
115
+ /** Unordered pair key: (A→B) and (B→A) map to the same conversation. */
116
+ export function pairKeyOf(a, b) {
117
+ return [endpointKey(a), endpointKey(b)].sort().join('\n');
118
+ }
119
+ /**
120
+ * The conversation a fresh `--to` send should join: the pair's stored ref
121
+ * advanced by one turn. Either endpoint may continue (f/t order is the
122
+ * initiator's and stays fixed). No usable record -> brand-new conversation.
123
+ */
124
+ export function continueConversation(file, caller, target) {
125
+ const stored = loadPair(file, pairKeyOf(caller, target));
126
+ if (stored !== undefined) {
127
+ try {
128
+ const ref = decodeRef(stored.ref);
129
+ const sameEndpoints = matchesEndpoints(ref, caller, target);
130
+ if (sameEndpoints && ref.c >= 1) {
131
+ const next = nextTurnRef(ref);
132
+ return { ref: next, turn: next.c };
133
+ }
134
+ }
135
+ catch {
136
+ // stored ref no longer decodes: fall through to a fresh conversation
137
+ }
138
+ }
139
+ return { ref: newConversationRef(caller, target), turn: 1 };
140
+ }
141
+ /** Both endpoints present, in either f/t order (a record either side can continue). */
142
+ function matchesEndpoints(ref, a, b) {
143
+ return ((endpointKey(ref.f) === endpointKey(a) && endpointKey(ref.t) === endpointKey(b)) ||
144
+ (endpointKey(ref.f) === endpointKey(b) && endpointKey(ref.t) === endpointKey(a)));
145
+ }
146
+ /**
147
+ * The conversation a `--conversation` reply should join (B22): the passed ref
148
+ * advanced by one turn — unless the pair's shard has already moved at or past
149
+ * it (late reply, or several senders working from the same stale base), in
150
+ * which case the shard line wins and turn collisions disappear. Shard behind
151
+ * the passed ref, absent, a different conversation (nonce differs), or
152
+ * endpoint-mismatched: unchanged pass-through continuation.
153
+ */
154
+ export function continueFromRef(file, ref) {
155
+ const stored = loadPair(file, pairKeyOf(ref.f, ref.t));
156
+ if (stored !== undefined) {
157
+ try {
158
+ const shard = decodeRef(stored.ref);
159
+ if (matchesEndpoints(shard, ref.f, ref.t) && shard.n === ref.n && shard.c >= ref.c) {
160
+ const next = nextTurnRef(shard);
161
+ return { ref: next, turn: next.c };
162
+ }
163
+ }
164
+ catch {
165
+ // stored ref no longer decodes: continue from the passed ref
166
+ }
167
+ }
168
+ return { ref: nextTurnRef(ref), turn: ref.c + 1 };
169
+ }
170
+ /** Record the pair's latest ref (issued with a message that got out: delivered, queued, or parked). */
171
+ export function recordConversation(file, ref, nowMs = Date.now()) {
172
+ savePair(file, pairKeyOf(ref.f, ref.t), { ref: encodeRef(ref), updatedAt: nowMs });
173
+ }
174
+ //# sourceMappingURL=conversations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversations.js","sourceRoot":"","sources":["../src/conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EACL,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,WAAW,GAGZ,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,UAAU,wBAAwB;IACtC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,EAAE,EAAE,WAAW,EAAE,oBAAoB,CAAC,CAAC;AACxF,CAAC;AAYD,2EAA2E;AAC3E,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,OAAe;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC;QACxD,IACE,MAAM,KAAK,IAAI;YACf,OAAO,MAAM,KAAK,QAAQ;YAC1B,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;YAC/B,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;YAC9B,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,EACpC,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;QAC7E,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS,CAAC,SAAiB;IAClC,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,CAAC,2BAA2B;IAC/C,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA2C,CAAC;QAChG,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC;IACvG,CAAC;IAAC,MAAM,CAAC;QACP,2CAA2C;IAC7C,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,gFAAgF;AAChF,SAAS,QAAQ,CAAC,IAAY,EAAE,OAAe;IAC7C,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,OAAe,EAAE,MAAkB;IACjE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7B,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,sEAAsE;QACtE,sEAAsE;QACtE,+DAA+D;QAC/D,MAAM,GAAG,GAAG,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;QACxD,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACzE,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;IACjF,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAA+B,eAAe,CAAC,IAAI,CAAC,CAAC;IAChE,IAAI,KAAK,GAAa,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC,CAAC,2CAA2C;IAC3D,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACtC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACtD,IAAI,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IACrD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,QAAqB;IACxC,OAAO,QAAQ,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;AAC3E,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,SAAS,CAAC,CAAc,EAAE,CAAc;IACtD,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,MAAmB,EACnB,MAAmB;IAEnB,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,aAAa,GAAG,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAC5D,IAAI,aAAa,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;gBAC9B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;IACH,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,uFAAuF;AACvF,SAAS,gBAAgB,CAAC,GAAoB,EAAE,CAAc,EAAE,CAAc;IAC5E,OAAO,CACL,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;QAChF,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CACjF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,GAAoB;IAEpB,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;gBACnF,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;gBAChC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,6DAA6D;QAC/D,CAAC;IACH,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,GAAoB,EAAE,QAAgB,IAAI,CAAC,GAAG,EAAE;IAC/F,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AACrF,CAAC"}
package/dist/envelope.js CHANGED
@@ -27,7 +27,7 @@ export function composeEnvelope(input) {
27
27
  return (`<cross-session-message from-name="${escapeAttr(fromName)}" turn="${input.turn}"${aliasAttr}>\n` +
28
28
  `<crosschat-reply-hint conversation="${input.ref}" reply-as="${escapeAttr(input.toName)}">` +
29
29
  `回复请运行: crosschat send --conversation ${input.ref} --body "<你的回复>"</crosschat-reply-hint>\n` +
30
- `新话题: crosschat send --to <名字> --body "...";超 16KiB 请写文件后只发路径\n` +
30
+ `新话题或对话已推进时: crosschat send --to <名字> --body "..."(--to 自动接续该端对最近对话);超 16KiB 请写文件后只发路径\n` +
31
31
  `${body}\n` +
32
32
  `</cross-session-message>`);
33
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yEAAyE;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,4FAA4F,CAAC;AAc1H,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAoB;IAClD,MAAM,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,wBAAwB,CAAC;IAC/D,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IACrG,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,gBAAgB,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,MAAM,IAAI,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,CACL,qCAAqC,UAAU,CAAC,QAAQ,CAAC,WAAW,KAAK,CAAC,IAAI,IAAI,SAAS,KAAK;QAChG,uCAAuC,KAAK,CAAC,GAAG,eAAe,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI;QAC3F,wCAAwC,KAAK,CAAC,GAAG,2CAA2C;QAC5F,gEAAgE;QAChE,GAAG,IAAI,IAAI;QACX,0BAA0B,CAC3B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yEAAyE;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,4FAA4F,CAAC;AAc1H,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAoB;IAClD,MAAM,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,wBAAwB,CAAC;IAC/D,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IACrG,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,gBAAgB,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,MAAM,IAAI,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,CACL,qCAAqC,UAAU,CAAC,QAAQ,CAAC,WAAW,KAAK,CAAC,IAAI,IAAI,SAAS,KAAK;QAChG,uCAAuC,KAAK,CAAC,GAAG,eAAe,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI;QAC3F,wCAAwC,KAAK,CAAC,GAAG,2CAA2C;QAC5F,yFAAyF;QACzF,GAAG,IAAI,IAAI;QACX,0BAA0B,CAC3B,CAAC;AACJ,CAAC"}
package/dist/outbox.js CHANGED
@@ -1,43 +1,81 @@
1
- import { mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
1
+ import { appendFileSync, closeSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync, writeSync, } from 'node:fs';
2
2
  import { homedir } from 'node:os';
3
3
  import { join } from 'node:path';
4
4
  import process from 'node:process';
5
+ import { randomBytes } from 'node:crypto';
5
6
  import { MultichatError } from './errors.js';
6
7
  import { checkAndRecord, rateKey } from './rate-limit.js';
7
8
  /**
8
- * Opportunistic outbox (B10): when a codex delivery fails with
9
- * CODEX_THREAD_BUSY_TIMEOUT / CODEX_THREAD_LOCKED, the fully composed envelope
10
- * is parked on disk (one JSON file per thread under
9
+ * Opportunistic outbox (B10/B11, reworked B12): when a codex delivery fails
10
+ * with CODEX_THREAD_BUSY_TIMEOUT / CODEX_THREAD_LOCKED, the fully composed
11
+ * envelope is parked on disk (one JSON file per thread under
11
12
  * %LOCALAPPDATA%/crosschat/outbox/) and re-delivered verbatim by the next
12
- * send/status invocation. No daemon; drains are short-wait and never block
13
- * the invoking command for long.
13
+ * send/status invocation or by the detached watchdog loop (src/watchdog.ts).
14
+ *
15
+ * B12 invariants, learned from the 2026-10-02 incident:
16
+ * - busy/locked is a THREAD-level state: one failing attempt aborts the whole
17
+ * thread for this round instead of burning the budget on guaranteed failures
18
+ * (the old loop starved queue tails to attempts=0 for 12h).
19
+ * - new sends join the queue instead of jumping it (enforced in send.ts).
20
+ * - every parked/delivered/dropped item is mirrored into a human-readable
21
+ * mailbox file so stuck content is always readable.
22
+ * - park/drain mutations take a per-thread lockfile so the watchdog and CLI
23
+ * drains cannot lose items by racing read-modify-write cycles.
14
24
  */
15
- export const OUTBOX_MAX_PER_THREAD = 20;
25
+ export const OUTBOX_MAX_PER_THREAD = 200;
16
26
  /** Short wait for drains: opportunistic relief must not block the real command. */
17
27
  const DEFAULT_DRAIN_BUSY_TIMEOUT_MS = 5_000;
18
28
  /** B11: a drain round re-delivers at most this many items (rest waits for the next round). */
19
29
  const DEFAULT_DRAIN_MAX_ITEMS = 5;
20
30
  /** B11: wall-clock budget for one drain round, judged on the injected clock. */
21
31
  const DEFAULT_DRAIN_BUDGET_MS = 15_000;
32
+ /** Per-thread lockfile staleness; a crashed holder is stolen after this. */
33
+ const LOCK_STALE_MS = 60_000;
22
34
  export function defaultOutboxDir() {
23
35
  return join(process.env.LOCALAPPDATA ?? homedir(), 'crosschat', 'outbox');
24
36
  }
37
+ /** Mailbox mirror lives next to the outbox root (sibling "mailbox" directory). */
38
+ export function mailboxDirFor(outboxDir) {
39
+ return join(outboxDir, '..', 'mailbox');
40
+ }
41
+ export function mailboxFileFor(outboxDir, threadId) {
42
+ return join(mailboxDirFor(outboxDir), `${threadId}.md`);
43
+ }
44
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
45
+ function genId(nowMs) {
46
+ return `${nowMs.toString(36)}-${randomBytes(3).toString('hex')}`;
47
+ }
48
+ function isoOf(nowMs) {
49
+ return new Date(nowMs).toISOString();
50
+ }
25
51
  /** Append one parked item (FIFO); refuses honestly past the per-thread cap. */
26
- export function park(dir, threadId, item, nowMs = Date.now()) {
27
- const items = readItems(dir, threadId) ?? []; // missing/corrupt: self-heal as empty
28
- if (items.length >= OUTBOX_MAX_PER_THREAD) {
29
- throw new MultichatError('OUTBOX_FULL', `Outbox full for codex thread ${threadId} (${OUTBOX_MAX_PER_THREAD} parked). ` +
30
- `线程疑似已死:改投其它线程,或人工清理 ${threadFile(dir, threadId)}。`);
52
+ export function park(dir, threadId, item, nowMs = Date.now(), mailboxDir = mailboxDirFor(dir)) {
53
+ // Best-effort lock: a contended park falls through lockless (ms-scale window,
54
+ // same risk as pre-B12) rather than blocking the sending command.
55
+ const locked = acquireThreadLock(dir, threadId, Date.now());
56
+ try {
57
+ const items = readItems(dir, threadId) ?? []; // missing/corrupt: self-heal as empty
58
+ if (items.length >= OUTBOX_MAX_PER_THREAD) {
59
+ throw new MultichatError('OUTBOX_FULL', `Outbox full for codex thread ${threadId} (${OUTBOX_MAX_PER_THREAD} parked). ` +
60
+ `对方线程持续忙或已死:读 ${join(mailboxDir, `${threadId}.md`)} 取回内容,` +
61
+ `或确认线程仍存在后重发。`);
62
+ }
63
+ const parked = { ...item, id: genId(nowMs), parkedAt: nowMs, attempts: 0 };
64
+ writeItems(dir, threadId, [...items, parked]);
65
+ appendMailbox(mailboxDir, threadId, `\n## ${parked.id} 寄存 ${isoOf(nowMs)}(队列第 ${items.length + 1} 位)\n${parked.envelope}\n`);
66
+ return parked;
67
+ }
68
+ finally {
69
+ if (locked)
70
+ releaseThreadLock(dir, threadId);
31
71
  }
32
- const parked = { ...item, parkedAt: nowMs, attempts: 0 };
33
- writeItems(dir, threadId, [...items, parked]);
34
- return parked;
35
72
  }
36
73
  /**
37
- * Try parked items once, in FIFO order, under a per-round budget. Success
38
- * removes the item; a still busy/locked thread keeps it with attempts+1;
39
- * CODEX_THREAD_NOT_FOUND dead-letters the whole thread (deleted threads are
40
- * unreachable forever); any other error keeps the item for a later drain.
74
+ * Deliver parked items head-first, one at a time: each delivery re-reads the
75
+ * file under the thread lock and removes exactly the delivered id, so a
76
+ * concurrent park is never lost. A busy/locked failure aborts the thread for
77
+ * this round (the state is thread-level); CODEX_THREAD_NOT_FOUND dead-letters
78
+ * the whole thread; any other error skips just that item for this round.
41
79
  * Never throws (corrupt files are skipped, a missing dir is a no-op), so it
42
80
  * can run before any command without failing it.
43
81
  */
@@ -45,6 +83,7 @@ export async function drain(dir, deliverFn, opts = {}) {
45
83
  const busyTimeoutMs = opts.busyTimeoutMs ?? DEFAULT_DRAIN_BUSY_TIMEOUT_MS;
46
84
  const maxItems = opts.maxItems ?? DEFAULT_DRAIN_MAX_ITEMS;
47
85
  const budgetMs = opts.budgetMs ?? DEFAULT_DRAIN_BUDGET_MS;
86
+ const mailboxDir = opts.mailboxDir ?? mailboxDirFor(dir);
48
87
  const now = opts.now ?? Date.now;
49
88
  const deadline = now() + budgetMs;
50
89
  let allowance = maxItems;
@@ -60,25 +99,32 @@ export async function drain(dir, deliverFn, opts = {}) {
60
99
  if (!file.endsWith('.json'))
61
100
  continue;
62
101
  const threadId = file.slice(0, -'.json'.length);
63
- const items = readItems(dir, threadId);
64
- if (items === undefined)
65
- continue; // missing/corrupt: leave the file alone
66
- const remaining = [];
102
+ // Items to ignore for the rest of this round (rate-window full, unknown
103
+ // delivery error): kept verbatim, retried by the next round.
104
+ const skipIds = new Set();
67
105
  let delivered = 0;
68
106
  let dropped = 0;
69
- let deliveredName = '';
70
- for (const item of items) {
71
- if (allowance <= 0 || now() >= deadline) {
72
- remaining.push(item); // round budget exhausted: keep verbatim for the next drain
73
- continue;
74
- }
107
+ let toName = '';
108
+ for (;;) {
109
+ if (allowance <= 0 || now() >= deadline)
110
+ break;
111
+ const head = await withThreadLock(dir, threadId, 2_000, () => {
112
+ const items = readItems(dir, threadId);
113
+ if (items === undefined || items.length === 0)
114
+ return undefined;
115
+ const item = items.find((candidate) => !skipIds.has(candidate.id));
116
+ return item === undefined ? undefined : { item };
117
+ });
118
+ if (head === undefined)
119
+ break;
120
+ toName = head.item.toName;
75
121
  if (opts.rateDir !== undefined) {
76
122
  try {
77
- checkAndRecord(opts.rateDir, rateKey(item.callerKey ?? 'human', `codex:${threadId}`), now());
123
+ checkAndRecord(opts.rateDir, rateKey(head.item.callerKey ?? 'human', `codex:${threadId}`), now());
78
124
  }
79
125
  catch (err) {
80
126
  if (err instanceof MultichatError && err.code === 'RATE_LIMITED') {
81
- remaining.push(item); // window full: skip this round, retry next drain
127
+ skipIds.add(head.item.id); // window full: skip this round, retry next drain
82
128
  continue;
83
129
  }
84
130
  throw err;
@@ -86,44 +132,51 @@ export async function drain(dir, deliverFn, opts = {}) {
86
132
  }
87
133
  allowance -= 1;
88
134
  try {
89
- await deliverFn(threadId, item.envelope, busyTimeoutMs);
135
+ await deliverFn(threadId, head.item.envelope, busyTimeoutMs);
90
136
  delivered++;
91
- deliveredName = item.toName;
137
+ appendMailbox(mailboxDir, threadId, `> ${head.item.id} 送达 ${isoOf(now())}\n`);
138
+ await withThreadLock(dir, threadId, 2_000, () => {
139
+ removeById(dir, threadId, head.item.id);
140
+ });
92
141
  }
93
142
  catch (err) {
94
143
  if (err instanceof MultichatError && err.code === 'CODEX_THREAD_NOT_FOUND') {
95
144
  // Dead letter: the thread is gone, so every parked item for it is
96
145
  // unreachable — discard all of them, not just this one.
97
- dropped = items.length - delivered;
98
- remaining.length = 0;
146
+ const removed = (await withThreadLock(dir, threadId, 2_000, () => {
147
+ const items = readItems(dir, threadId) ?? [];
148
+ writeItems(dir, threadId, []);
149
+ return items.length;
150
+ })) ?? 0;
151
+ dropped += removed;
152
+ appendMailbox(mailboxDir, threadId, `> 线程已不存在,丢弃 ${removed} 条(${isoOf(now())})\n`);
99
153
  break;
100
154
  }
101
155
  if (err instanceof MultichatError &&
102
156
  (err.code === 'CODEX_THREAD_BUSY_TIMEOUT' || err.code === 'CODEX_THREAD_LOCKED')) {
103
- // ponytail: attempts grows unbounded; cap/age-out if a stuck thread ever floods the file.
104
- remaining.push({ ...item, attempts: item.attempts + 1 });
105
- }
106
- else {
107
- remaining.push(item); // unknown state: keep, try again next drain
157
+ // Thread-level state: everything after the head would fail too.
158
+ await withThreadLock(dir, threadId, 2_000, () => {
159
+ bumpAttempts(dir, threadId, head.item.id);
160
+ });
161
+ break;
108
162
  }
163
+ skipIds.add(head.item.id); // unknown state: keep, try again next drain
109
164
  }
110
165
  }
111
- const changed = remaining.length !== items.length || remaining.some((item, i) => item !== items[i]);
112
- if (changed)
113
- writeItems(dir, threadId, remaining);
114
- if (delivered > 0 || remaining.length > 0 || dropped > 0) {
166
+ const remaining = countItems(dir, threadId);
167
+ if (delivered > 0 || remaining > 0 || dropped > 0) {
115
168
  results.push({
116
169
  threadId,
117
- toName: deliveredName || items.at(-1)?.toName || threadId,
170
+ toName: toName || shortThread(threadId),
118
171
  delivered,
119
- remaining: remaining.length,
172
+ remaining,
120
173
  dropped,
121
174
  });
122
175
  }
123
176
  }
124
177
  return results;
125
178
  }
126
- /** Parked item count per thread (doctor display); corrupt/empty files are skipped. */
179
+ /** Parked item count + oldest age per thread (doctor display); corrupt files are skipped. */
127
180
  export function outboxSummary(dir) {
128
181
  let files;
129
182
  try {
@@ -138,18 +191,62 @@ export function outboxSummary(dir) {
138
191
  continue;
139
192
  const threadId = file.slice(0, -'.json'.length);
140
193
  const items = readItems(dir, threadId);
141
- if (items !== undefined && items.length > 0)
142
- summary.push({ threadId, count: items.length });
194
+ if (items !== undefined && items.length > 0) {
195
+ summary.push({
196
+ threadId,
197
+ count: items.length,
198
+ oldestParkedAt: Math.min(...items.map((item) => item.parkedAt)),
199
+ });
200
+ }
143
201
  }
144
202
  return summary;
145
203
  }
204
+ /** Queue depth for one thread (0 when nothing is parked). */
205
+ export function outboxCount(dir, threadId) {
206
+ return readItems(dir, threadId)?.length ?? 0;
207
+ }
208
+ /**
209
+ * Parked counts keyed by unordered pair key — caller identity × `codex:<thread>`,
210
+ * joined with the same sort + '\n' convention as conversations.ts pairKeyOf
211
+ * (status batch B0). Items without a caller key count under 'human', the same
212
+ * fallback the drain's rate limiter uses. Corrupt files are skipped.
213
+ */
214
+ export function outboxPairCounts(dir) {
215
+ let files;
216
+ try {
217
+ files = readdirSync(dir);
218
+ }
219
+ catch {
220
+ return new Map();
221
+ }
222
+ const counts = new Map();
223
+ for (const file of files) {
224
+ if (!file.endsWith('.json'))
225
+ continue;
226
+ const threadId = file.slice(0, -'.json'.length);
227
+ for (const item of readItems(dir, threadId) ?? []) {
228
+ const key = [item.callerKey ?? 'human', `codex:${threadId}`].sort().join('\n');
229
+ counts.set(key, (counts.get(key) ?? 0) + 1);
230
+ }
231
+ }
232
+ return counts;
233
+ }
234
+ function shortThread(threadId) {
235
+ return `codex/${threadId.slice(0, 8)}`;
236
+ }
146
237
  function threadFile(dir, threadId) {
147
238
  return join(dir, `${threadId}.json`);
148
239
  }
240
+ function lockFile(dir, threadId) {
241
+ return join(dir, `${threadId}.lock`);
242
+ }
149
243
  function readItems(dir, threadId) {
150
244
  try {
151
245
  const parsed = JSON.parse(readFileSync(threadFile(dir, threadId), 'utf8'));
152
- return Array.isArray(parsed.items) ? parsed.items : undefined;
246
+ if (!Array.isArray(parsed.items))
247
+ return undefined;
248
+ // Pre-B12 files carry no id: synthesize a stable one from parkedAt+index.
249
+ return parsed.items.map((item, index) => item.id === undefined ? { ...item, id: `${item.parkedAt.toString(36)}-${index.toString(36)}` } : item);
153
250
  }
154
251
  catch {
155
252
  return undefined;
@@ -163,10 +260,91 @@ function writeItems(dir, threadId, items) {
163
260
  return;
164
261
  }
165
262
  mkdirSync(dir, { recursive: true });
166
- // ponytail: no cross-process locking; two concurrent drains can double-deliver
167
- // one item — rare and downstream-idempotent enough; add a lockfile if it bites.
168
263
  const tmp = join(dir, `${threadId}.${process.pid}.${Date.now()}.tmp`);
169
264
  writeFileSync(tmp, JSON.stringify({ items }), 'utf8');
170
265
  renameSync(tmp, file);
171
266
  }
267
+ function removeById(dir, threadId, id) {
268
+ const items = readItems(dir, threadId);
269
+ if (items === undefined)
270
+ return;
271
+ writeItems(dir, threadId, items.filter((item) => item.id !== id));
272
+ }
273
+ function bumpAttempts(dir, threadId, id) {
274
+ const items = readItems(dir, threadId);
275
+ if (items === undefined)
276
+ return;
277
+ writeItems(dir, threadId, items.map((item) => (item.id === id ? { ...item, attempts: item.attempts + 1 } : item)));
278
+ }
279
+ function countItems(dir, threadId) {
280
+ return readItems(dir, threadId)?.length ?? 0;
281
+ }
282
+ function appendMailbox(mailboxDir, threadId, text) {
283
+ try {
284
+ mkdirSync(mailboxDir, { recursive: true });
285
+ appendFileSync(join(mailboxDir, `${threadId}.md`), text, 'utf8');
286
+ }
287
+ catch {
288
+ // ponytail: the mirror is best-effort observability; outbox json stays authoritative.
289
+ }
290
+ }
291
+ function acquireThreadLock(dir, threadId, nowMs) {
292
+ const file = lockFile(dir, threadId);
293
+ for (let attempt = 0; attempt < 2; attempt++) {
294
+ try {
295
+ const fd = openExclusive(file);
296
+ writeSyncClose(fd, `${process.pid} ${nowMs}`);
297
+ return true;
298
+ }
299
+ catch (err) {
300
+ if (err.code !== 'EEXIST')
301
+ return false;
302
+ try {
303
+ const [, ts] = readFileSync(file, 'utf8').trim().split(/\s+/);
304
+ const written = Number(ts);
305
+ if (Number.isFinite(written) && nowMs - written > LOCK_STALE_MS) {
306
+ rmSync(file, { force: true }); // steal a crashed holder's lock
307
+ continue;
308
+ }
309
+ }
310
+ catch {
311
+ return false;
312
+ }
313
+ return false;
314
+ }
315
+ }
316
+ return false;
317
+ }
318
+ function releaseThreadLock(dir, threadId) {
319
+ rmSync(lockFile(dir, threadId), { force: true });
320
+ }
321
+ /** Run fn under the per-thread lock, waiting up to waitMs; undefined = never ran. */
322
+ async function withThreadLock(dir, threadId, waitMs, fn) {
323
+ const deadline = Date.now() + waitMs;
324
+ for (;;) {
325
+ if (acquireThreadLock(dir, threadId, Date.now())) {
326
+ try {
327
+ return fn();
328
+ }
329
+ finally {
330
+ releaseThreadLock(dir, threadId);
331
+ }
332
+ }
333
+ if (Date.now() >= deadline)
334
+ return undefined;
335
+ await sleep(25);
336
+ }
337
+ }
338
+ // fs.open with "wx" lives behind openSync's flag form; keep it tiny and local.
339
+ function openExclusive(file) {
340
+ return openSync(file, 'wx');
341
+ }
342
+ function writeSyncClose(fd, text) {
343
+ try {
344
+ writeSync(fd, text, null, 'utf8');
345
+ }
346
+ finally {
347
+ closeSync(fd);
348
+ }
349
+ }
172
350
  //# sourceMappingURL=outbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../src/outbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../src/outbox.ts"],"names":[],"mappings":"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"}