dsh-bettertaskgraphs 0.3.1-rc.34 → 0.3.1-rc.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DSH-COMPATIBILITY.json +7 -8
- package/README.md +5 -5
- package/VALIDATION.md +1 -1
- package/client.js +8 -11
- package/client.source.mjs +5 -6
- package/index.mjs +5 -9
- package/package.json +10 -10
- package/projection.mjs +8 -1
- package/remote.mjs +2 -4
package/DSH-COMPATIBILITY.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
3
|
"updateRound": 3,
|
|
4
|
-
"slot":
|
|
5
|
-
"branch": "0.2.1-alpha.
|
|
6
|
-
"host": "0.2.1-alpha.
|
|
4
|
+
"slot": 5,
|
|
5
|
+
"branch": "0.2.1-alpha.2",
|
|
6
|
+
"host": "0.2.1-alpha.2",
|
|
7
7
|
"hosts": [
|
|
8
|
-
"0.2.1-alpha.
|
|
9
|
-
"0.2.1-alpha.3"
|
|
8
|
+
"0.2.1-alpha.2"
|
|
10
9
|
],
|
|
11
|
-
"channel": "dsh-0.2.1-alpha.
|
|
12
|
-
"taskgraph": "0.3.1-rc.
|
|
13
|
-
"dynamicContext": "0.1.1-rc.
|
|
10
|
+
"channel": "dsh-0.2.1-alpha.2",
|
|
11
|
+
"taskgraph": "0.3.1-rc.35",
|
|
12
|
+
"dynamicContext": "0.1.1-rc.35"
|
|
14
13
|
}
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-bettertaskgraphs
|
|
2
2
|
|
|
3
|
-
本构建版本为 `0.3.1-rc.
|
|
3
|
+
本构建版本为 `0.3.1-rc.35`。适用宿主和配套版本见 [兼容清单](DSH-COMPATIBILITY.json)。
|
|
4
4
|
|
|
5
5
|
独立运行保留动态上下文开发前 `0.2.3` 的五个工具、初始指引与事务语义;通用扩展接口供其他插件登记工作流和会话策略。动态上下文装配、修改审批及其提示词由扩展插件实现。
|
|
6
6
|
|
|
@@ -12,9 +12,9 @@ DeepSeek Harness 的事务型任务图 Bundle,包含模型侧的任务图工
|
|
|
12
12
|
|
|
13
13
|
## 兼容范围
|
|
14
14
|
|
|
15
|
-
分支 `0.2.1-alpha.
|
|
15
|
+
分支 `0.2.1-alpha.2` 采用 npm 标签 `dsh-0.2.1-alpha.2`。配套动态上下文版本为 `0.1.1-rc.35`。
|
|
16
16
|
|
|
17
|
-
- DSH `0.2.1-alpha.
|
|
17
|
+
- DSH `0.2.1-alpha.2`,使用 Web profile。
|
|
18
18
|
- Node.js `^22.19.0 || >=24.0.0`,开发用 npm。此包与 DSH 共享会话、工具和远程调用接口,升级 DSH 时需要重新验证这些接口。
|
|
19
19
|
|
|
20
20
|
## 构建和打包
|
|
@@ -26,7 +26,7 @@ npm test
|
|
|
26
26
|
npm run pack:bundle
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
`build` 从前端源码生成可由 DSH Web 加载的 `client.js`。`check` 校验生成物与源码一致,`pack:bundle` 会重新构建前端并生成 `dist/dsh-bettertaskgraphs-0.3.1-rc.
|
|
29
|
+
`build` 从前端源码生成可由 DSH Web 加载的 `client.js`。`check` 校验生成物与源码一致,`pack:bundle` 会重新构建前端并生成 `dist/dsh-bettertaskgraphs-0.3.1-rc.35.tgz`。包内包含服务端模块、Web 构建产物、对应源码和构建脚本,以及 Bundle 配置补丁。
|
|
30
30
|
|
|
31
31
|
## 安装到独立 Web profile
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ npm run pack:bundle
|
|
|
34
34
|
|
|
35
35
|
```sh
|
|
36
36
|
dsh --profile bettertaskgraphs --from-default-profile web --dump-config
|
|
37
|
-
dsh plugin --profile bettertaskgraphs add "$PWD/dist/dsh-bettertaskgraphs-0.3.1-rc.
|
|
37
|
+
dsh plugin --profile bettertaskgraphs add "$PWD/dist/dsh-bettertaskgraphs-0.3.1-rc.35.tgz"
|
|
38
38
|
dsh --profile bettertaskgraphs --dump-config
|
|
39
39
|
dsh --profile bettertaskgraphs
|
|
40
40
|
```
|
package/VALIDATION.md
CHANGED
package/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
// Corresponding source: https://github.com/oldcitynight/dsh-bettertaskgraphs/tree/v0.3.1-rc.
|
|
2
|
+
// Corresponding source: https://github.com/oldcitynight/dsh-bettertaskgraphs/tree/v0.3.1-rc.35
|
|
3
3
|
// Generated by scripts/build-client.mjs.
|
|
4
4
|
window.__ModuleLoader__.load({id:"dsh-bettertaskgraphs",factory(require){
|
|
5
5
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
@@ -7,7 +7,6 @@ window.__ModuleLoader__.load({id:"dsh-bettertaskgraphs",factory(require){
|
|
|
7
7
|
function createRemoteContribution(z) {
|
|
8
8
|
const packageName = 'dsh-bettertaskgraphs'
|
|
9
9
|
const id = z.string().min(1).max(128)
|
|
10
|
-
const input = z.object({ sessionId: id }).strict()
|
|
11
10
|
const node = z.object({
|
|
12
11
|
id, label: z.string().min(1).max(512), kind: z.enum(['container', 'leaf']),
|
|
13
12
|
parent: id.nullable(),
|
|
@@ -44,9 +43,8 @@ function createRemoteContribution(z) {
|
|
|
44
43
|
id: `${packageName}#transactionGraphView/status`,
|
|
45
44
|
service: 'transactionGraph', namespace: 'transactionGraphView', method: 'status', invocation: { kind: 'direct' },
|
|
46
45
|
parameters: [{
|
|
47
|
-
name: '
|
|
48
|
-
codec:
|
|
49
|
-
strictCodec: codec('TransactionGraphStatusStrictRequest', input),
|
|
46
|
+
name: 'session', wire: 'sessionId', source: 'lookup', lookup: 'session',
|
|
47
|
+
codec: { mode: 'strict', typeSymbol: '@deepseek-ai/dsh-session/types#SessionId', create: () => id },
|
|
50
48
|
}],
|
|
51
49
|
cancellation: { parameter: 'signal' },
|
|
52
50
|
result: codec('TransactionGraphStatusResult', output),
|
|
@@ -477,15 +475,14 @@ function createClientPlugin(React, z, createRemoteContribution, graphPresentatio
|
|
|
477
475
|
}
|
|
478
476
|
|
|
479
477
|
function makeDock(api) {
|
|
480
|
-
return function TransactionGraphDock({ sessionId, useSession,
|
|
481
|
-
const canRead = useAccess('transactionGraphView/status')
|
|
478
|
+
return function TransactionGraphDock({ sessionId, useSession, t }) {
|
|
482
479
|
const opened = useSession(session => session.openState === 'open' && !session.removed)
|
|
483
480
|
const running = useSession(session => session.running)
|
|
484
481
|
const [result, setResult] = useState(null)
|
|
485
482
|
const [refreshCount, requestRefresh] = useState(0)
|
|
486
483
|
const refresh = () => requestRefresh(value => value + 1)
|
|
487
484
|
useEffect(() => {
|
|
488
|
-
if (!
|
|
485
|
+
if (!opened) return
|
|
489
486
|
const controller = new AbortController()
|
|
490
487
|
let timer
|
|
491
488
|
async function refreshStatus() {
|
|
@@ -495,7 +492,7 @@ function createClientPlugin(React, z, createRemoteContribution, graphPresentatio
|
|
|
495
492
|
busy: true, failed: value?.sessionId === sessionId && value.failed,
|
|
496
493
|
}))
|
|
497
494
|
try {
|
|
498
|
-
const response = await api.status(
|
|
495
|
+
const response = await api.status(sessionId, signal)
|
|
499
496
|
if (controller.signal.aborted) return
|
|
500
497
|
const parsed = response?.ok ? statusResult.safeParse(response.value) : null
|
|
501
498
|
if (!parsed?.success || parsed.data.sessionId !== sessionId || parsed.data.status === 'unavailable') throw new Error('Unavailable')
|
|
@@ -509,8 +506,8 @@ function createClientPlugin(React, z, createRemoteContribution, graphPresentatio
|
|
|
509
506
|
}
|
|
510
507
|
void refreshStatus()
|
|
511
508
|
return () => { controller.abort(); clearTimeout(timer) }
|
|
512
|
-
}, [
|
|
513
|
-
if (!
|
|
509
|
+
}, [opened, running, sessionId, refreshCount])
|
|
510
|
+
if (!opened || result?.sessionId !== sessionId || !result.graph) return null
|
|
514
511
|
return h(GraphPanel, { key: sessionId, graph: result.graph, t, busy: result.busy, failed: result.failed, refresh })
|
|
515
512
|
}
|
|
516
513
|
}
|
package/client.source.mjs
CHANGED
|
@@ -263,15 +263,14 @@ export function createClientPlugin(React, z, createRemoteContribution, graphPres
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
function makeDock(api) {
|
|
266
|
-
return function TransactionGraphDock({ sessionId, useSession,
|
|
267
|
-
const canRead = useAccess('transactionGraphView/status')
|
|
266
|
+
return function TransactionGraphDock({ sessionId, useSession, t }) {
|
|
268
267
|
const opened = useSession(session => session.openState === 'open' && !session.removed)
|
|
269
268
|
const running = useSession(session => session.running)
|
|
270
269
|
const [result, setResult] = useState(null)
|
|
271
270
|
const [refreshCount, requestRefresh] = useState(0)
|
|
272
271
|
const refresh = () => requestRefresh(value => value + 1)
|
|
273
272
|
useEffect(() => {
|
|
274
|
-
if (!
|
|
273
|
+
if (!opened) return
|
|
275
274
|
const controller = new AbortController()
|
|
276
275
|
let timer
|
|
277
276
|
async function refreshStatus() {
|
|
@@ -281,7 +280,7 @@ export function createClientPlugin(React, z, createRemoteContribution, graphPres
|
|
|
281
280
|
busy: true, failed: value?.sessionId === sessionId && value.failed,
|
|
282
281
|
}))
|
|
283
282
|
try {
|
|
284
|
-
const response = await api.status(
|
|
283
|
+
const response = await api.status(sessionId, signal)
|
|
285
284
|
if (controller.signal.aborted) return
|
|
286
285
|
const parsed = response?.ok ? statusResult.safeParse(response.value) : null
|
|
287
286
|
if (!parsed?.success || parsed.data.sessionId !== sessionId || parsed.data.status === 'unavailable') throw new Error('Unavailable')
|
|
@@ -295,8 +294,8 @@ export function createClientPlugin(React, z, createRemoteContribution, graphPres
|
|
|
295
294
|
}
|
|
296
295
|
void refreshStatus()
|
|
297
296
|
return () => { controller.abort(); clearTimeout(timer) }
|
|
298
|
-
}, [
|
|
299
|
-
if (!
|
|
297
|
+
}, [opened, running, sessionId, refreshCount])
|
|
298
|
+
if (!opened || result?.sessionId !== sessionId || !result.graph) return null
|
|
300
299
|
return h(GraphPanel, { key: sessionId, graph: result.graph, t, busy: result.busy, failed: result.failed, refresh })
|
|
301
300
|
}
|
|
302
301
|
}
|
package/index.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import { FileGraphStore } from './store.mjs'
|
|
|
13
13
|
|
|
14
14
|
export const name = 'dsh-bettertaskgraphs'
|
|
15
15
|
let bindSessionResource
|
|
16
|
-
Remote(
|
|
16
|
+
Remote('status')(undefined, {
|
|
17
17
|
kind: 'method', name: 'status', addInitializer: callback => { bindSessionResource = callback },
|
|
18
18
|
})
|
|
19
19
|
const guidance = 'For work the user asks to track in a transaction graph, read the program-generated revision and choices before creating or resuming it. One leaf may be active. Begin must commit before work starts. Pending or UNKNOWN work blocks finish and dependent work. Never replay blindly. Complete requires a qualified successful tool result after begin. Incomplete requires known failure, confirmed non-execution, or an unsatisfied outcome. Wait for the enclosing tool call to finish and read the committed state before continuing. Containers aggregate. Transaction completion does not complete Goal.'
|
|
@@ -43,7 +43,7 @@ export default class TransactionGraphPlugin extends TypertRemoteService {
|
|
|
43
43
|
text: ({ agent }) => this.host.inProject(agent?.session) && this.sessionPolicies.allowClassic(agent) ? this.host.context(agent) : '' })
|
|
44
44
|
ctx.inject(['typert', 'sessionController'], remoteCtx => {
|
|
45
45
|
const typert = remoteCtx.typert
|
|
46
|
-
if (typert.
|
|
46
|
+
if (typert.lookups.get('session')?.wire !== 'sessionId') throw new Error('Transaction graph requires the native Session RPC lookup')
|
|
47
47
|
const contribution = createRemoteContribution(z)
|
|
48
48
|
remoteCtx.effect(() => typert.register({ package: contribution.package, face: 'host', schemas: [],
|
|
49
49
|
model: { services: [], events: [], objects: [] }, invocations: contribution.descriptors }))
|
|
@@ -64,14 +64,10 @@ export default class TransactionGraphPlugin extends TypertRemoteService {
|
|
|
64
64
|
})
|
|
65
65
|
ctx.effect(() => () => { this.workflows.close(); this.sessionPolicies.close(); return this.host.close() })
|
|
66
66
|
}
|
|
67
|
-
async status(
|
|
67
|
+
async status(session, signal) {
|
|
68
68
|
signal?.throwIfAborted()
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const result = await controller.resolveAgent(sessionId)
|
|
72
|
-
if (result.error) throw result.error
|
|
73
|
-
signal?.throwIfAborted()
|
|
74
|
-
return this.host.snapshot(result.agent.session)
|
|
69
|
+
if (!this.host.inProject(session)) throw new RemoteError('session/not-found', 'Session unavailable')
|
|
70
|
+
return this.host.snapshot(session)
|
|
75
71
|
}
|
|
76
72
|
registerRecoveryVerifier(adapter) { return this.host.registerRecoveryVerifier(adapter) }
|
|
77
73
|
recoverInterrupted(agent, request) { return this.host.recoverInterrupted(agent, request) }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-bettertaskgraphs",
|
|
3
|
-
"version": "0.3.1-rc.
|
|
3
|
+
"version": "0.3.1-rc.35",
|
|
4
4
|
"description": "Transactional task graphs with a conversation panel for DeepSeek Harness",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"keywords": [
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
],
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": "^22.19.0 || >=24.0.0",
|
|
53
|
-
"dsh": "0.2.1-alpha.
|
|
53
|
+
"dsh": "0.2.1-alpha.2"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "node scripts/build-client.mjs",
|
|
@@ -62,23 +62,23 @@
|
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public",
|
|
65
|
-
"tag": "dsh-0.2.1-alpha.
|
|
65
|
+
"tag": "dsh-0.2.1-alpha.2",
|
|
66
66
|
"registry": "https://registry.npmjs.org/"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"zod": "4.6.7"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
|
-
"@deepseek-ai/dsh-session": "0.2.1-alpha.
|
|
73
|
-
"@deepseek-ai/dsh-tools": "0.2.1-alpha.
|
|
74
|
-
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.
|
|
72
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
73
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
|
|
74
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.2"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@deepseek-ai/cordis": "4.0.5",
|
|
78
|
-
"@deepseek-ai/dsh-session": "0.2.1-alpha.
|
|
79
|
-
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.
|
|
80
|
-
"@deepseek-ai/dsh-tools": "0.2.1-alpha.
|
|
81
|
-
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.
|
|
78
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
79
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
|
|
80
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
|
|
81
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.2"
|
|
82
82
|
},
|
|
83
83
|
"dsh": {
|
|
84
84
|
"bundle": {
|
package/projection.mjs
CHANGED
|
@@ -59,7 +59,14 @@ export function outcomeOfContent(content = []) {
|
|
|
59
59
|
}
|
|
60
60
|
function toolOutcome(state, tool, rootCallId, callId, content) {
|
|
61
61
|
const outcome = outcomeOfContent(content)
|
|
62
|
-
if (tool !== 'bash'
|
|
62
|
+
if (tool !== 'bash') return outcome
|
|
63
|
+
// These DSH hosts deliver the native Bash status as renderer suffixes.
|
|
64
|
+
const text = content?.length === 1 && content[0].type === 'text' ? content[0].text.trimEnd() : ''
|
|
65
|
+
if (/(?:^|\n)started background job [^\n]+$|\[still running after \d+ms; moved to background job [^\]\n]+\]/.test(text))
|
|
66
|
+
return 'UNKNOWN'
|
|
67
|
+
const nativeFailure = /(?:^|\n)\[(?:timed out after \d+ms|stopped: [^\]\n]+|sandbox: file access denied under [^\]\n]+ mode)\](?:\n|$)/.test(text)
|
|
68
|
+
|| /(?:^|\n)\[(?:exit code: (?!0\])-?\d+|killed by signal: [^\]\n]+)\]$/.test(text)
|
|
69
|
+
if (!nativeFailure && !state.bashFailures.some(row => row.rootCallId === rootCallId && row.callId === callId)) return outcome
|
|
63
70
|
return outcome === 'UNKNOWN' || outcome === 'NOT_RUN' ? 'UNKNOWN' : 'FAIL'
|
|
64
71
|
}
|
|
65
72
|
export function chainQualification(start, root, dispatches) {
|
package/remote.mjs
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
export function createRemoteContribution(z) {
|
|
4
4
|
const packageName = 'dsh-bettertaskgraphs'
|
|
5
5
|
const id = z.string().min(1).max(128)
|
|
6
|
-
const input = z.object({ sessionId: id }).strict()
|
|
7
6
|
const node = z.object({
|
|
8
7
|
id, label: z.string().min(1).max(512), kind: z.enum(['container', 'leaf']),
|
|
9
8
|
parent: id.nullable(),
|
|
@@ -40,9 +39,8 @@ export function createRemoteContribution(z) {
|
|
|
40
39
|
id: `${packageName}#transactionGraphView/status`,
|
|
41
40
|
service: 'transactionGraph', namespace: 'transactionGraphView', method: 'status', invocation: { kind: 'direct' },
|
|
42
41
|
parameters: [{
|
|
43
|
-
name: '
|
|
44
|
-
codec:
|
|
45
|
-
strictCodec: codec('TransactionGraphStatusStrictRequest', input),
|
|
42
|
+
name: 'session', wire: 'sessionId', source: 'lookup', lookup: 'session',
|
|
43
|
+
codec: { mode: 'strict', typeSymbol: '@deepseek-ai/dsh-session/types#SessionId', create: () => id },
|
|
46
44
|
}],
|
|
47
45
|
cancellation: { parameter: 'signal' },
|
|
48
46
|
result: codec('TransactionGraphStatusResult', output),
|