dsh-a2a-server 0.2.0 → 0.3.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/CHANGELOG.zh-CN.md +28 -0
  3. package/README.md +99 -26
  4. package/README.zh-CN.md +67 -27
  5. package/cordis.patch.yml +10 -6
  6. package/lib/briefing.d.ts +39 -0
  7. package/lib/briefing.d.ts.map +1 -0
  8. package/lib/briefing.js +108 -0
  9. package/lib/briefing.js.map +1 -0
  10. package/lib/config.d.ts +54 -15
  11. package/lib/config.d.ts.map +1 -1
  12. package/lib/config.js +70 -5
  13. package/lib/config.js.map +1 -1
  14. package/lib/contexts.d.ts +9 -4
  15. package/lib/contexts.d.ts.map +1 -1
  16. package/lib/contexts.js +7 -13
  17. package/lib/contexts.js.map +1 -1
  18. package/lib/index.d.ts +1 -31
  19. package/lib/index.d.ts.map +1 -1
  20. package/lib/index.js +418 -439
  21. package/lib/index.js.map +1 -1
  22. package/lib/management.d.ts +5 -0
  23. package/lib/management.d.ts.map +1 -0
  24. package/lib/management.js +74 -0
  25. package/lib/management.js.map +1 -0
  26. package/lib/projection.d.ts +46 -3
  27. package/lib/projection.d.ts.map +1 -1
  28. package/lib/projection.js +19 -8
  29. package/lib/projection.js.map +1 -1
  30. package/lib/router.d.ts +45 -0
  31. package/lib/router.d.ts.map +1 -1
  32. package/lib/router.js +207 -65
  33. package/lib/router.js.map +1 -1
  34. package/lib/security.d.ts +4 -2
  35. package/lib/security.d.ts.map +1 -1
  36. package/lib/security.js +4 -2
  37. package/lib/security.js.map +1 -1
  38. package/lib/state.d.ts +37 -0
  39. package/lib/state.d.ts.map +1 -0
  40. package/lib/state.js +146 -0
  41. package/lib/state.js.map +1 -0
  42. package/lib/tasks.d.ts +4 -0
  43. package/lib/tasks.d.ts.map +1 -1
  44. package/lib/tasks.js +18 -0
  45. package/lib/tasks.js.map +1 -1
  46. package/lib/types.d.ts +9 -0
  47. package/lib/types.d.ts.map +1 -1
  48. package/lib/types.js.map +1 -1
  49. package/lib/version.d.ts +1 -1
  50. package/lib/version.js +1 -1
  51. package/lib/workspace-read.d.ts +9 -0
  52. package/lib/workspace-read.d.ts.map +1 -0
  53. package/lib/workspace-read.js +152 -0
  54. package/lib/workspace-read.js.map +1 -0
  55. package/package.json +39 -30
package/lib/state.js ADDED
@@ -0,0 +1,146 @@
1
+ /** Bounded, private checkpoints for task retention and idle context recovery. */
2
+ import { createHash, randomUUID } from 'node:crypto';
3
+ import { mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, openSync, closeSync, statSync } from 'node:fs';
4
+ import { homedir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { z } from 'zod';
7
+ export function deploymentKey(config) {
8
+ return createHash('sha256').update(`${config.isolation.workspaceRoot}\n${config.basePath}\n${config.admin?.tokenEnv ?? ''}`).digest('hex').slice(0, 24);
9
+ }
10
+ const checkpointSchema = z.object({
11
+ id: z.string().uuid(), peer: z.string(), cwd: z.string(), updatedAt: z.number(),
12
+ turns: z.number().int().nonnegative(), events: z.array(z.unknown()),
13
+ inputs: z.record(z.string(), z.string()).default({}), exhausted: z.boolean().optional(),
14
+ tasks: z.array(z.object({ id: z.string(), contextId: z.string(), status: z.object({
15
+ state: z.string(), timestamp: z.string(),
16
+ }).passthrough() }).passthrough()),
17
+ });
18
+ const terminal = new Set(['TASK_STATE_COMPLETED', 'TASK_STATE_FAILED', 'TASK_STATE_CANCELED', 'TASK_STATE_REJECTED']);
19
+ /** Checkpoints are written before acceptance and after idle; directories must not be shared by processes. */
20
+ export class StateStore {
21
+ config;
22
+ directory;
23
+ records = new Map();
24
+ lock;
25
+ budgets = {};
26
+ constructor(config) {
27
+ this.config = config;
28
+ this.directory = config.storage.directory ?? join(homedir(), '.dsh-a2a', deploymentKey(config));
29
+ mkdirSync(this.directory, { recursive: true, mode: 0o700 });
30
+ this.lock = join(this.directory, 'process.lock');
31
+ try {
32
+ const pid = Number(readFileSync(this.lock, 'utf8'));
33
+ if (!Number.isSafeInteger(pid) || pid <= 0)
34
+ throw new Error('A2A state lock is incomplete or invalid');
35
+ let live = true;
36
+ try {
37
+ process.kill(pid, 0);
38
+ }
39
+ catch (error) {
40
+ live = error.code !== 'ESRCH';
41
+ }
42
+ if (live)
43
+ throw new Error('A2A state directory is already in use');
44
+ rmSync(this.lock);
45
+ }
46
+ catch (error) {
47
+ if (error.code !== 'ENOENT')
48
+ throw error;
49
+ }
50
+ const fd = openSync(this.lock, 'wx', 0o600);
51
+ writeFileSync(fd, String(process.pid));
52
+ closeSync(fd);
53
+ try {
54
+ for (const file of readdirSync(this.directory)) {
55
+ if (!/^[0-9a-f-]{36}\.json$/.test(file))
56
+ continue;
57
+ if (statSync(join(this.directory, file)).size > config.storage.maxContextBytes)
58
+ throw new Error('stored A2A checkpoint exceeds configured size');
59
+ if (this.records.size >= config.storage.maxContexts)
60
+ throw new Error('stored A2A contexts exceed configured capacity');
61
+ const parsed = checkpointSchema.parse(JSON.parse(readFileSync(join(this.directory, file), 'utf8')));
62
+ if (`${parsed.id}.json` !== file)
63
+ throw new Error('A2A checkpoint id mismatch');
64
+ // The harness validates the event vocabulary and sequence again at restore.
65
+ const record = parsed;
66
+ for (const task of record.tasks) {
67
+ if (task.contextId !== record.id)
68
+ throw new Error('A2A checkpoint task ownership mismatch');
69
+ if (!terminal.has(task.status.state)) {
70
+ task.status = { state: 'TASK_STATE_FAILED', timestamp: new Date().toISOString() };
71
+ task.metadata = { dsh: { stopReason: 'process_restart' } };
72
+ }
73
+ }
74
+ this.records.set(record.id, record);
75
+ }
76
+ try {
77
+ this.budgets = z.record(z.string(), z.object({ day: z.string(), count: z.number().int().nonnegative() }))
78
+ .parse(JSON.parse(readFileSync(join(this.directory, 'budgets.json'), 'utf8')));
79
+ }
80
+ catch (error) {
81
+ if (error.code !== 'ENOENT')
82
+ throw error;
83
+ }
84
+ this.prune();
85
+ }
86
+ catch (error) {
87
+ this.close();
88
+ throw error;
89
+ }
90
+ }
91
+ write(name, value) {
92
+ const text = JSON.stringify(value);
93
+ if (Buffer.byteLength(text) > this.config.storage.maxContextBytes)
94
+ throw new Error('A2A checkpoint size limit exceeded');
95
+ const target = join(this.directory, name);
96
+ const temporary = `${target}.${randomUUID()}.tmp`;
97
+ try {
98
+ writeFileSync(temporary, text, { mode: 0o600 });
99
+ renameSync(temporary, target);
100
+ }
101
+ finally {
102
+ rmSync(temporary, { force: true });
103
+ }
104
+ }
105
+ save(record) {
106
+ this.write(`${record.id}.json`, record);
107
+ this.records.set(record.id, record);
108
+ }
109
+ /** Fail-closed live outcome when disk I/O itself is unavailable. */
110
+ rememberFailure(record) { this.records.set(record.id, record); }
111
+ get(id, peer) {
112
+ const record = this.records.get(id);
113
+ return record?.peer === peer ? record : undefined;
114
+ }
115
+ values() { return [...this.records.values()]; }
116
+ ensureRoom(protectedIds = new Set()) {
117
+ this.prune(protectedIds);
118
+ if (this.records.size >= this.config.storage.maxContexts)
119
+ throw new Error('A2A retained context capacity reached');
120
+ }
121
+ prune(protectedIds = new Set()) {
122
+ for (const [id, record] of this.records) {
123
+ if (!protectedIds.has(id) && record.updatedAt < Date.now() - this.config.storage.retentionMs) {
124
+ rmSync(join(this.directory, `${id}.json`), { force: true });
125
+ this.records.delete(id);
126
+ }
127
+ }
128
+ }
129
+ assertQuota(peer) {
130
+ const current = this.budgets[peer];
131
+ if (current?.day === new Date().toISOString().slice(0, 10) && current.count >= this.config.maxTasksPerPeerPerDay) {
132
+ throw new Error('daily task quota exceeded');
133
+ }
134
+ }
135
+ charge(peer) {
136
+ const day = new Date().toISOString().slice(0, 10);
137
+ const previous = this.budgets[peer];
138
+ const count = previous?.day === day ? previous.count : 0;
139
+ this.assertQuota(peer);
140
+ const next = { ...this.budgets, [peer]: { day, count: count + 1 } };
141
+ this.write('budgets.json', next);
142
+ this.budgets = next;
143
+ }
144
+ close() { rmSync(this.lock, { force: true }); }
145
+ }
146
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
package/lib/tasks.d.ts CHANGED
@@ -42,6 +42,10 @@ export interface TaskSlot {
42
42
  settle: (settlement: TaskSettlement) => void;
43
43
  /** Whether `settle` has already run. */
44
44
  done: boolean;
45
+ /** Monotonic subscribers, removable on disconnected transports. */
46
+ onSettled: (listener: (settlement: TaskSettlement) => void) => () => void;
47
+ forcedState?: A2ATaskState;
48
+ modelCalls?: number;
45
49
  }
46
50
  /**
47
51
  * Create an unsettled task slot.
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAE/E,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,YAAY,CAAA;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,SAAS,EAAE,WAAW,EAAE,CAAA;CACzB;AAED,8CAA8C;AAC9C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,kEAAkE;IAClE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IACzC,sCAAsC;IACtC,MAAM,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAA;IAC5C,wCAAwC;IACxC,IAAI,EAAE,OAAO,CAAA;CACd;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,CAkBzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,EAAE,CAQ7F;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAK3E"}
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAE/E,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,YAAY,CAAA;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,SAAS,EAAE,WAAW,EAAE,CAAA;CACzB;AAED,8CAA8C;AAC9C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,kEAAkE;IAClE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IACzC,sCAAsC;IACtC,MAAM,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAA;IAC5C,wCAAwC;IACxC,IAAI,EAAE,OAAO,CAAA;IACb,mEAAmE;IACnE,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;IACzE,WAAW,CAAC,EAAE,YAAY,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,CA+BzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,EAAE,CAQ7F;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAK3E"}
package/lib/tasks.js CHANGED
@@ -25,6 +25,8 @@
25
25
  export function createSlot(taskId, messageId) {
26
26
  let fulfil;
27
27
  const settled = new Promise((resolve) => { fulfil = resolve; });
28
+ const listeners = new Set();
29
+ let result;
28
30
  const slot = {
29
31
  taskId,
30
32
  messageId,
@@ -37,7 +39,23 @@ export function createSlot(taskId, messageId) {
37
39
  if (slot.done)
38
40
  return;
39
41
  slot.done = true;
42
+ result = settlement;
40
43
  fulfil?.(settlement);
44
+ for (const listener of listeners) {
45
+ // A broken transport must not strand other subscribers or quotas.
46
+ try {
47
+ listener(settlement);
48
+ }
49
+ catch { /* Each transport owns its errors. */ }
50
+ }
51
+ listeners.clear();
52
+ },
53
+ onSettled: listener => {
54
+ if (result !== undefined)
55
+ listener(result);
56
+ else
57
+ listeners.add(listener);
58
+ return () => { listeners.delete(listener); };
41
59
  },
42
60
  };
43
61
  return slot;
package/lib/tasks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAgCH;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAiB,EAAE,SAAiB;IAC7D,IAAI,MAA0D,CAAA;IAC9D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE,GAAG,MAAM,GAAG,OAAO,CAAA,CAAC,CAAC,CAAC,CAAA;IAC9E,MAAM,IAAI,GAAa;QACrB,MAAM;QACN,SAAS;QACT,IAAI,EAAE,SAAS;QACf,SAAS,EAAE,SAAS;QACpB,KAAK,EAAE,EAAE;QACT,OAAO;QACP,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE;YACrB,IAAI,IAAI,CAAC,IAAI;gBAAE,OAAM;YACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;YAChB,MAAM,EAAE,CAAC,UAAU,CAAC,CAAA;QACtB,CAAC;KACF,CAAA;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,KAAwB;IAC5E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAClC,OAAO,CAAC;YACN,UAAU,EAAE,GAAG,MAAM,SAAS;YAC9B,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;SACnD,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,SAA6B;IAC3D,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,qBAAqB,CAAA;IACzD,IAAI,SAAS,KAAK,OAAO;QAAE,OAAO,mBAAmB,CAAA;IACrD,IAAI,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO,qBAAqB,CAAA;IACvF,OAAO,sBAAsB,CAAA;AAC/B,CAAC"}
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAoCH;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAiB,EAAE,SAAiB;IAC7D,IAAI,MAA0D,CAAA;IAC9D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE,GAAG,MAAM,GAAG,OAAO,CAAA,CAAC,CAAC,CAAC,CAAA;IAC9E,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAA;IACjE,IAAI,MAAkC,CAAA;IACtC,MAAM,IAAI,GAAa;QACrB,MAAM;QACN,SAAS;QACT,IAAI,EAAE,SAAS;QACf,SAAS,EAAE,SAAS;QACpB,KAAK,EAAE,EAAE;QACT,OAAO;QACP,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE;YACrB,IAAI,IAAI,CAAC,IAAI;gBAAE,OAAM;YACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;YAChB,MAAM,GAAG,UAAU,CAAA;YACnB,MAAM,EAAE,CAAC,UAAU,CAAC,CAAA;YACpB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,kEAAkE;gBAClE,IAAI,CAAC;oBAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,qCAAqC,CAAC,CAAC;YAC9E,CAAC;YACD,SAAS,CAAC,KAAK,EAAE,CAAA;QACnB,CAAC;QACD,SAAS,EAAE,QAAQ,CAAC,EAAE;YACpB,IAAI,MAAM,KAAK,SAAS;gBAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;;gBACrC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAC5B,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA,CAAC,CAAC,CAAA;QAC7C,CAAC;KACF,CAAA;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,KAAwB;IAC5E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAClC,OAAO,CAAC;YACN,UAAU,EAAE,GAAG,MAAM,SAAS;YAC9B,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;SACnD,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,SAA6B;IAC3D,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,qBAAqB,CAAA;IACzD,IAAI,SAAS,KAAK,OAAO;QAAE,OAAO,mBAAmB,CAAA;IACrD,IAAI,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO,qBAAqB,CAAA;IACvF,OAAO,sBAAsB,CAAA;AAC/B,CAAC"}
package/lib/types.d.ts CHANGED
@@ -33,6 +33,15 @@ declare module '@deepseek-ai/dsh-session/types' {
33
33
  state: A2ATaskState;
34
34
  /** The turn this task correlates with, once one has claimed its message. */
35
35
  turn?: number;
36
+ /**
37
+ * Non-terminal edges: the visitor's submitted text, verbatim.
38
+ *
39
+ * Recorded so the monitoring surface can show what a visitor SAID without
40
+ * reaching into the message history — the same whole-value discipline the
41
+ * terminal edge applies to `output`. Absent on terminal edges, which carry
42
+ * the answer instead.
43
+ */
44
+ input?: string;
36
45
  /** Terminal edges only: the real harness turn ending, for Task.metadata. */
37
46
  stopReason?: string;
38
47
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,QAAQ,gCAAgC,CAAC;IAC9C,UAAU,eAAe;QACvB;;;;;;;WAOG;QACH,UAAU,EAAE;YACV,qCAAqC;YACrC,MAAM,EAAE,SAAS,CAAA;YACjB,qEAAqE;YACrE,IAAI,EAAE,MAAM,CAAA;YACZ,0CAA0C;YAC1C,KAAK,EAAE,YAAY,CAAA;YACnB,4EAA4E;YAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;YACb,4EAA4E;YAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;YACnB;;;;;;;;eAQG;YACH,MAAM,CAAC,EAAE,MAAM,CAAA;SAChB,CAAA;KACF;CACF;AAED,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB;;;;;;WAMG;QACH,OAAO,EAAE;YACP,IAAI,EAAE,UAAU,CAAA;YAChB,2EAA2E;YAC3E,IAAI,EAAE,MAAM,CAAA;YACZ,sDAAsD;YACtD,MAAM,EAAE,SAAS,CAAA;YACjB,IAAI,EAAE,OAAO,CAAA;SACd,CAAA;KACF;CACF;AAED,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,QAAQ,gCAAgC,CAAC;IAC9C,UAAU,eAAe;QACvB;;;;;;;WAOG;QACH,UAAU,EAAE;YACV,qCAAqC;YACrC,MAAM,EAAE,SAAS,CAAA;YACjB,qEAAqE;YACrE,IAAI,EAAE,MAAM,CAAA;YACZ,0CAA0C;YAC1C,KAAK,EAAE,YAAY,CAAA;YACnB,4EAA4E;YAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;YACb;;;;;;;eAOG;YACH,KAAK,CAAC,EAAE,MAAM,CAAA;YACd,4EAA4E;YAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;YACnB;;;;;;;;eAQG;YACH,MAAM,CAAC,EAAE,MAAM,CAAA;SAChB,CAAA;KACF;CACF;AAED,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB;;;;;;WAMG;QACH,OAAO,EAAE;YACP,IAAI,EAAE,UAAU,CAAA;YAChB,2EAA2E;YAC3E,IAAI,EAAE,MAAM,CAAA;YACZ,sDAAsD;YACtD,MAAM,EAAE,SAAS,CAAA;YACjB,IAAI,EAAE,OAAO,CAAA;SACd,CAAA;KACF;CACF;AAED,OAAO,EAAE,CAAA"}
package/lib/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA2DH,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAoEH,OAAO,EAAE,CAAA"}
package/lib/version.d.ts CHANGED
@@ -16,5 +16,5 @@
16
16
  * @module dsh-a2a/version
17
17
  */
18
18
  /** Must equal `version` in package.json. */
19
- export declare const SERVER_VERSION = "0.2.0";
19
+ export declare const SERVER_VERSION = "0.3.0";
20
20
  //# sourceMappingURL=version.d.ts.map
package/lib/version.js CHANGED
@@ -16,5 +16,5 @@
16
16
  * @module dsh-a2a/version
17
17
  */
18
18
  /** Must equal `version` in package.json. */
19
- export const SERVER_VERSION = '0.2.0';
19
+ export const SERVER_VERSION = '0.3.0';
20
20
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,9 @@
1
+ import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
2
+ export declare const WORKSPACE_READ_TOOL = "read_file";
3
+ /**
4
+ * Pin a canonical root for this activation. Never mount the host's general read
5
+ * tool: its path policy is different. State directories remain private even
6
+ * when an operator puts them inside the shared data root.
7
+ */
8
+ export declare function workspaceReadTool(directory: string, privateDirectories: readonly string[]): Promise<ToolDefinition>;
9
+ //# sourceMappingURL=workspace-read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-read.d.ts","sourceRoot":"","sources":["../src/workspace-read.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAG5D,eAAO,MAAM,mBAAmB,cAAc,CAAA;AAe9C;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CA0GzH"}
@@ -0,0 +1,152 @@
1
+ /** A single read capability rooted in the owner's configured data directory. */
2
+ import { constants } from 'node:fs';
3
+ import { lstat, open, opendir, realpath } from 'node:fs/promises';
4
+ import { isAbsolute, join, relative, resolve, sep } from 'node:path';
5
+ import { z } from 'zod';
6
+ export const WORKSPACE_READ_TOOL = 'read_file';
7
+ const MAX_FILE_BYTES = 2 * 1024 * 1024;
8
+ const MAX_TEXT_CHARS = 32_000;
9
+ const MAX_DIRECTORY_SCAN = 1000;
10
+ const argsSchema = z.object({
11
+ path: z.string().min(1).max(4096),
12
+ offset: z.number().int().min(1).max(10_000_000).default(1),
13
+ limit: z.number().int().min(1).max(500).default(200),
14
+ }).strict();
15
+ function within(root, target) {
16
+ const suffix = relative(root, target);
17
+ return suffix === '' || (!isAbsolute(suffix) && suffix !== '..' && !suffix.startsWith(`..${sep}`));
18
+ }
19
+ /**
20
+ * Pin a canonical root for this activation. Never mount the host's general read
21
+ * tool: its path policy is different. State directories remain private even
22
+ * when an operator puts them inside the shared data root.
23
+ */
24
+ export async function workspaceReadTool(directory, privateDirectories) {
25
+ const configuredRoot = resolve(directory);
26
+ const root = await realpath(directory);
27
+ const privatePaths = await Promise.all(privateDirectories.map(async (path) => {
28
+ const absolute = resolve(path);
29
+ return { absolute, canonical: await realpath(absolute).catch(() => absolute) };
30
+ }));
31
+ const isPrivate = (path) => privatePaths.some(p => within(p.absolute, path) || within(p.canonical, path));
32
+ const validatePath = async (input) => {
33
+ if (input.includes('\0'))
34
+ throw new Error('Invalid file path');
35
+ // Reject NT device namespaces and alternate data streams before normalization.
36
+ if (process.platform === 'win32' && (/^[/\\]{2}[?.][/\\]/.test(input) || input.replace(/^[a-z]:/i, '').includes(':'))) {
37
+ throw new Error('Device paths and alternate data streams are not available');
38
+ }
39
+ const absolute = resolve(root, input);
40
+ // Windows may return an expanded path for a configured 8.3 directory alias.
41
+ const candidate = isAbsolute(input) && within(configuredRoot, absolute)
42
+ ? resolve(root, relative(configuredRoot, absolute)) : absolute;
43
+ if (!within(root, candidate) || isPrivate(candidate))
44
+ throw new Error('Path is outside the authorized data directory');
45
+ const canonical = await realpath(candidate);
46
+ if (!within(root, canonical) || isPrivate(canonical))
47
+ throw new Error('Path is outside the authorized data directory');
48
+ // Refuse links/junctions along the entire relative path, even when a link
49
+ // currently targets this root. An authorized directory is not a link portal.
50
+ let current = root;
51
+ for (const component of ['', ...relative(root, candidate).split(sep).filter(Boolean)]) {
52
+ if (component)
53
+ current = join(current, component);
54
+ if ((await lstat(current)).isSymbolicLink())
55
+ throw new Error('Symbolic links and junctions are not available');
56
+ }
57
+ return candidate;
58
+ };
59
+ return {
60
+ name: WORKSPACE_READ_TOOL,
61
+ description: 'Read a UTF-8 text file from the owner-authorized data directory. Paths are relative to that directory (not the agent cwd); absolute paths must remain inside it. Use path "." to list its entries, or a subdirectory path to list that directory. offset is a 1-based line/entry offset; limit is at most 500. Other tools and writes are unavailable.',
62
+ parameters: {
63
+ type: 'object', additionalProperties: false, required: ['path'], properties: {
64
+ path: { type: 'string', minLength: 1, maxLength: 4096 },
65
+ offset: { type: 'integer', minimum: 1, maximum: 10_000_000 },
66
+ limit: { type: 'integer', minimum: 1, maximum: 500 },
67
+ },
68
+ },
69
+ output: {
70
+ schema: { type: 'object', required: ['kind', 'path', 'content', 'truncated'], properties: {
71
+ kind: { type: 'string' }, path: { type: 'string' }, content: { type: 'string' }, truncated: { type: 'boolean' },
72
+ } },
73
+ render: (_args, value) => [{ type: 'text', text: JSON.stringify(value) }],
74
+ },
75
+ execute: async (raw, { signal }) => {
76
+ const args = argsSchema.parse(raw);
77
+ signal.throwIfAborted();
78
+ const path = await validatePath(args.path);
79
+ const before = await lstat(path);
80
+ if (before.isDirectory()) {
81
+ const entries = [];
82
+ let scanned = 0;
83
+ let truncated = false;
84
+ // Read at most a bounded prefix; do not build an unbounded directory tree.
85
+ const dir = await opendir(path);
86
+ for await (const entry of dir) {
87
+ signal.throwIfAborted();
88
+ if (++scanned > MAX_DIRECTORY_SCAN) {
89
+ truncated = true;
90
+ break;
91
+ }
92
+ if (entry.isSymbolicLink() || isPrivate(join(path, entry.name)))
93
+ continue;
94
+ if (!entry.isFile() && !entry.isDirectory())
95
+ continue;
96
+ entries.push(`${entry.name}${entry.isDirectory() ? '/' : ''}`);
97
+ }
98
+ const after = await lstat(await validatePath(args.path));
99
+ if (before.dev !== after.dev || before.ino !== after.ino)
100
+ throw new Error('Directory changed during read; retry');
101
+ entries.sort();
102
+ const selected = entries.slice(args.offset - 1, args.offset - 1 + args.limit).join('\n');
103
+ return { kind: 'directory', path: relative(root, path) || '.', content: selected.slice(0, MAX_TEXT_CHARS),
104
+ truncated: truncated || entries.length > args.offset - 1 + args.limit || selected.length > MAX_TEXT_CHARS };
105
+ }
106
+ if (!before.isFile())
107
+ throw new Error('Only regular text files and directories can be read');
108
+ if (before.nlink > 1)
109
+ throw new Error('Hard-linked files are not available');
110
+ if (before.size > MAX_FILE_BYTES)
111
+ throw new Error('File exceeds the 2 MiB read limit');
112
+ // O_NOFOLLOW is supported on Unix. Windows is covered by the component
113
+ // checks and comparing the opened file's identity before reading any bytes.
114
+ const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
115
+ try {
116
+ const opened = await handle.stat();
117
+ if (!opened.isFile() || opened.nlink > 1 || opened.dev !== before.dev || opened.ino !== before.ino)
118
+ throw new Error('File changed during open; retry');
119
+ if (opened.size > MAX_FILE_BYTES)
120
+ throw new Error('File exceeds the 2 MiB read limit');
121
+ await validatePath(args.path);
122
+ // Explicit byte limit also bounds reads if a local writer grows the file.
123
+ const bytes = Buffer.alloc(MAX_FILE_BYTES + 1);
124
+ let used = 0;
125
+ while (used < bytes.length) {
126
+ signal.throwIfAborted();
127
+ const part = await handle.read(bytes, used, bytes.length - used, used);
128
+ if (!part.bytesRead)
129
+ break;
130
+ used += part.bytesRead;
131
+ }
132
+ if (used > MAX_FILE_BYTES)
133
+ throw new Error('File exceeds the 2 MiB read limit');
134
+ const after = await lstat(await validatePath(args.path));
135
+ if (opened.dev !== after.dev || opened.ino !== after.ino || after.nlink > 1)
136
+ throw new Error('File changed during read; retry');
137
+ signal.throwIfAborted();
138
+ const content = new TextDecoder('utf-8', { fatal: true }).decode(bytes.subarray(0, used));
139
+ if (content.includes('\0'))
140
+ throw new Error('Binary files are not supported by read_file');
141
+ const lines = content.split(/\r?\n/);
142
+ const selected = lines.slice(args.offset - 1, args.offset - 1 + args.limit).join('\n');
143
+ return { kind: 'file', path: relative(root, path), content: selected.slice(0, MAX_TEXT_CHARS),
144
+ truncated: lines.length > args.offset - 1 + args.limit || selected.length > MAX_TEXT_CHARS };
145
+ }
146
+ finally {
147
+ await handle.close();
148
+ }
149
+ },
150
+ };
151
+ }
152
+ //# sourceMappingURL=workspace-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-read.js","sourceRoot":"","sources":["../src/workspace-read.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-a2a-server",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Inbound A2A (Agent2Agent) protocol server for DeepSeek Harness: publish an Agent Card and let any A2A-compliant peer submit tasks to a harness agent",
5
5
  "keywords": [
6
6
  "dsh",
@@ -27,57 +27,66 @@
27
27
  },
28
28
  "files": [
29
29
  "lib",
30
- "cordis.patch.yml"
30
+ "cordis.patch.yml",
31
+ "CHANGELOG.md",
32
+ "CHANGELOG.zh-CN.md"
31
33
  ],
32
34
  "dsh": {
33
35
  "bundle": {
34
36
  "patch": "./cordis.patch.yml"
35
37
  }
36
38
  },
39
+ "engines": {
40
+ "dsh": ">=0.2.1-rc.2 <0.3.0"
41
+ },
37
42
  "scripts": {
38
43
  "build": "tsc -p tsconfig.build.json",
39
44
  "typecheck": "tsc -p tsconfig.json --noEmit",
40
45
  "test": "vitest run",
41
46
  "test:watch": "vitest",
47
+ "test:package": "pnpm build && node scripts/test-package.mjs",
42
48
  "serve": "tsx example/serve.ts",
43
49
  "probe": "node example/probe.mjs",
44
- "prepublishOnly": "pnpm typecheck && pnpm test && pnpm build"
50
+ "prepublishOnly": "pnpm typecheck && pnpm test && pnpm test:package"
45
51
  },
46
52
  "peerDependencies": {
47
- "@deepseek-ai/cordis": "4.0.1",
48
- "@deepseek-ai/dsh-agent": "0.1.0-rc.6",
49
- "@deepseek-ai/dsh-credentials": "0.1.0-rc.6",
50
- "@deepseek-ai/dsh-host-webserver": "0.1.0-rc.6",
51
- "@deepseek-ai/dsh-llm": "0.1.0-rc.6",
52
- "@deepseek-ai/dsh-session": "0.1.0-rc.6"
53
+ "@deepseek-ai/cordis": "^4.0.5",
54
+ "@deepseek-ai/dsh-agent": ">=0.2.1-rc.2 <0.3.0",
55
+ "@deepseek-ai/dsh-credentials": ">=0.2.1-rc.2 <0.3.0",
56
+ "@deepseek-ai/dsh-host-webserver": ">=0.2.1-rc.2 <0.3.0",
57
+ "@deepseek-ai/dsh-llm": ">=0.2.1-rc.2 <0.3.0",
58
+ "@deepseek-ai/dsh-session": ">=0.2.1-rc.2 <0.3.0",
59
+ "@deepseek-ai/dsh-session-projection": ">=0.2.1-rc.2 <0.3.0",
60
+ "@deepseek-ai/dsh-tools": ">=0.2.1-rc.2 <0.3.0",
61
+ "@deepseek-ai/dsh-system-prompt": ">=0.2.1-rc.2 <0.3.0"
53
62
  },
54
63
  "dependencies": {
55
- "@deepseek-ai/schemastery": "3.18.1"
64
+ "@deepseek-ai/schemastery": "^3.18.5",
65
+ "zod": "^4.4.3"
56
66
  },
57
67
  "devDependencies": {
58
- "@deepseek-ai/cordis": "4.0.1",
59
- "@deepseek-ai/cordis-plugin-loader": "1.0.2",
60
- "@deepseek-ai/dsh-agent": "0.1.0-rc.6",
61
- "@deepseek-ai/dsh-agent-loop": "0.1.0-rc.6",
62
- "@deepseek-ai/dsh-agent-loop-testkit": "0.1.0-rc.6",
63
- "@deepseek-ai/dsh-brand": "0.1.0-rc.6",
64
- "@deepseek-ai/dsh-credentials": "0.1.0-rc.6",
65
- "@deepseek-ai/dsh-credentials-local": "0.1.0-rc.6",
66
- "@deepseek-ai/dsh-host-webserver": "0.1.0-rc.6",
67
- "@deepseek-ai/dsh-invariants": "0.1.0-rc.6",
68
- "@deepseek-ai/dsh-llm": "0.1.0-rc.6",
69
- "@deepseek-ai/dsh-llm-deepseek": "0.1.0-rc.6",
70
- "@deepseek-ai/dsh-llm-replay": "0.1.0-rc.6",
71
- "@deepseek-ai/dsh-scope": "0.1.0-rc.6",
72
- "@deepseek-ai/dsh-session": "0.1.0-rc.6",
73
- "@deepseek-ai/dsh-session-projection": "0.1.0-rc.6",
74
- "@deepseek-ai/dsh-system-prompt": "0.1.0-rc.6",
75
- "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
68
+ "@deepseek-ai/cordis": "4.0.5",
69
+ "@deepseek-ai/cordis-plugin-loader": "1.0.6",
70
+ "@deepseek-ai/dsh-agent": "0.2.1-rc.2",
71
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-rc.2",
72
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-rc.2",
73
+ "@deepseek-ai/dsh-brand": "0.2.1-rc.2",
74
+ "@deepseek-ai/dsh-credentials": "0.2.1-rc.2",
75
+ "@deepseek-ai/dsh-credentials-local": "0.2.1-rc.2",
76
+ "@deepseek-ai/dsh-host-webserver": "0.2.1-rc.2",
77
+ "@deepseek-ai/dsh-llm": "0.2.1-rc.2",
78
+ "@deepseek-ai/dsh-llm-deepseek": "0.2.1-rc.2",
79
+ "@deepseek-ai/dsh-llm-deepseek-api-key": "0.2.1-rc.2",
80
+ "@deepseek-ai/dsh-llm-replay": "0.2.1-rc.2",
81
+ "@deepseek-ai/dsh-scope": "0.2.1-rc.2",
82
+ "@deepseek-ai/dsh-session": "0.2.1-rc.2",
83
+ "@deepseek-ai/dsh-session-projection": "0.2.1-rc.2",
84
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
85
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.2",
76
86
  "@types/node": "^22.10.0",
77
87
  "tsx": "^4.19.2",
78
88
  "typescript": "^5.7.2",
79
- "vitest": "^2.1.8",
80
- "zod": "^4.4.3"
89
+ "vitest": "^2.1.8"
81
90
  },
82
91
  "repository": {
83
92
  "type": "git",