dsh-better-tips 0.12.1 → 0.13.0

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.
@@ -3,6 +3,8 @@ import assert from 'node:assert/strict'
3
3
  import fs, { readFile } from 'node:fs/promises'
4
4
  import { syncBuiltinESMExports } from 'node:module'
5
5
  import { join } from 'node:path'
6
+ import { tmpdir } from 'node:os'
7
+ import { pathToFileURL } from 'node:url'
6
8
  import { apply } from '../index.js'
7
9
 
8
10
  /**
@@ -70,7 +72,7 @@ test('the detail route mounts when connection arrives after plugin activation an
70
72
  const { routes, connect, disposers } = harness({ extraRetries: 0 }, { connectionReady: false })
71
73
  assert.equal(routes.length, 0)
72
74
  connect()
73
- assert.equal(routes.length, 3, 'late service activation must install all three routes')
75
+ assert.equal(routes.length, 4, 'late service activation must install all four routes')
74
76
  const detail = routes.find((entry) => entry.path === '/api/better-tips/details')
75
77
  const result = await detail.fetch(new Request('http://localhost/api/better-tips/details?sessionId=session-1&turn=1'))
76
78
  assert.equal(result.status, 200)
@@ -78,6 +80,221 @@ test('the detail route mounts when connection arrives after plugin activation an
78
80
  assert.equal(routes.length, 0, 'the routes belong to the dependency lifetime')
79
81
  })
80
82
 
83
+ async function reportEnvironment (h, signal) {
84
+ const route = h.routes.find((entry) => entry.path === '/api/better-tips/environment')
85
+ return route.fetch(new Request('http://localhost/api/better-tips/environment', { signal }))
86
+ }
87
+
88
+ async function withInventoryManifests (run) {
89
+ const root = await fs.mkdtemp(join(tmpdir(), 'better-tips-inventory-'))
90
+ const manifests = new Map()
91
+ const reads = new Map()
92
+ const originalRead = fs.readFile
93
+ try {
94
+ const put = async (name, version, suffix = '') => {
95
+ const directory = join(root, name.replace(/[^A-Za-z0-9]/g, '_') + suffix)
96
+ await fs.mkdir(directory, { recursive: true })
97
+ const manifestPath = join(directory, 'package.json')
98
+ await fs.writeFile(manifestPath, JSON.stringify({ name, ...(version === undefined ? {} : { version }), privateConfig: 'DO_NOT_EXPORT_CONFIG' }))
99
+ manifests.set(name + suffix, manifestPath)
100
+ return manifestPath
101
+ }
102
+ fs.readFile = async (path, ...args) => { const key = String(path); reads.set(key, (reads.get(key) ?? 0) + 1); return originalRead(path, ...args) }
103
+ syncBuiltinESMExports()
104
+ await run({ put, manifests, reads, root })
105
+ } finally {
106
+ fs.readFile = originalRead; syncBuiltinESMExports()
107
+ // root is the exact directory returned by mkdtemp above, owned by this fixture.
108
+ await fs.rm(root, { recursive: true, force: true })
109
+ }
110
+ }
111
+
112
+ test('report environment collects enabled host entries and bundles using exact Loader anchors', async () => {
113
+ await withInventoryManifests(async ({ put, reads }) => {
114
+ const plugin = await put('@fixture/plugin', '1.2.3')
115
+ const otherVersion = await put('@fixture/plugin', '2.0.0', '-other')
116
+ const core = await put('@deepseek-ai/core', '0.2.2-rc.2')
117
+ const baseA = pathToFileURL(join(tmpdir(), 'tree-a.yml')).href
118
+ const baseB = pathToFileURL(join(tmpdir(), 'tree-b.yml')).href
119
+ const entries = [
120
+ { options: { name: '@fixture/plugin/client' }, disabled: false, parent: { tree: { ctx: { baseUrl: baseA } } }, fiber: { state: 'failed' } },
121
+ { options: { name: '@fixture/plugin/tools' }, disabled: false, parent: { tree: { ctx: { baseUrl: baseA } } } },
122
+ { options: { name: '@fixture/plugin' }, disabled: false, parent: { tree: { ctx: { baseUrl: baseB } } } },
123
+ { options: { name: '@deepseek-ai/core' }, disabled: false, parent: { tree: { ctx: { baseUrl: baseA } } } },
124
+ { options: { name: 'official-addon/runtime' }, disabled: false, parent: { tree: { ctx: { baseUrl: baseA } } } },
125
+ { options: { name: 'disabled-secret' }, disabled: true },
126
+ { options: { name: 'group-secret', group: true }, disabled: false },
127
+ ]
128
+ const resolutions = []
129
+ const h = harness({}, { services: {
130
+ loader: { entries: () => entries },
131
+ pluginPackages: { packageOf (name, anchor) { resolutions.push([name, anchor]); return { manifestPath: name === '@deepseek-ai/core' ? core : anchor === baseB ? otherVersion : plugin } } },
132
+ pluginManager: { listBundles: async () => [
133
+ { name: '@deepseek-ai/dsh-base', version: '0.2.2-rc.2', enabled: true, availability: 'installation', official: false, rows: [{ moduleName: '@deepseek-ai/core' }] },
134
+ { name: 'official-addon', version: '1.0.0', enabled: true, availability: 'profile', official: true, rows: [{ moduleName: 'official-addon/runtime' }] },
135
+ { name: '@deepseek-ai/third-party-fixture', version: '7.0.0', enabled: true, availability: 'profile', official: false },
136
+ { name: '@fixture/plugin', version: '1.2.3', enabled: true, source: 'DO_NOT_EXPORT_SOURCE' },
137
+ { name: '@fixture/config-preset', version: '3.4.5', enabled: true, rows: [] },
138
+ { name: 'disabled-bundle', version: '9', enabled: false },
139
+ ] },
140
+ } })
141
+ try {
142
+ const response = await reportEnvironment(h)
143
+ assert.equal(response.status, 200)
144
+ const body = await response.json()
145
+ assert.equal(body.runtime.pluginsStatus, 'complete')
146
+ assert.deepEqual(body.runtime.enabledPlugins, [
147
+ { name: '@deepseek-ai/third-party-fixture', version: '7.0.0' },
148
+ { name: '@fixture/config-preset', version: '3.4.5' },
149
+ { name: '@fixture/plugin', version: '1.2.3' },
150
+ { name: '@fixture/plugin', version: '2.0.0' },
151
+ ])
152
+ assert.ok(resolutions.some(([name, anchor]) => name === '@fixture/plugin' && anchor === baseB))
153
+ assert.equal(reads.get(plugin), 1, 'one manifest read per package path within this request')
154
+ assert.doesNotMatch(JSON.stringify(body), /DO_NOT_EXPORT|tree-a|tree-b|disabled-|group-secret|manifestPath|"config":|"source":/)
155
+ assert.ok(body.runtime.enabledPlugins.every((entry) => Object.keys(entry).sort().join(',') === 'name,version'))
156
+ } finally { await disposeHarness(h) }
157
+ })
158
+ })
159
+
160
+ test('report environment excludes native repository packages without relying on package-name prefix', async () => {
161
+ await withInventoryManifests(async ({ put }) => {
162
+ const native = await put('native-unscoped-plugin', '0.2.2-rc.2')
163
+ await fs.writeFile(native, JSON.stringify({ name: 'native-unscoped-plugin', version: '0.2.2-rc.2', repository: { url: 'git+https://github.com/deepseek-ai/deepseek-harness.git' } }))
164
+ const thirdParty = await put('@deepseek-ai/not-shipped-fixture', '9.0.0')
165
+ const h = harness({}, { services: {
166
+ loader: { entries: () => [native, thirdParty].map((path, index) => ({ disabled: false, options: { name: index ? '@deepseek-ai/not-shipped-fixture' : 'native-unscoped-plugin' } })) },
167
+ pluginPackages: { packageOf: (name) => ({ manifestPath: name === 'native-unscoped-plugin' ? native : thirdParty }) },
168
+ pluginManager: { listBundles: async () => [{ name: 'native-unscoped-plugin', version: '0.2.2-rc.2', enabled: true, availability: 'profile', official: false }] },
169
+ agentPresets: {
170
+ inspectCompositions: () => [],
171
+ compositionInventory: async () => [{ id: 'fixture', rows: [
172
+ { moduleName: 'native-unscoped-plugin', enabled: true },
173
+ { moduleName: 'native-unscoped-plugin', enabled: 'conditional' },
174
+ { moduleName: 'cordis:group', enabled: true },
175
+ { moduleName: 'not-enabled-conditional', enabled: 'conditional' },
176
+ ] }],
177
+ },
178
+ } })
179
+ try {
180
+ const body = await (await reportEnvironment(h)).json()
181
+ assert.deepEqual(body.runtime.enabledPlugins, [{ name: '@deepseek-ai/not-shipped-fixture', version: '9.0.0' }])
182
+ assert.equal(body.runtime.pluginsStatus, 'complete')
183
+ } finally { await disposeHarness(h) }
184
+ })
185
+ })
186
+
187
+ test('report environment recollects every request and rereads versions rather than caching the old roster', async () => {
188
+ await withInventoryManifests(async ({ put }) => {
189
+ const path = await put('fixture-changing', '1.0.0')
190
+ let plugins = [{ moduleName: 'fixture-changing/client', enabled: true, fiberPhase: 'failed', config: 'DO_NOT_EXPORT' }]
191
+ let bundles = [{ name: 'fixture-changing', version: '1.0.0', enabled: true }]
192
+ let pluginCalls = 0
193
+ let bundleCalls = 0
194
+ const h = harness({}, { services: {
195
+ pluginPackages: { packageOf: () => ({ manifestPath: path }) },
196
+ pluginManager: { listPlugins: async () => { pluginCalls++; return plugins }, listBundles: async () => { bundleCalls++; return bundles } },
197
+ } })
198
+ try {
199
+ const first = await (await reportEnvironment(h)).json()
200
+ assert.deepEqual(first.runtime.enabledPlugins, [{ name: 'fixture-changing', version: '1.0.0' }])
201
+ await fs.writeFile(path, JSON.stringify({ name: 'fixture-changing', version: '1.1.0' }))
202
+ bundles = [{ name: 'fixture-changing', version: '1.1.0', enabled: true }]
203
+ const second = await (await reportEnvironment(h)).json()
204
+ assert.deepEqual(second.runtime.enabledPlugins, [{ name: 'fixture-changing', version: '1.1.0' }])
205
+ plugins = [{ moduleName: 'fixture-changing', enabled: false }]
206
+ bundles = []
207
+ const third = await (await reportEnvironment(h)).json()
208
+ assert.deepEqual(third.runtime.enabledPlugins, [])
209
+ assert.equal(third.runtime.pluginsStatus, 'complete')
210
+ assert.equal(pluginCalls, 3)
211
+ assert.equal(bundleCalls, 3)
212
+ } finally { await disposeHarness(h) }
213
+ })
214
+ })
215
+
216
+ test('report environment keeps large lists complete and marks missing or invalid versions honestly', async () => {
217
+ await withInventoryManifests(async ({ put }) => {
218
+ const missingVersion = await put('fixture-no-version', undefined)
219
+ const h = harness({}, { services: {
220
+ pluginPackages: { packageOf (name) { return name === 'fixture-no-version' ? { manifestPath: missingVersion } : undefined } },
221
+ pluginManager: { listPlugins: async () => [
222
+ { moduleName: 'fixture-no-version/subpath', enabled: true }, { moduleName: 'fixture-unresolved', enabled: true },
223
+ ], listBundles: async () => [
224
+ ...Array.from({ length: 137 }, (_, index) => ({ name: 'fixture-bundle-' + index, version: '1.0.0', enabled: true })),
225
+ { name: 'fixture-bad-version', version: 'D:\\PRIVATE\\token=secret', enabled: true },
226
+ ] },
227
+ } })
228
+ try {
229
+ const body = await (await reportEnvironment(h)).json()
230
+ assert.equal(body.runtime.enabledPlugins.length, 140)
231
+ assert.equal(body.runtime.pluginsStatus, 'partial')
232
+ for (const name of ['fixture-no-version', 'fixture-unresolved', 'fixture-bad-version']) {
233
+ assert.deepEqual(body.runtime.enabledPlugins.find((entry) => entry.name === name), { name, version: null })
234
+ }
235
+ assert.doesNotMatch(JSON.stringify(body), /PRIVATE|token=|manifestPath/)
236
+ } finally { await disposeHarness(h) }
237
+ })
238
+ })
239
+
240
+ test('report environment reports unavailable or partial service inventories without leaking errors', async () => {
241
+ for (const [services, expectedStatus, expectedNames] of [
242
+ [{}, 'unavailable', []],
243
+ [{ pluginManager: { listPlugins: async () => { throw Error('PRIVATE_PATH_AND_TOKEN') }, listBundles: async () => [{ name: 'fixture-config', version: '1', enabled: true }] } }, 'partial', ['fixture-config']],
244
+ [{ loader: { entries: () => { throw Error('PRIVATE_PATH_AND_TOKEN') } } }, 'unavailable', []],
245
+ ]) {
246
+ const h = harness({}, { services })
247
+ try {
248
+ const body = await (await reportEnvironment(h)).json()
249
+ assert.equal(body.runtime.pluginsStatus, expectedStatus)
250
+ assert.deepEqual(body.runtime.enabledPlugins.map((entry) => entry.name), expectedNames)
251
+ assert.doesNotMatch(JSON.stringify(body), /PRIVATE_PATH_AND_TOKEN/)
252
+ } finally { await disposeHarness(h) }
253
+ }
254
+ })
255
+
256
+ test('report environment includes preset composition packages without exporting preset internals', async () => {
257
+ await withInventoryManifests(async ({ put }) => {
258
+ const path = await put('fixture-preset-tool', '4.5.6')
259
+ const anchor = pathToFileURL(join(tmpdir(), 'private-preset.yml')).href
260
+ const h = harness({}, { services: {
261
+ loader: { entries: () => [] },
262
+ pluginManager: { listBundles: async () => [] },
263
+ pluginPackages: { packageOf (name, base) { assert.equal(name, 'fixture-preset-tool'); assert.equal(base, anchor); return { manifestPath: path } } },
264
+ agentPresets: {
265
+ inspectCompositions: () => [{ id: 'private-preset-id', modules: [{ moduleName: 'fixture-preset-tool/tools', baseUrl: anchor, useHostBase: false }], leakedServices: ['DO_NOT_EXPORT'] }],
266
+ compositionInventory: async () => [{ id: 'private-preset-id', rows: [
267
+ { moduleName: 'fixture-preset-tool/tools', enabled: true },
268
+ { moduleName: 'fixture-failed-preset-entry', enabled: true, fiberState: 'failed' },
269
+ { moduleName: 'fixture-disabled-preset-entry', enabled: false },
270
+ { moduleName: 'fixture-conditional-preset-entry', enabled: 'conditional', condition: 'PRIVATE_CONDITION' },
271
+ ] }],
272
+ },
273
+ } })
274
+ try {
275
+ const body = await (await reportEnvironment(h)).json()
276
+ assert.equal(body.runtime.pluginsStatus, 'partial')
277
+ assert.deepEqual(body.runtime.enabledPlugins, [{ name: 'fixture-failed-preset-entry', version: null }, { name: 'fixture-preset-tool', version: '4.5.6' }])
278
+ assert.doesNotMatch(JSON.stringify(body), /private-preset|DO_NOT_EXPORT|PRIVATE_CONDITION|disabled-preset|conditional-preset|baseUrl/)
279
+ } finally { await disposeHarness(h) }
280
+ })
281
+ })
282
+
283
+ test('report environment requires authenticated owner before collecting inventory and honors cancellation', async () => {
284
+ for (const [admission, status] of [[{ rejection: 401 }, 401], [{ peer: { principal: { kind: 'guest' } } }, 403]]) {
285
+ let reads = 0
286
+ const h = harness({}, { admission, services: { pluginManager: { listPlugins () { reads++; return [] }, listBundles () { reads++; return [] } } } })
287
+ try {
288
+ const response = await reportEnvironment(h)
289
+ assert.equal(response.status, status)
290
+ assert.equal(reads, 0)
291
+ } finally { await disposeHarness(h) }
292
+ }
293
+ const controller = new AbortController()
294
+ const h = harness({}, { services: { pluginManager: { listBundles: async () => { controller.abort(); return [] }, listPlugins: async () => { assert.fail('must stop after cancellation') } } } })
295
+ try { assert.equal((await reportEnvironment(h, controller.signal)).status, 499) } finally { await disposeHarness(h) }
296
+ })
297
+
81
298
  test('diagnostic routes share cached versions from the actual launch and plugin manifests', async () => {
82
299
  const originalRead = fs.readFile
83
300
  const oldInstall = process.env.DSH_INSTALL_DIR
@@ -505,9 +722,9 @@ function runtimeHarness (h, adapter, middleware = []) {
505
722
  }
506
723
 
507
724
  async function collect (stream) { const chunks = []; for await (const chunk of stream) chunks.push(chunk); return chunks }
508
- async function compactionRecords (h) {
725
+ async function compactionRecords (h, sessionId = 'session-1') {
509
726
  const route = h.routes.find((entry) => entry.path === '/api/better-tips/compaction')
510
- return (await route.fetch(new Request('http://localhost/api/better-tips/compaction?sessionId=session-1'))).json()
727
+ return (await route.fetch(new Request(`http://localhost/api/better-tips/compaction?sessionId=${encodeURIComponent(sessionId)}`))).json()
511
728
  }
512
729
 
513
730
  test('compaction retries re-dispatch every attempt through two downstream middleware layers', async () => {
@@ -527,6 +744,8 @@ test('compaction retries re-dispatch every attempt through two downstream middle
527
744
  assert.equal(record.attempts.length, 2)
528
745
  assert.equal(record.delays.length, 1)
529
746
  assert.equal(record.attempts[0].failure.code, 'SERVER')
747
+ assert.equal(record.attempts[0].finishReason, 'error')
748
+ assert.equal(record.attempts[1].finishReason, 'stop')
530
749
  assert.equal(record.attempts[0].failure.status, 502)
531
750
  assert.ok(Number.isFinite(record.durationMs))
532
751
  await disposeHarness(h)
@@ -658,6 +877,137 @@ test('compaction capture is bound at failure and cannot change after unrelated l
658
877
  } finally { await disposeHarness(h); globalThis.fetch = originalFetch }
659
878
  })
660
879
 
880
+ test('compaction HTTP and network failures retain scoped capture when iterator throws the original error', async () => {
881
+ const originalFetch = globalThis.fetch
882
+ try {
883
+ for (const kind of ['response', 'network']) {
884
+ const networkError = Object.assign(new Error('synthetic socket failed'), { code: 'ECONNRESET' })
885
+ const thrown = kind === 'network' ? networkError : Object.assign(new Error('adapter failed after HTTP response'), { code: 'STREAM_CLOSED' })
886
+ globalThis.fetch = async () => {
887
+ if (kind === 'network') throw networkError
888
+ return new Response('synthetic upstream body', { status: 502, headers: { 'x-request-id': 'throw-http-request' } })
889
+ }
890
+ const h = harness({ captureDetails: true, compactionRetries: 3, initialDelayMs: 0 })
891
+ try {
892
+ const { runtime, stats } = runtimeHarness(h, () => (async function * () {
893
+ const response = await fetch(`https://${kind}.example/v1/chat`)
894
+ await response.text()
895
+ throw thrown
896
+ })())
897
+ await assert.rejects(collect(runtime.stream({ ...COMPACTION_OPTIONS })), error => error === thrown)
898
+ const body = await compactionRecords(h)
899
+ const record = body.records[0]
900
+ const attempt = record.attempts[0]
901
+ assert.equal(record.status, 'thrown')
902
+ assert.equal(record.attempts.length, 1)
903
+ assert.equal(stats.adapterCalls, 1, 'throw handling does not introduce retries')
904
+ assert.equal(body.capture.records, 1)
905
+ assert.equal(attempt.provenance, 'request-context')
906
+ assert.ok(attempt.attemptId)
907
+ assert.equal(attempt.detail.context.attemptId, attempt.attemptId)
908
+ assert.equal(attempt.detail.context.sessionId, COMPACTION_OPTIONS.sessionId)
909
+ assert.equal(attempt.detail.host, `${kind}.example`)
910
+ assert.equal(attempt.thrown.message, thrown.message)
911
+ if (kind === 'response') {
912
+ assert.equal(attempt.detail.status, 502)
913
+ assert.equal(attempt.detail.headers['x-request-id'], 'throw-http-request')
914
+ } else assert.equal(attempt.detail.error.code, 'ECONNRESET')
915
+ } finally { await disposeHarness(h) }
916
+ }
917
+ } finally { globalThis.fetch = originalFetch }
918
+ })
919
+
920
+ test('synchronous compaction dispatch throws retain identity without borrowing an earlier capture', async () => {
921
+ const originalFetch = globalThis.fetch
922
+ globalThis.fetch = async () => new Response('old capture', { status: 502 })
923
+ const h = harness({ captureDetails: true, compactionRetries: 3 })
924
+ try {
925
+ await fetch('https://unrelated.example/v1/chat')
926
+ const thrown = new Error('synchronous adapter refused dispatch')
927
+ const { runtime, stats } = runtimeHarness(h, () => { throw thrown })
928
+ await assert.rejects(collect(runtime.stream({ ...COMPACTION_OPTIONS })), error => error === thrown)
929
+ const body = await compactionRecords(h)
930
+ const attempt = body.records[0].attempts[0]
931
+ assert.equal(stats.adapterCalls, 1)
932
+ assert.equal(body.capture.records, 1)
933
+ assert.equal(body.records[0].status, 'thrown')
934
+ assert.ok(attempt.attemptId, 'identity is assigned before the dispatch can throw')
935
+ assert.equal(attempt.provenance, 'request-context')
936
+ assert.equal(attempt.detail, undefined)
937
+ assert.equal(attempt.finishReason, undefined)
938
+ assert.equal(attempt.thrown.message, thrown.message)
939
+ } finally { await disposeHarness(h); globalThis.fetch = originalFetch }
940
+ })
941
+
942
+ test('concurrent thrown compactions keep evidence inside their own session and attempt', async () => {
943
+ const originalFetch = globalThis.fetch
944
+ globalThis.fetch = async (url) => new Response(String(url), { status: 502 })
945
+ const h = harness({ captureDetails: true, compactionRetries: 0 })
946
+ try {
947
+ const waiting = new Map()
948
+ const errors = { 'session-A': new Error('throw A'), 'session-B': new Error('throw B') }
949
+ const { runtime } = runtimeHarness(h, (options) => (async function * () {
950
+ await fetch(`https://${options.sessionId.toLowerCase()}.example/v1/chat`)
951
+ await new Promise(resolve => waiting.set(options.sessionId, resolve))
952
+ throw errors[options.sessionId]
953
+ })())
954
+ const rejected = Object.fromEntries(Object.keys(errors).map(sessionId => [sessionId,
955
+ assert.rejects(collect(runtime.stream({ ...COMPACTION_OPTIONS, sessionId })), error => error === errors[sessionId])]))
956
+ for (let pass = 0; pass < 50 && waiting.size < 2; pass++) await new Promise(resolve => setImmediate(resolve))
957
+ assert.equal(waiting.size, 2)
958
+ waiting.get('session-B')()
959
+ await rejected['session-B']
960
+ waiting.get('session-A')()
961
+ await rejected['session-A']
962
+ const a = (await compactionRecords(h, 'session-A')).records[0].attempts[0]
963
+ const b = (await compactionRecords(h, 'session-B')).records[0].attempts[0]
964
+ assert.notEqual(a.attemptId, b.attemptId)
965
+ for (const [attempt, sessionId] of [[a, 'session-A'], [b, 'session-B']]) {
966
+ assert.equal(attempt.detail.context.sessionId, sessionId)
967
+ assert.equal(attempt.detail.context.attemptId, attempt.attemptId)
968
+ assert.equal(attempt.detail.host, `${sessionId.toLowerCase()}.example`)
969
+ }
970
+ } finally { await disposeHarness(h); globalThis.fetch = originalFetch }
971
+ })
972
+
973
+ test('caller cancellation during compaction preserves original thrown identity and starts no retry', async () => {
974
+ const originalFetch = globalThis.fetch
975
+ globalThis.fetch = async () => new Response('failed before cancellation', { status: 502 })
976
+ const h = harness({ captureDetails: true, compactionRetries: 3 })
977
+ const caller = new AbortController()
978
+ const abort = Object.assign(new Error('caller cancelled inside adapter'), { code: 'ABORTED' })
979
+ try {
980
+ const { runtime, stats } = runtimeHarness(h, () => (async function * () {
981
+ await fetch('https://cancelled.example/v1/chat')
982
+ caller.abort(abort)
983
+ throw abort
984
+ })())
985
+ await assert.rejects(collect(runtime.stream({ ...COMPACTION_OPTIONS, signal: caller.signal })), error => error === abort)
986
+ const record = (await compactionRecords(h)).records[0]
987
+ assert.equal(record.status, 'aborted')
988
+ assert.equal(record.attempts[0].thrown.code, 'ABORTED')
989
+ assert.equal(record.attempts[0].detail.host, 'cancelled.example')
990
+ assert.equal(stats.adapterCalls, 1)
991
+ } finally { await disposeHarness(h); globalThis.fetch = originalFetch }
992
+ })
993
+
994
+ test('compaction terminal finish kind is exposed and max-tokens is never recorded as ok', async () => {
995
+ const h = harness({ compactionRetries: 3 })
996
+ try {
997
+ for (const [kind, expected] of [['stop', 'ok'], ['tool-calls', 'ok'], ['max-tokens', 'max-tokens'], ['aborted', 'aborted'], ['unexpected-kind', 'incomplete']]) {
998
+ const chunks = [{ type: 'finish', reason: { kind } }]
999
+ const { runtime, stats } = runtimeHarness(h, () => streamOf(chunks))
1000
+ assert.deepEqual(await collect(runtime.stream({ ...COMPACTION_OPTIONS })), chunks)
1001
+ const record = (await compactionRecords(h)).records.at(-1)
1002
+ assert.equal(record.status, expected, kind)
1003
+ assert.equal(record.attempts[0].finishReason, kind)
1004
+ assert.ok(record.attempts[0].attemptId)
1005
+ assert.equal(record.attempts[0].detail, undefined)
1006
+ assert.equal(stats.adapterCalls, 1, 'terminal-state recording does not change retry policy')
1007
+ }
1008
+ } finally { await disposeHarness(h) }
1009
+ })
1010
+
661
1011
  test('successful compaction attempts never inherit a neighboring failure capture', async () => {
662
1012
  const originalFetch = globalThis.fetch
663
1013
  globalThis.fetch = async () => new Response('', { status: 502 })
@@ -853,6 +1203,70 @@ test('AUTH compaction route suppresses credential echoes in both failure and cor
853
1203
  } finally { await disposeHarness(h); globalThis.fetch = originalFetch }
854
1204
  })
855
1205
 
1206
+ test('AUTH thrown compactions protect arbitrary text and body through cause and aggregate errors', async () => {
1207
+ const originalFetch = globalThis.fetch
1208
+ const unrecognized = 'arbitraryVendorCredentialWithoutKnownShape'
1209
+ try {
1210
+ for (const wrapped of ['direct', 'cause', 'aggregate']) {
1211
+ globalThis.fetch = async () => new Response(`${unrecognized} ${PRIVATE_KEY} ${PRIVATE_BEARER}`, {
1212
+ status: 401, statusText: unrecognized, headers: { 'x-request-id': 'auth-throw-request', 'cf-ray': PRIVATE_KEY },
1213
+ })
1214
+ const auth = Object.assign(new Error(unrecognized), { code: 'AUTH', errno: unrecognized })
1215
+ const thrown = wrapped === 'cause' ? Object.assign(new Error(unrecognized), { code: 'WRAPPER', cause: auth })
1216
+ : wrapped === 'aggregate' ? new AggregateError([new Error('unrelated'), new AggregateError([auth], unrecognized)], unrecognized) : auth
1217
+ if (wrapped === 'aggregate') thrown.errors.unshift(thrown)
1218
+ const h = harness({ captureDetails: true, compactionRetries: 0 })
1219
+ try {
1220
+ const { runtime } = runtimeHarness(h, () => (async function * () {
1221
+ await (await fetch('https://auth-throw.example/v1/chat')).text()
1222
+ throw thrown
1223
+ })())
1224
+ await assert.rejects(collect(runtime.stream({ ...COMPACTION_OPTIONS })), error => error === thrown)
1225
+ const body = await compactionRecords(h)
1226
+ assertNoCredential(body)
1227
+ assert.equal(JSON.stringify(body).includes(unrecognized), false)
1228
+ const attempt = body.records[0].attempts[0]
1229
+ assert.deepEqual(attempt.thrown, { code: 'AUTH', message: '', protected: true })
1230
+ assert.ok(attempt.attemptId)
1231
+ assert.equal(attempt.detail.context.attemptId, attempt.attemptId)
1232
+ assert.equal(attempt.detail.status, 401)
1233
+ assert.equal(attempt.detail.headers['x-request-id'], 'auth-throw-request')
1234
+ assert.equal(attempt.detail.statusText, undefined)
1235
+ assert.equal(attempt.detail.body, undefined)
1236
+ assert.equal(attempt.detail.error, undefined)
1237
+ assert.equal(attempt.detail.bodyReason, 'credential-protection')
1238
+ assert.equal(attempt.detail.protected, true)
1239
+ assert.equal(thrown.message, unrecognized, 'original thrown value is untouched')
1240
+ } finally { await disposeHarness(h) }
1241
+ }
1242
+ } finally { globalThis.fetch = originalFetch }
1243
+ })
1244
+
1245
+ test('thrown compaction network detail redacts nested credentials without changing the source error', async () => {
1246
+ const originalFetch = globalThis.fetch
1247
+ const thrown = Object.assign(new Error(`network ${PRIVATE_KEY}`), {
1248
+ code: 'ECONNRESET', errno: PRIVATE_KEY, syscall: PRIVATE_BEARER, address: PRIVATE_KEY,
1249
+ cause: Object.assign(new Error(PRIVATE_BEARER), { code: `ERR_${PRIVATE_KEY}` }),
1250
+ })
1251
+ globalThis.fetch = async () => { throw thrown }
1252
+ const h = harness({ captureDetails: true, compactionRetries: 0 })
1253
+ try {
1254
+ const { runtime } = runtimeHarness(h, () => (async function * () { await fetch('https://nested-throw.example/v1/chat') })())
1255
+ await assert.rejects(collect(runtime.stream({ ...COMPACTION_OPTIONS })), error => error === thrown)
1256
+ const body = await compactionRecords(h)
1257
+ assertNoCredential(body)
1258
+ const attempt = body.records[0].attempts[0]
1259
+ assert.equal(attempt.detail.error.errno, 'sk-[redacted]')
1260
+ assert.equal(attempt.detail.error.syscall, 'Bearer [redacted]')
1261
+ assert.equal(attempt.detail.error.address, 'sk-[redacted]')
1262
+ assert.equal(attempt.detail.error.cause.message, 'Bearer [redacted]')
1263
+ assert.equal(attempt.detail.error.cause.code, 'ERR_sk-[redacted]')
1264
+ assert.equal(attempt.thrown.errno, 'sk-[redacted]')
1265
+ assert.equal(thrown.errno, PRIVATE_KEY)
1266
+ assert.equal(thrown.cause.message, PRIVATE_BEARER)
1267
+ } finally { await disposeHarness(h); globalThis.fetch = originalFetch }
1268
+ })
1269
+
856
1270
  test('metadata error responses redact native exception text and never export AUTH durable event text', async () => {
857
1271
  const failure = Object.freeze({ code: 'AUTH', message: `unrecognized-provider-credential ${PRIVATE_KEY} ${PRIVATE_BEARER}` })
858
1272
  const event = Object.freeze({ seq: 7, type: 'llm/retry', data: Object.freeze({ failure }) })