chat-recall 0.5.22 → 0.5.24

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,17 @@
1
+ /** One request the collector made. */
2
+ export interface RecordedRequest {
3
+ method: string;
4
+ path: string;
5
+ /** Parsed JSON body, when there was one. */
6
+ body?: unknown;
7
+ }
8
+ export interface ConformantServer {
9
+ url: string;
10
+ /** Every request, in order — the record a test asserts against. */
11
+ requests: RecordedRequest[];
12
+ /** The conversations POSTed to /api/sync across every upload. */
13
+ uploaded: () => Array<Record<string, unknown>>;
14
+ close: () => Promise<void>;
15
+ }
16
+ export declare function startConformantServer(): Promise<ConformantServer>;
17
+ //# sourceMappingURL=conformant-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformant-server.d.ts","sourceRoot":"","sources":["../src/conformant-server.ts"],"names":[],"mappings":"AAyBA,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,mEAAmE;IACnE,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/C,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAmBD,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CA4EvE"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * The SMALLEST server the collector will successfully sync to.
3
+ *
4
+ * ── Why this exists, next to hostile-server.ts ────────────────────────────
5
+ * hostile-server.ts proves the CLI describes a BROKEN server correctly. Nothing
6
+ * proved the CLI can complete a sync at all except the compose-integration
7
+ * workflow, which needs Docker and therefore runs on Linux only. So on macOS and
8
+ * Windows the gate said: it installs, it prints a version, it boots the MCP
9
+ * server, and it fails gracefully. Whether `login` then `sync` actually uploads
10
+ * a session on those two platforms was never checked anywhere.
11
+ *
12
+ * Every failure that gap could hide is platform-shaped — path separators, a
13
+ * case-insensitive filesystem, a home directory with a space in it, CRLF in a
14
+ * transcript, a Windows temp path in a project id. This answers it with no
15
+ * Docker and no network: an in-process HTTP server that speaks enough of the API
16
+ * for a real `login --token` and a real `sync` to succeed, and that RECORDS what
17
+ * it was sent so a test can assert the session actually arrived.
18
+ *
19
+ * It is deliberately not a fake of the product. It has no storage, no tenants
20
+ * and no search. It answers the seven endpoints the collector's sync path calls,
21
+ * with the minimum each one needs, and keeps the request bodies.
22
+ */
23
+ import { createServer } from 'node:http';
24
+ import { gunzipSync } from 'node:zlib';
25
+ /** The API version this stub claims. Must be >= the collector's floor. */
26
+ const API_VERSION = 2;
27
+ async function readBody(req) {
28
+ const chunks = [];
29
+ for await (const c of req)
30
+ chunks.push(c);
31
+ if (chunks.length === 0)
32
+ return undefined;
33
+ let raw = Buffer.concat(chunks);
34
+ // The collector gzips a body when the server advertises it. This one does not
35
+ // advertise it, but decode anyway rather than fail confusingly if that ever
36
+ // changes.
37
+ if (req.headers['content-encoding'] === 'gzip') {
38
+ try {
39
+ raw = gunzipSync(raw);
40
+ }
41
+ catch { /* fall through to a parse failure */ }
42
+ }
43
+ try {
44
+ return JSON.parse(raw.toString('utf8'));
45
+ }
46
+ catch {
47
+ return raw.toString('utf8');
48
+ }
49
+ }
50
+ export async function startConformantServer() {
51
+ const requests = [];
52
+ const conversations = [];
53
+ const server = createServer((req, res) => {
54
+ void (async () => {
55
+ const path = (req.url || '').split('?')[0];
56
+ const body = await readBody(req);
57
+ requests.push({ method: req.method || 'GET', path, body });
58
+ const json = (status, payload) => {
59
+ res.writeHead(status, { 'content-type': 'application/json' });
60
+ res.end(JSON.stringify(payload));
61
+ };
62
+ switch (path) {
63
+ case '/api/capabilities':
64
+ // apiVersion is what verifyServerApi requires; `limits` is what it
65
+ // learns from here instead of assuming.
66
+ return json(200, {
67
+ apiVersion: API_VERSION,
68
+ edition: 'test-stub',
69
+ authProvider: 'none',
70
+ oidcIssuer: null,
71
+ limits: { ingestConcurrencyPerTenant: 2, acceptsGzipBody: false },
72
+ });
73
+ case '/api/status':
74
+ // Used by `login` to verify a token, and by `status`.
75
+ return json(200, { ok: true, sessions: 0 });
76
+ case '/api/secrets/rules':
77
+ // No tenant rules; the collector's compiled-in redactors still apply.
78
+ return json(200, { version: 'stub-1', rules: [], pack: { version: 'stub-1', rules: [] } });
79
+ case '/api/teams/security-config':
80
+ return json(200, { verifySecrets: true, telemetry: false });
81
+ case '/api/sync-config/sources':
82
+ // The collector REPORTS its sources here; nothing to answer.
83
+ return json(200, { ok: true });
84
+ case '/api/sync-config':
85
+ // No server-side exclusions. An empty set here is a real answer, and
86
+ // the collector refuses to sync when it cannot get one at all.
87
+ return json(200, { excludeTools: [], excludeProjects: [], excludeSources: [], approveSources: [] });
88
+ case '/api/sync': {
89
+ const b = body;
90
+ if (Array.isArray(b?.conversations))
91
+ conversations.push(...b.conversations);
92
+ // `cli: null` so the collector never tries to self-update from a stub.
93
+ return json(200, { accepted: b?.conversations?.length ?? 0, full_resync_needed: [], cli: null, telemetry: false });
94
+ }
95
+ default:
96
+ // A 404 here is honest: this stub implements the sync path, not the
97
+ // whole API. Anything the collector needs and does not get shows up as
98
+ // a named endpoint in `requests`, which is how this stays minimal.
99
+ return json(404, { error: 'not implemented by the conformant stub', path });
100
+ }
101
+ })();
102
+ });
103
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
104
+ const addr = server.address();
105
+ const port = typeof addr === 'object' && addr ? addr.port : 0;
106
+ return {
107
+ url: `http://127.0.0.1:${port}`,
108
+ requests,
109
+ uploaded: () => conversations,
110
+ close: () => new Promise((resolve) => {
111
+ server.closeAllConnections?.();
112
+ server.close(() => resolve());
113
+ }),
114
+ };
115
+ }
116
+ //# sourceMappingURL=conformant-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformant-server.js","sourceRoot":"","sources":["../src/conformant-server.ts"],"names":[],"mappings":"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"}
@@ -7,10 +7,6 @@ export interface DeviceTokens {
7
7
  refreshToken?: string;
8
8
  expiresIn: number;
9
9
  }
10
- /**
11
- * Run the full device flow. `onPrompt` receives the human-facing instructions
12
- * (verification URL + code) so the caller controls presentation.
13
- */
14
10
  export declare function deviceLogin(opts: {
15
11
  issuer?: string;
16
12
  clientId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"device-auth.d.ts","sourceRoot":"","sources":["../src/device-auth.ts"],"names":[],"mappings":"AAyBA;iFACiF;AACjF,eAAO,MAAM,cAAc,QAA4C,CAAC;AACxE,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5D,QAAQ,EAAE,CAAC,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,GAChF,OAAO,CAAC,YAAY,CAAC,CAqEvB;AAED;yEACyE;AACzE,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAE3D;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,GAChF,OAAO,CAAC,YAAY,CAAC,CAiDvB"}
1
+ {"version":3,"file":"device-auth.d.ts","sourceRoot":"","sources":["../src/device-auth.ts"],"names":[],"mappings":"AAyBA;iFACiF;AACjF,eAAO,MAAM,cAAc,QAA4C,CAAC;AACxE,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AA8DD,wBAAsB,WAAW,CAC/B,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5D,QAAQ,EAAE,CAAC,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,GAChF,OAAO,CAAC,YAAY,CAAC,CAqEvB;AAED;yEACyE;AACzE,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAE3D;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,GAChF,OAAO,CAAC,YAAY,CAAC,CAiDvB"}
@@ -30,6 +30,47 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
30
30
  * Run the full device flow. `onPrompt` receives the human-facing instructions
31
31
  * (verification URL + code) so the caller controls presentation.
32
32
  */
33
+ /**
34
+ * Read a device-code response, or say what answered instead.
35
+ *
36
+ * TWO FAILURES CAME THROUGH THIS ONE LINE (`await startRes.json()`):
37
+ *
38
+ * - a 200 carrying HTML — a login wall or a parked domain — threw
39
+ * "Unexpected token '<', \"<!DOCTYPE \"... is not valid JSON", which names
40
+ * neither the host nor the fix;
41
+ * - a 200 carrying SOMEBODY ELSE'S JSON parsed fine, every field came back
42
+ * undefined, and the CLI printed
43
+ *
44
+ * To log in, open:
45
+ * undefined
46
+ * (if prompted, enter code: undefined at undefined)
47
+ * Waiting for approval…
48
+ *
49
+ * then polled a stranger's endpoint until the (undefined → NaN) deadline
50
+ * expired and reported "the code expired before approval". The user waited
51
+ * for a link that never existed.
52
+ *
53
+ * So: read as text, parse defensively, and require the three fields RFC 8628
54
+ * makes mandatory before telling a human to go and approve something.
55
+ */
56
+ async function readDeviceCode(res, where) {
57
+ const text = await res.text().catch(() => '');
58
+ let parsed;
59
+ try {
60
+ parsed = JSON.parse(text);
61
+ }
62
+ catch {
63
+ throw new Error(`${where} answered ${res.status} with something that is not a device-code response `
64
+ + `(${JSON.stringify(text.trim().slice(0, 60))}) — this host is not serving the chat-recall API`);
65
+ }
66
+ const d = parsed;
67
+ if (typeof d?.device_code !== 'string' || typeof d?.user_code !== 'string'
68
+ || typeof d?.verification_uri !== 'string' || typeof d?.expires_in !== 'number') {
69
+ throw new Error(`${where} answered ${res.status} with JSON that is not a device-code response `
70
+ + `(${JSON.stringify(text.trim().slice(0, 60))}) — this host is not serving the chat-recall API`);
71
+ }
72
+ return d;
73
+ }
33
74
  export async function deviceLogin(opts, onPrompt) {
34
75
  const issuer = (opts.issuer || DEFAULT_ISSUER).replace(/\/+$/, '');
35
76
  if (!issuer) {
@@ -51,7 +92,7 @@ export async function deviceLogin(opts, onPrompt) {
51
92
  if (!startRes.ok) {
52
93
  throw new Error(`device-auth init failed: HTTP ${startRes.status} ${await startRes.text().catch(() => '')}`);
53
94
  }
54
- const start = (await startRes.json());
95
+ const start = await readDeviceCode(startRes, issuer);
55
96
  onPrompt({
56
97
  url: start.verification_uri_complete || start.verification_uri,
57
98
  userCode: start.user_code,
@@ -117,7 +158,7 @@ export async function betterAuthDeviceLogin(serverUrl, onPrompt) {
117
158
  if (!startRes.ok) {
118
159
  throw new Error(`device-auth init failed: HTTP ${startRes.status} ${await startRes.text().catch(() => '')}`);
119
160
  }
120
- const start = (await startRes.json());
161
+ const start = await readDeviceCode(startRes, base);
121
162
  onPrompt({
122
163
  url: start.verification_uri_complete || start.verification_uri,
123
164
  userCode: start.user_code,
@@ -1 +1 @@
1
- {"version":3,"file":"device-auth.js","sourceRoot":"","sources":["../src/device-auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"device-auth.js","sourceRoot":"","sources":["../src/device-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAE9G;iFACiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC;AACxE,MAAM,CAAC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAiBnD,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpE;;;GAGG;AACH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,KAAK,UAAU,cAAc,CAAC,GAAa,EAAE,KAAa;IACxD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,aAAa,GAAG,CAAC,MAAM,qDAAqD;cAClF,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kDAAkD,CACjG,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,GAAG,MAAqC,CAAC;IAChD,IAAI,OAAO,CAAC,EAAE,WAAW,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,SAAS,KAAK,QAAQ;WACrE,OAAO,CAAC,EAAE,gBAAgB,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,UAAU,KAAK,QAAQ,EAAE,CAAC;QAClF,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,aAAa,GAAG,CAAC,MAAM,gDAAgD;cAC7E,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kDAAkD,CACjG,CAAC;IACJ,CAAC;IACD,OAAO,CAAuB,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAA4D,EAC5D,QAAiF;IAEjF,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,oEAAoE;cAClE,2DAA2D;cAC3D,mDAAmD;cACnD,4DAA4D,CAC/D,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,iBAAiB,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,sBAAsB,CAAC;IAEnD,yEAAyE;IACzE,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAEjF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,sCAAsC,EAAE;QAC5E,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;QAChE,IAAI,EAAE,IAAI,eAAe,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,EAAE,CAAC;KACxH,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAErD,QAAQ,CAAC;QACP,GAAG,EAAE,KAAK,CAAC,yBAAyB,IAAI,KAAK,CAAC,gBAAgB;QAC9D,QAAQ,EAAE,KAAK,CAAC,SAAS;QACzB,eAAe,EAAE,KAAK,CAAC,gBAAgB;KACxC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,GAAG,MAAM,gCAAgC,CAAC;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;IACtD,IAAI,QAAQ,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAE5C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,IAAI,eAAe,CAAC;gBACxB,qEAAqE;gBACrE,kEAAkE;gBAClE,oEAAoE;gBACpE,8CAA8C;gBAC9C,UAAU,EAAE,8CAA8C;gBAC1D,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,SAAS,EAAE,QAAQ;gBACnB,aAAa,EAAE,YAAY;aAC5B,CAAC;SACH,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAA4B,CAAC;QAC7E,IAAI,GAAG,CAAC,EAAE,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACpD,OAAO;gBACL,WAAW,EAAE,IAAI,CAAC,YAAY;gBAC9B,YAAY,EAAE,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;gBACrF,SAAS,EAAE,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;aACrE,CAAC;QACJ,CAAC;QACD,+EAA+E;QAC/E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC;QACvB,IAAI,GAAG,KAAK,uBAAuB;YAAE,SAAS;QAC9C,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAAC,QAAQ,IAAI,IAAI,CAAC;YAAC,SAAS;QAAC,CAAC;QACxD,IAAI,GAAG,KAAK,eAAe;YAAE,MAAM;QACnC,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,CAAC,GAAG,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;AAC/E,CAAC;AAED;yEACyE;AACzE,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,SAAiB,EACjB,QAAiF;IAEjF,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,uBAAuB,EAAE;QAC3D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,yBAAyB,EAAE,CAAC;KAC/D,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAEnD,QAAQ,CAAC;QACP,GAAG,EAAE,KAAK,CAAC,yBAAyB,IAAI,KAAK,CAAC,gBAAgB;QAC9D,QAAQ,EAAE,KAAK,CAAC,SAAS;QACzB,eAAe,EAAE,KAAK,CAAC,gBAAgB;KACxC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;IACtD,IAAI,QAAQ,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAE5C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,wBAAwB,EAAE;YACvD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,UAAU,EAAE,8CAA8C;gBAC1D,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,SAAS,EAAE,yBAAyB;aACrC,CAAC;SACH,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAA4B,CAAC;QAC7E,IAAI,GAAG,CAAC,EAAE,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACpD,OAAO;gBACL,WAAW,EAAE,IAAI,CAAC,YAAY;gBAC9B,SAAS,EAAE,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;aACrE,CAAC;QACJ,CAAC;QACD,wDAAwD;QACxD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC;QACvB,IAAI,GAAG,KAAK,uBAAuB;YAAE,SAAS;QAC9C,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAAC,QAAQ,IAAI,IAAI,CAAC;YAAC,SAAS;QAAC,CAAC;QACxD,IAAI,GAAG,KAAK,eAAe,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,2DAA2D,CAAC,CAAC;QAChJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,CAAC,GAAG,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,47 @@
1
+ export type HostileMode =
2
+ /** A retired route behind Traefik/nginx: plain text, HTTP 404. THE one that
3
+ * produced the JSON parse error, because `404 page not found` parses as the
4
+ * number 404 and then fails at position 4. */
5
+ 'text404'
6
+ /** A parked domain or a login wall: HTML with a 200. */
7
+ | 'html200'
8
+ /** An upstream that is up but broken. */
9
+ | 'gateway502'
10
+ /** Authenticated but forbidden — a revoked device token looks like this. */
11
+ | 'forbidden403'
12
+ /** 200, valid JSON, but not our API: a different service on the same host. */
13
+ | 'notOurApi'
14
+ /** Accepts the connection and never answers. A dropped packet looks like this
15
+ * to the client, and it is the failure people describe as "it just hangs". */
16
+ | 'silent';
17
+ export interface HostileServer {
18
+ url: string;
19
+ /** Every path the CLI actually asked for, in order. A test that only checks
20
+ * the printed message cannot tell "the CLI handled a 404 well" from "the CLI
21
+ * never sent a request" — and the first version of this harness spawned the
22
+ * CLI with execFileSync, which blocks the test process's event loop, so this
23
+ * server answered NOTHING and four assertions passed on a timeout. */
24
+ hits: string[];
25
+ close: () => Promise<void>;
26
+ }
27
+ /** Start one. Always on 127.0.0.1 and an ephemeral port, so tests can run in
28
+ * parallel and nothing is exposed. */
29
+ export declare function startHostileServer(mode: HostileMode): Promise<HostileServer>;
30
+ /**
31
+ * A port nothing listens on — connection refused, immediately. Distinct from
32
+ * 'silent' (accepted then ignored) and from a name that does not resolve.
33
+ *
34
+ * IT HAS TO BE A REAL PORT. This returned `http://127.0.0.1:1`, and port 1 is on
35
+ * the WHATWG "bad port" list, so undici refuses the request before it opens a
36
+ * socket and throws a bare `Error: bad port` with no code. The test asserting
37
+ * "a refused port says refused" was therefore never testing a refused port, and
38
+ * it failed against a CLI whose ECONNREFUSED handling was correct all along.
39
+ *
40
+ * Bind an ephemeral port, read it, close it: nothing else can be listening on it
41
+ * at that instant, and the number is one undici will actually dial.
42
+ */
43
+ export declare function refusedUrl(): Promise<string>;
44
+ /** A hostname that cannot resolve. `.invalid` is reserved by RFC 2606 exactly so
45
+ * a test can rely on this without depending on somebody's DNS. */
46
+ export declare function unresolvableUrl(): string;
47
+ //# sourceMappingURL=hostile-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostile-server.d.ts","sourceRoot":"","sources":["../src/hostile-server.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,WAAW;AACrB;;+CAE+C;AAC7C,SAAS;AACX,wDAAwD;GACtD,SAAS;AACX,yCAAyC;GACvC,YAAY;AACd,4EAA4E;GAC1E,cAAc;AAChB,8EAA8E;GAC5E,WAAW;AACb;+EAC+E;GAC7E,QAAQ,CAAC;AAEb,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ;;;;2EAIuE;IACvE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;uCACuC;AACvC,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CA+ClF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAOlD;AAED;mEACmE;AACnE,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Servers that answer BADLY, on demand, so CI can meet them before a user does.
3
+ *
4
+ * Every install bug found on 2026-08-27 was found by a person running a command
5
+ * on a laptop, because the test suite only ever pointed the CLI at a healthy
6
+ * server or at nothing:
7
+ *
8
+ * - a failed capabilities probe reported "No OIDC issuer configured for SSO
9
+ * login" on a service that has never used SSO;
10
+ * - that failure called process.exit(1), so `init` died before configuring MCP;
11
+ * - a retired hostname answered `404 page not found` in text/plain, and the
12
+ * sync client called .json() on it, so the user was shown "Unexpected
13
+ * non-whitespace character after JSON at position 4".
14
+ *
15
+ * None of those need a network to reproduce. They need a server that responds
16
+ * the way real infrastructure does when something is wrong — which is what this
17
+ * is. Each mode is one line of behaviour, deliberately: the point is to be
18
+ * obviously correct, not configurable.
19
+ */
20
+ import { createServer } from 'node:http';
21
+ /** Start one. Always on 127.0.0.1 and an ephemeral port, so tests can run in
22
+ * parallel and nothing is exposed. */
23
+ export async function startHostileServer(mode) {
24
+ const hits = [];
25
+ const server = createServer((req, res) => {
26
+ hits.push(`${req.method} ${req.url}`);
27
+ switch (mode) {
28
+ case 'text404':
29
+ res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });
30
+ res.end('404 page not found');
31
+ return;
32
+ case 'html200':
33
+ res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
34
+ res.end('<!DOCTYPE html><html><body>Nothing here</body></html>');
35
+ return;
36
+ case 'gateway502':
37
+ res.writeHead(502, { 'content-type': 'text/html' });
38
+ res.end('<html><head><title>502 Bad Gateway</title></head></html>');
39
+ return;
40
+ case 'forbidden403':
41
+ res.writeHead(403, { 'content-type': 'application/json' });
42
+ res.end(JSON.stringify({ error: 'forbidden' }));
43
+ return;
44
+ case 'notOurApi':
45
+ res.writeHead(200, { 'content-type': 'application/json' });
46
+ res.end(JSON.stringify({ service: 'something-else', version: 9 }));
47
+ return;
48
+ case 'silent':
49
+ // Deliberately no response and no close: the socket stays open until the
50
+ // client's own timeout fires. `req` is untouched on purpose.
51
+ void req;
52
+ return;
53
+ }
54
+ });
55
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
56
+ const addr = server.address();
57
+ const port = typeof addr === 'object' && addr ? addr.port : 0;
58
+ return {
59
+ url: `http://127.0.0.1:${port}`,
60
+ hits,
61
+ close: () => new Promise((resolve) => {
62
+ // closeAllConnections, or a 'silent' server keeps the process alive with
63
+ // its open socket and the test run hangs at the end instead of exiting.
64
+ server.closeAllConnections?.();
65
+ server.close(() => resolve());
66
+ }),
67
+ };
68
+ }
69
+ /**
70
+ * A port nothing listens on — connection refused, immediately. Distinct from
71
+ * 'silent' (accepted then ignored) and from a name that does not resolve.
72
+ *
73
+ * IT HAS TO BE A REAL PORT. This returned `http://127.0.0.1:1`, and port 1 is on
74
+ * the WHATWG "bad port" list, so undici refuses the request before it opens a
75
+ * socket and throws a bare `Error: bad port` with no code. The test asserting
76
+ * "a refused port says refused" was therefore never testing a refused port, and
77
+ * it failed against a CLI whose ECONNREFUSED handling was correct all along.
78
+ *
79
+ * Bind an ephemeral port, read it, close it: nothing else can be listening on it
80
+ * at that instant, and the number is one undici will actually dial.
81
+ */
82
+ export async function refusedUrl() {
83
+ const probe = createServer();
84
+ await new Promise((resolve) => probe.listen(0, '127.0.0.1', resolve));
85
+ const addr = probe.address();
86
+ const port = typeof addr === 'object' && addr ? addr.port : 0;
87
+ await new Promise((resolve) => probe.close(() => resolve()));
88
+ return `http://127.0.0.1:${port}`;
89
+ }
90
+ /** A hostname that cannot resolve. `.invalid` is reserved by RFC 2606 exactly so
91
+ * a test can rely on this without depending on somebody's DNS. */
92
+ export function unresolvableUrl() {
93
+ return 'https://chat-recall-does-not-exist.invalid';
94
+ }
95
+ //# sourceMappingURL=hostile-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostile-server.js","sourceRoot":"","sources":["../src/hostile-server.ts"],"names":[],"mappings":"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"}