dsh-bailinghub 0.6.0 → 0.7.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.
@@ -0,0 +1,82 @@
1
+ const envelope = value => value?.schema === 'bailing.provider-response.v1'
2
+ const failure = code => Object.assign(new Error(`Model response unavailable (${code}).`), { code })
3
+
4
+ /** Feed a local provider adapter without replacing global fetch. The receipt pump is independent
5
+ * of the body reader: adapters may stop at [DONE], but original-result persistence must finish.
6
+ */
7
+ export async function* usageNativeModelChunks(events, consumeResponse) {
8
+ let openResponse, failResponse, resolveReceipt, rejectReceipt, controller, cancelled = false
9
+ let header, body = '', bytes = 0, ended = false
10
+ const responseReady = new Promise((resolve, reject) => { openResponse = resolve; failResponse = reject })
11
+ const receiptReady = new Promise((resolve, reject) => { resolveReceipt = resolve; rejectReceipt = reject })
12
+ // The pump can reject before either consumer reaches its await.
13
+ responseReady.catch(() => {}); receiptReady.catch(() => {})
14
+ const encoder = new TextEncoder()
15
+ function open(value) {
16
+ if (!envelope(value) || !['sse', 'json'].includes(value.format)
17
+ || !Number.isInteger(value.status) || value.status < 200 || value.status > 599
18
+ || value.content_type !== (value.format === 'sse' ? 'text/event-stream' : 'application/json')) throw failure('USAGE_STREAM_INCOMPLETE')
19
+ if (header) {
20
+ if (['format', 'status', 'content_type'].some(key => header[key] !== value[key])) throw failure('USAGE_STREAM_INCOMPLETE')
21
+ return
22
+ }
23
+ header = value
24
+ const stream = new ReadableStream({ start(value) { controller = value }, cancel() { cancelled = true } })
25
+ // Fetch forbids a body for these status codes. The saved body remains available to the receipt check.
26
+ openResponse(new Response([204, 205, 304].includes(value.status) ? null : stream,
27
+ { status: value.status, headers: { 'content-type': value.content_type } }))
28
+ }
29
+ function append(text) {
30
+ if (typeof text !== 'string') throw failure('USAGE_STREAM_INCOMPLETE')
31
+ const chunk = encoder.encode(text); bytes += chunk.byteLength
32
+ if (bytes > 4 * 1024 * 1024) throw failure('USAGE_PROVIDER_RESPONSE_TOO_LARGE')
33
+ body += text
34
+ if (!cancelled) controller.enqueue(chunk)
35
+ }
36
+ const pump = (async () => {
37
+ try {
38
+ for await (const event of events) {
39
+ if (ended) throw failure('USAGE_STREAM_INCOMPLETE')
40
+ if (event.type === 'provider') { open(event.provider); append(event.provider.data) }
41
+ if (event.type !== 'operation') continue
42
+ const receipt = event.operation, saved = receipt?.response
43
+ if (receipt?.result_state === 'failed' && receipt.delivery_state !== 'cancelled_late_result') throw Object.assign(new Error(receipt.error?.message ?? 'Model service rejected the request.'), {code: 'USAGE_PROVIDER_REJECTED', operationId: receipt.operation_id, feedback: {schema:'bailing.usage-feedback.v1',code:'USAGE_PROVIDER_REJECTED',dispatch:'rejected',next_action:'contact_operator',retryable:false}})
44
+ if (receipt?.delivery_state !== 'response_ready' || receipt.host_turn_active !== true) throw failure(
45
+ receipt?.delivery_state === 'cancelled_late_result' ? 'USAGE_CANCELLED' : 'USAGE_ORIGINAL_PENDING')
46
+ const hadPreview = Boolean(header)
47
+ open(saved)
48
+ if (typeof saved.body !== 'string') throw failure('USAGE_STREAM_INCOMPLETE')
49
+ if (!hadPreview) append(saved.body) // Recovery reads the recorded body once, never reissues a request.
50
+ if (body !== saved.body) throw failure('USAGE_STREAM_INCOMPLETE')
51
+ ended = true
52
+ if (!cancelled) controller.close()
53
+ resolveReceipt(receipt)
54
+ }
55
+ if (!ended) throw failure('USAGE_STREAM_INCOMPLETE')
56
+ } catch (error) {
57
+ if (controller && !cancelled) { try { controller.error(error) } catch {} }
58
+ failResponse(error); rejectReceipt(error)
59
+ throw error
60
+ }
61
+ })()
62
+ pump.catch(() => {})
63
+ try {
64
+ const response = await responseReady
65
+ for await (const chunk of consumeResponse(response)) {
66
+ // No executable tool block or terminal marker before the original receipt is durable locally.
67
+ if (chunk.type === 'finish' || chunk.type === 'tool-call-delta'
68
+ || (chunk.type === 'block-start' && chunk.blockType === 'tool-call')
69
+ || (chunk.type === 'block-end' && chunk.block?.type === 'tool-call')) await receiptReady
70
+ yield chunk
71
+ }
72
+ // Some native parsers return without a finish marker; AgentLoop must still not advance early.
73
+ await receiptReady
74
+ await pump
75
+ } finally {
76
+ // Drain the original operation even when a parser throws, returns early or cancels its reader.
77
+ // No retry/model call is performed by this adapter.
78
+ cancelled = true
79
+ // A late local persistence/identity failure keeps priority over a parser error.
80
+ await pump
81
+ }
82
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-bailinghub",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Let a local DeepSeek Harness Agent use BailingHub to query data, update records, and run permitted actions in your online store, SaaS, or other admin system.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -58,7 +58,12 @@
58
58
  "docs/RELEASE_NOTES_v0.6.0.md",
59
59
  "docs/UPGRADE_v0.6.0.md",
60
60
  "docs/RELEASE_NOTES_v0.6.0.en.md",
61
- "docs/UPGRADE_v0.6.0.en.md"
61
+ "docs/UPGRADE_v0.6.0.en.md",
62
+ "docs/USAGE_SERVICE.md",
63
+ "docs/RELEASE_NOTES_v0.7.0.md",
64
+ "docs/RELEASE_NOTES_v0.7.0.en.md",
65
+ "docs/UPGRADE_v0.7.0.md",
66
+ "docs/UPGRADE_v0.7.0.en.md"
62
67
  ],
63
68
  "engines": {
64
69
  "node": "^22.19.0 || >=24.0.0"
@@ -73,10 +78,11 @@
73
78
  },
74
79
  "dependencies": {
75
80
  "@deepseek-ai/schemastery": "^3.18.1",
76
- "bailinghub-mcp-server": "0.6.0"
81
+ "bailinghub-mcp-server": "0.7.0"
77
82
  },
78
83
  "devDependencies": {
79
84
  "@deepseek-ai/cordis": "4.0.1",
85
+ "@deepseek-ai/dsh-agent-loop": "0.1.1-rc.2",
80
86
  "@deepseek-ai/dsh-commands": "0.1.1-rc.2",
81
87
  "@deepseek-ai/dsh-scope": "0.1.1-rc.2",
82
88
  "@deepseek-ai/dsh-system-prompt": "0.1.1-rc.2",