super-dsh 0.1.3 → 0.1.5

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 (142) hide show
  1. package/README.md +3 -3
  2. package/agent-agy/cordis.patch.yml +8 -4
  3. package/agent-agy/dist/agent-preset-agy.d.ts +23 -43
  4. package/agent-agy/dist/agent-preset-agy.js +29 -166
  5. package/agent-agy/dist/agent.d.ts +2 -1
  6. package/agent-agy/dist/agent.js +3 -2
  7. package/agent-agy/dist/agy-sessions.d.ts +2 -1
  8. package/agent-agy/dist/agy-sessions.js +2 -11
  9. package/agent-agy/dist/index.js +13 -12
  10. package/agent-agy/dist/world-plugin.d.ts +2 -1
  11. package/agent-agy/dist/world-plugin.js +31 -51
  12. package/agent-agy/package.json +6 -6
  13. package/agent-claude/cordis.patch.yml +8 -4
  14. package/agent-claude/dist/agent-preset-claude.js +29 -166
  15. package/agent-claude/dist/agent.js +10 -10
  16. package/agent-claude/dist/claude-client.js +22 -3
  17. package/agent-claude/dist/claude-home.js +0 -8
  18. package/agent-claude/dist/index.js +12 -15
  19. package/agent-claude/dist/session-map.js +2 -5
  20. package/agent-claude/dist/world-plugin.js +3 -3
  21. package/agent-claude/package.json +9 -9
  22. package/agent-codex/README.md +8 -8
  23. package/agent-codex/cordis.patch.yml +9 -5
  24. package/agent-codex/dist/agent-preset-codex.js +29 -168
  25. package/agent-codex/dist/agent.js +17 -12
  26. package/agent-codex/dist/codex-store.js +0 -9
  27. package/agent-codex/dist/index.js +13 -16
  28. package/agent-codex/dist/session-map.js +2 -5
  29. package/agent-codex/dist/world-plugin.js +31 -51
  30. package/agent-codex/package.json +14 -11
  31. package/agent-hermes/README.md +9 -8
  32. package/agent-hermes/cordis.patch.yml +8 -4
  33. package/agent-hermes/dist/agent-preset-hermes.js +29 -168
  34. package/agent-hermes/dist/agent.js +33 -19
  35. package/agent-hermes/dist/hermes-client.js +5 -5
  36. package/agent-hermes/dist/hermes-store.js +2 -11
  37. package/agent-hermes/dist/index.js +13 -12
  38. package/agent-hermes/dist/world-plugin.js +31 -52
  39. package/agent-hermes/package.json +14 -11
  40. package/agent-omp/README.md +2 -2
  41. package/agent-omp/cordis.patch.yml +12 -7
  42. package/agent-omp/dist/agent-preset-omp.js +30 -169
  43. package/agent-omp/dist/agent.js +13 -5
  44. package/agent-omp/dist/index.js +12 -22
  45. package/agent-omp/dist/mobile/gesture.js +2 -2
  46. package/agent-omp/dist/mobile/zoom-guard.js +4 -4
  47. package/agent-omp/dist/mobile-boot.js +2 -2
  48. package/agent-omp/dist/omp-cli.js +1 -1
  49. package/agent-omp/dist/omp-disk-discovery.js +1 -1
  50. package/agent-omp/dist/protocol.js +1 -1
  51. package/agent-omp/dist/sidecar-client.js +1 -1
  52. package/agent-omp/dist/world-plugin.js +37 -50
  53. package/agent-omp/package.json +18 -14
  54. package/agent-omp/sidecar/main.ts +2 -2
  55. package/agent-pi/README.md +5 -5
  56. package/agent-pi/cordis.patch.yml +8 -4
  57. package/agent-pi/dist/agent-preset-pi.js +29 -166
  58. package/agent-pi/dist/agent.js +18 -12
  59. package/agent-pi/dist/index.js +14 -16
  60. package/agent-pi/dist/pi-home.js +2 -12
  61. package/agent-pi/dist/world-plugin.js +31 -51
  62. package/agent-pi/package.json +14 -11
  63. package/client/index.js +1994 -150
  64. package/cordis.patch.yml +38 -15
  65. package/package.json +32 -30
  66. package/{agent-hub → superd-hub}/cordis.patch.yml +3 -3
  67. package/{agent-hub → superd-hub}/dist/agent-roster.d.ts +3 -1
  68. package/{agent-hub → superd-hub}/dist/agent-roster.js +4 -2
  69. package/superd-hub/dist/carrier.d.ts +62 -0
  70. package/superd-hub/dist/carrier.js +213 -0
  71. package/superd-hub/dist/fusion-transport.d.ts +148 -0
  72. package/superd-hub/dist/fusion-transport.js +397 -0
  73. package/{agent-hub → superd-hub}/dist/gateway.d.ts +9 -4
  74. package/superd-hub/dist/gateway.js +44 -0
  75. package/superd-hub/dist/hub-route.d.ts +74 -0
  76. package/superd-hub/dist/hub-route.js +188 -0
  77. package/{agent-hub → superd-hub}/dist/index.d.ts +14 -6
  78. package/{agent-hub → superd-hub}/dist/index.js +14 -6
  79. package/{agent-hub → superd-hub}/dist/roster.d.ts +2 -2
  80. package/{agent-hub → superd-hub}/dist/rpc.js +1 -1
  81. package/{agent-hub → superd-hub}/dist/spawn-world.d.ts +27 -6
  82. package/superd-hub/dist/spawn-world.js +279 -0
  83. package/superd-hub/dist/switch-core.d.ts +630 -0
  84. package/superd-hub/dist/switch-core.js +734 -0
  85. package/superd-hub/dist/system-head.d.ts +69 -0
  86. package/superd-hub/dist/system-head.js +194 -0
  87. package/superd-hub/dist/web-trust.d.ts +112 -0
  88. package/superd-hub/dist/web-trust.js +126 -0
  89. package/superd-hub/dist/world-entry.d.ts +38 -0
  90. package/superd-hub/dist/world-entry.js +47 -0
  91. package/{agent-hub → superd-hub}/dist/world-host.d.ts +15 -20
  92. package/superd-hub/dist/world-host.js +65 -0
  93. package/{agent-hub → superd-hub}/dist/world-join.d.ts +2 -1
  94. package/{agent-hub → superd-hub}/dist/world-join.js +30 -50
  95. package/superd-hub/dist/world-mount.d.ts +82 -0
  96. package/superd-hub/dist/world-mount.js +105 -0
  97. package/{agent-hub → superd-hub}/dist/world-mux.d.ts +21 -6
  98. package/superd-hub/dist/world-mux.js +392 -0
  99. package/{agent-hub → superd-hub}/dist/world-provision.d.ts +20 -4
  100. package/superd-hub/dist/world-provision.js +203 -0
  101. package/superd-hub/dist/world-web-server.d.ts +113 -0
  102. package/superd-hub/dist/world-web-server.js +99 -0
  103. package/superd-hub/lib/client/index.js +2086 -0
  104. package/{agent-hub → superd-hub}/package.json +12 -7
  105. package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
  106. package/agent-agy/dist/agent-preset-projection.js +0 -33
  107. package/agent-claude/dist/agent-preset-projection.js +0 -30
  108. package/agent-codex/dist/agent-preset-projection.js +0 -37
  109. package/agent-codex/dist/app-home.js +0 -65
  110. package/agent-codex/dist/spike.js +0 -46
  111. package/agent-hermes/dist/agent-preset-projection.js +0 -34
  112. package/agent-hub/dist/carrier.d.ts +0 -43
  113. package/agent-hub/dist/carrier.js +0 -241
  114. package/agent-hub/dist/client-shim.d.ts +0 -28
  115. package/agent-hub/dist/client-shim.js +0 -251
  116. package/agent-hub/dist/gateway.js +0 -18
  117. package/agent-hub/dist/index-pass.d.ts +0 -22
  118. package/agent-hub/dist/index-pass.js +0 -47
  119. package/agent-hub/dist/labels.d.ts +0 -45
  120. package/agent-hub/dist/labels.js +0 -83
  121. package/agent-hub/dist/spawn-world.js +0 -72
  122. package/agent-hub/dist/world-entry.d.ts +0 -31
  123. package/agent-hub/dist/world-entry.js +0 -51
  124. package/agent-hub/dist/world-host.js +0 -44
  125. package/agent-hub/dist/world-mount.d.ts +0 -52
  126. package/agent-hub/dist/world-mount.js +0 -52
  127. package/agent-hub/dist/world-mux.js +0 -224
  128. package/agent-hub/dist/world-provision.js +0 -122
  129. package/agent-hub/dist/world-web-server.d.ts +0 -162
  130. package/agent-hub/dist/world-web-server.js +0 -248
  131. package/agent-hub/lib/client/index.js +0 -242
  132. package/agent-omp/dist/agent-preset-projection.js +0 -36
  133. package/agent-omp/dist/app-home.js +0 -86
  134. package/agent-pi/dist/agent-preset-projection.js +0 -29
  135. /package/{agent-hub → superd-hub}/dist/envelope.d.ts +0 -0
  136. /package/{agent-hub → superd-hub}/dist/envelope.js +0 -0
  137. /package/{agent-hub → superd-hub}/dist/ownership.d.ts +0 -0
  138. /package/{agent-hub → superd-hub}/dist/ownership.js +0 -0
  139. /package/{agent-hub → superd-hub}/dist/roster.js +0 -0
  140. /package/{agent-hub → superd-hub}/dist/rpc.d.ts +0 -0
  141. /package/{agent-hub → superd-hub}/dist/targets.d.ts +0 -0
  142. /package/{agent-hub → superd-hub}/dist/targets.js +0 -0
@@ -1,171 +1,32 @@
1
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
- var useValue = arguments.length > 2;
3
- for (var i = 0; i < initializers.length; i++) {
4
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
- }
6
- return useValue ? value : void 0;
7
- };
8
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
- var _, done = false;
14
- for (var i = decorators.length - 1; i >= 0; i--) {
15
- var context = {};
16
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
- if (kind === "accessor") {
21
- if (result === void 0) continue;
22
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
- if (_ = accept(result.get)) descriptor.get = _;
24
- if (_ = accept(result.set)) descriptor.set = _;
25
- if (_ = accept(result.init)) initializers.unshift(_);
26
- }
27
- else if (_ = accept(result)) {
28
- if (kind === "field") initializers.unshift(_);
29
- else descriptor[key] = _;
30
- }
31
- }
32
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
- done = true;
34
- };
35
- import { Remote, RemoteError, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
36
- const HERMES_PRESET = Object.freeze({
37
- id: "hermes",
38
- trust: "system",
39
- path: "",
1
+ export const HERMES_PRESET_ID = "hermes";
2
+ /** The single fixed Hermes preset: mounting it composes nothing. */
3
+ export const HERMES_PRESET = Object.freeze({
4
+ id: HERMES_PRESET_ID,
40
5
  name: "Hermes",
41
6
  description: "Hermes agent via the agent-hermes adapter",
7
+ plugins: Object.freeze([]),
42
8
  });
43
- const COMPOSITION_TEXT = [
44
- "# Hermes (fixed roster)",
45
- "",
46
- "This deployment runs exactly one agent mode: the Hermes provider bridges Dash",
47
- "sessions to a native Hermes agent over the TUI gateway JSON-RPC. There is no",
48
- "per-session plugin composition to configure, so this preset mounts nothing.",
49
- "",
50
- "rows: []",
51
- "",
52
- ].join("\n");
53
- /** The standing scope key every `hermes` session reads presenters through. */
54
- const STANDING_KEY = {};
55
- let SingleHermesPresetRoster = (() => {
56
- let _classSuper = TypertRemoteService;
57
- let _instanceExtraInitializers = [];
58
- let _remoteList_decorators;
59
- let _remoteRead_decorators;
60
- let _remoteCopy_decorators;
61
- let _remoteDelete_decorators;
62
- let _remoteSelect_decorators;
63
- return class SingleHermesPresetRoster extends _classSuper {
64
- static {
65
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
66
- _remoteList_decorators = [Remote("list")];
67
- _remoteRead_decorators = [Remote("read")];
68
- _remoteCopy_decorators = [Remote("copy")];
69
- _remoteDelete_decorators = [Remote("deletePreset")];
70
- _remoteSelect_decorators = [Remote("select")];
71
- __esDecorate(this, null, _remoteList_decorators, { kind: "method", name: "remoteList", static: false, private: false, access: { has: obj => "remoteList" in obj, get: obj => obj.remoteList }, metadata: _metadata }, null, _instanceExtraInitializers);
72
- __esDecorate(this, null, _remoteRead_decorators, { kind: "method", name: "remoteRead", static: false, private: false, access: { has: obj => "remoteRead" in obj, get: obj => obj.remoteRead }, metadata: _metadata }, null, _instanceExtraInitializers);
73
- __esDecorate(this, null, _remoteCopy_decorators, { kind: "method", name: "remoteCopy", static: false, private: false, access: { has: obj => "remoteCopy" in obj, get: obj => obj.remoteCopy }, metadata: _metadata }, null, _instanceExtraInitializers);
74
- __esDecorate(this, null, _remoteDelete_decorators, { kind: "method", name: "remoteDelete", static: false, private: false, access: { has: obj => "remoteDelete" in obj, get: obj => obj.remoteDelete }, metadata: _metadata }, null, _instanceExtraInitializers);
75
- __esDecorate(this, null, _remoteSelect_decorators, { kind: "method", name: "remoteSelect", static: false, private: false, access: { has: obj => "remoteSelect" in obj, get: obj => obj.remoteSelect }, metadata: _metadata }, null, _instanceExtraInitializers);
76
- if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
77
- }
78
- constructor(ctx) {
79
- super(ctx, "agentPresets");
80
- __runInitializers(this, _instanceExtraInitializers);
81
- }
82
- get defaultId() {
83
- return HERMES_PRESET.id;
84
- }
85
- get roots() {
86
- return [];
87
- }
88
- get authorable() {
89
- return false;
90
- }
91
- async list() {
92
- return [HERMES_PRESET];
93
- }
94
- async resolve(id) {
95
- if (id === undefined || id === HERMES_PRESET.id)
96
- return HERMES_PRESET;
97
- throw new RemoteError("agent-preset/not-found", `agent-presets: preset "${id}" not found (available: hermes)`, { agentPreset: id, available: [HERMES_PRESET.id] });
98
- }
99
- async mount(_agentCtx, id) {
100
- return this.resolve(id);
101
- }
102
- async recompose(_agentCtx, id) {
103
- return this.resolve(id);
104
- }
105
- async read(id) {
106
- await this.resolve(id);
107
- return COMPOSITION_TEXT;
108
- }
109
- // ── Remote RPC surface (alpha: agentPresets routes come from @Remote) ────
110
- // The stock dsh-host-apiproxy mapped cordis methods to routes; alpha serves
111
- // them from @Remote decorators on a TypertRemoteService. A plain Service
112
- // registers no routes, which is why Settings → Agent Preset 404'd.
113
- async remoteList() {
114
- if (process.env.HERMES_TRACE === "1")
115
- process.stderr.write("[hermes-roster] remoteList INVOKED\n");
116
- return {
117
- presets: [
118
- {
119
- id: HERMES_PRESET.id,
120
- trust: HERMES_PRESET.trust,
121
- isDefault: true,
122
- name: HERMES_PRESET.name,
123
- description: HERMES_PRESET.description,
124
- },
125
- ],
126
- authorable: this.authorable,
127
- };
128
- }
129
- async remoteRead(agentPreset) {
130
- const preset = await this.resolve(agentPreset);
131
- return {
132
- agentPreset: preset.id,
133
- trust: preset.trust,
134
- content: await this.read(preset.id),
135
- name: preset.name,
136
- description: preset.description,
137
- };
138
- }
139
- async remoteCopy(from, id, name) {
140
- await this.copy(from, id, name);
141
- }
142
- async remoteDelete(id) {
143
- await this.remove(id);
144
- }
145
- /** Fixed roster: one preset, so selecting it is a no-op ack; anything else is unknown. */
146
- async remoteSelect(agent, agentPreset) {
147
- const preset = await this.resolve(agentPreset);
148
- return preset.id;
149
- }
150
- async copy(_from, id, _name) {
151
- throw new RemoteError("agent-preset/read-only", `agent-presets: preset "${id}" cannot be written: the Hermes roster is fixed and ships exactly one preset`, { agentPreset: id, reason: "the Hermes roster is fixed and ships exactly one preset" });
152
- }
153
- async remove(id) {
154
- throw new RemoteError("agent-preset/read-only", `agent-presets: preset "${id}" cannot be written: the Hermes roster is fixed and ships exactly one preset`, { agentPreset: id, reason: "the Hermes roster is fixed and ships exactly one preset" });
155
- }
156
- serviceFor(_agent, _name) {
157
- return undefined;
158
- }
159
- composeFrom(_agentCtx, _parentCtx) {
160
- return undefined;
161
- }
162
- composedPreset(_agentCtx) {
163
- return HERMES_PRESET.id;
164
- }
165
- async standingKeyFor(id) {
166
- await this.resolve(id);
167
- return STANDING_KEY;
168
- }
169
- };
170
- })();
171
- export { SingleHermesPresetRoster };
9
+ /**
10
+ * Register the fixed preset into the host `AgentPresetRegistry` once the
11
+ * service is up. Registration failure keeps the roster row visible as
12
+ * `broken` inside the registry (upstream owns that lifecycle) — the adapter
13
+ * only owns the disposer.
14
+ */
15
+ export function registerHermesPreset(ctx) {
16
+ ctx.inject(["agentPresets"], (scoped) => {
17
+ let dispose;
18
+ let settled = false;
19
+ void scoped.agentPresets.register(HERMES_PRESET).then((unregister) => {
20
+ if (settled) {
21
+ void unregister();
22
+ }
23
+ else {
24
+ dispose = unregister;
25
+ }
26
+ });
27
+ ctx.effect(() => async () => {
28
+ settled = true;
29
+ await dispose?.();
30
+ }, "hermesAdapter.preset");
31
+ });
32
+ }
@@ -4,6 +4,7 @@ import { LlmAttemptId, ToolCallId, QUOTA_EXCEEDED_CODE, createAssistantMessage,
4
4
  import { createScope } from "@deepseek-ai/dsh-scope";
5
5
  import { GatewayRpcError, HERMES_SPAWN_ATTEMPTS } from "./hermes-client.js";
6
6
  import { approvalChoiceFromOutcome } from "./permission.js";
7
+ import { withSystemHead } from "../../superd-hub/dist/index.js";
7
8
  /**
8
9
  * v2 live assistant-stream publication for the Hermes bridge — the same frame
9
10
  * protocol the reference loop's AssistantStreamAttempt speaks (start marker,
@@ -58,22 +59,27 @@ const trace = (...parts) => {
58
59
  export function convertContent(blocks) {
59
60
  if (blocks === undefined)
60
61
  return [];
61
- const result = [];
62
+ // 0.1.6 renders blocks in ARRAY order; the native stream emits reasoning
63
+ // BEFORE text, so gateway messages that trail their thinking blocks must be
64
+ // hoisted — otherwise the WebUI draws "Thought for a while" AFTER the
65
+ // response (2026-09-23 evidence).
66
+ const reasoning = [];
67
+ const rest = [];
62
68
  for (const block of blocks) {
63
69
  switch (block.type) {
64
70
  case "text":
65
71
  if (typeof block.text === "string")
66
- result.push({ type: "text", text: block.text });
72
+ rest.push({ type: "text", text: block.text });
67
73
  break;
68
74
  case "thinking":
69
75
  if (typeof block.thinking === "string")
70
- result.push({ type: "reasoning", text: block.thinking });
76
+ reasoning.push({ type: "reasoning", text: block.thinking });
71
77
  break;
72
78
  case "toolCall": {
73
79
  const id = typeof block.id === "string" ? block.id : "";
74
80
  const name = typeof block.name === "string" ? block.name : "";
75
81
  const args = typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {});
76
- result.push({ type: "tool-call", id: ToolCallId(id), name, arguments: args });
82
+ rest.push({ type: "tool-call", id: ToolCallId(id), name, arguments: args });
77
83
  break;
78
84
  }
79
85
  default:
@@ -81,7 +87,7 @@ export function convertContent(blocks) {
81
87
  break;
82
88
  }
83
89
  }
84
- return result;
90
+ return [...reasoning, ...rest];
85
91
  }
86
92
  /**
87
93
  * Classify the wire's `stopReason: "error"` assistant message into a Dash
@@ -191,8 +197,13 @@ function userMessageText(message) {
191
197
  * work) and echo it into history as a fake user prompt. Detect and drop it.
192
198
  */
193
199
  function isApprovalNarration(message) {
194
- const source = message.source;
195
- return source.kind === "plugin" && source.plugin === "user-approval";
200
+ // 0.1.7: the shared `plugin` source kind is gone (MessageSourceMap is
201
+ // merge-extensible; each producer declares its own kind) — user-approval
202
+ // now carries the dedicated `user-approval` kind.
203
+ // Type-only: loads the `user-approval` MessageSourceMap augmentation
204
+ // (0.1.7: producer-owned source kinds; the shared `plugin` kind is gone).
205
+ // noinspection JSValidateTypes
206
+ return message.source.kind === "user-approval";
196
207
  }
197
208
  const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
198
209
  /**
@@ -264,6 +275,8 @@ export class HermesAgent {
264
275
  #pendingFailure = null;
265
276
  /** Last title mirrored into `session/title` (dedupes repeated gateway events). */
266
277
  #mirroredTitle = null;
278
+ /** Seq of the session's first user/message (v4 title citations derive from it). */
279
+ #titleSourceSeq;
267
280
  /** Live v2 assistant-stream publication for the in-flight wire message. */
268
281
  #streamBridge;
269
282
  #assistantAttemptCounter = 0;
@@ -299,7 +312,7 @@ export class HermesAgent {
299
312
  this.#loopCtx = loopCtx;
300
313
  this.id = id;
301
314
  this.options = options;
302
- this.session = session;
315
+ this.session = withSystemHead(session, () => createSystemMessage(""));
303
316
  this.#client = client;
304
317
  this.#onIdleExit = onIdleExit;
305
318
  this.#runtimeInfo = runtimeInfo;
@@ -482,7 +495,7 @@ export class HermesAgent {
482
495
  return;
483
496
  this.session.append("turn/start", { turn: this.#dashTurn });
484
497
  await this.#emitRequestContext();
485
- this.session.append("user/message", message, { surfaceOp: "append" });
498
+ this.#titleSourceSeq ??= this.session.append("user/message", message, { surfaceOp: "append" }).seq;
486
499
  this.#armTurnDeadline();
487
500
  void this.#client
488
501
  .prompt(userMessageText(message))
@@ -555,20 +568,19 @@ export class HermesAgent {
555
568
  if (this.#runtimeInfo === undefined || !this.#turnOpen)
556
569
  return;
557
570
  this.#commitStepStart();
558
- if (this.#step === 0)
571
+ // commitStepStart re-enters #emitSystemMessage (step open → stamp); the
572
+ // outer call must re-check the one-shot flag after the recursion.
573
+ if (this.#systemMessageDone)
559
574
  return;
560
- if (this.session.snapshotEvents().some((event) => event.type === "system/message")) {
561
- this.#systemMessageDone = true;
575
+ if (this.#step === 0)
562
576
  return;
563
- }
564
577
  const text = this.#runtimeInfo.systemPrompt();
565
578
  if (text === undefined || text.trim() === "")
566
579
  return;
567
- this.session.append("system/message", {
568
- turn: this.#dashTurn,
569
- step: this.#step,
570
- message: createSystemMessage(text, "aw.agent-adapter-hermes"),
571
- }, { surfaceOp: "append" });
580
+ // v4 protected-head posture: replace the placeholder head (stamped before
581
+ // the first user message); an append here would corrupt the log for the
582
+ // 0.1.7 reader ("system/message requires a protected first surface head").
583
+ this.session.stampSystemPrompt(this.#dashTurn, this.#step, createSystemMessage(text));
572
584
  this.#systemMessageDone = true;
573
585
  const title = this.#runtimeInfo.sessionTitle();
574
586
  if (title !== undefined && title !== "")
@@ -941,9 +953,11 @@ export class HermesAgent {
941
953
  return;
942
954
  this.#mirroredTitle = name;
943
955
  try {
956
+ if (this.#titleSourceSeq === undefined)
957
+ return; // v4: a provider title cites the user message it titles
944
958
  this.session.append("session/title", {
945
959
  title: name,
946
- messageSeqs: [],
960
+ messageSeqs: [this.#titleSourceSeq],
947
961
  source: { kind: "provider", provider: "hermes" },
948
962
  });
949
963
  trace(`session/title ← hermes: "${name}"`);
@@ -109,9 +109,9 @@ let gatewayFactory = defaultGatewayFactory;
109
109
  export function setGatewayFactory(factory) {
110
110
  gatewayFactory = factory ?? defaultGatewayFactory;
111
111
  }
112
- /** Brief-pinned order: AW_HERMES_PYTHON → <root>/venv/bin/python → <root>/.venv/bin/python → PATH python3. */
112
+ /** Brief-pinned order: SUPERD_HERMES_PYTHON → <root>/venv/bin/python → <root>/.venv/bin/python → PATH python3. */
113
113
  export function resolveHermesPython(root) {
114
- const configured = process.env.AW_HERMES_PYTHON?.trim();
114
+ const configured = process.env.SUPERD_HERMES_PYTHON?.trim();
115
115
  if (configured)
116
116
  return configured;
117
117
  for (const p of [resolve(root, "venv/bin/python"), resolve(root, ".venv/bin/python")]) {
@@ -120,9 +120,9 @@ export function resolveHermesPython(root) {
120
120
  }
121
121
  return "python3";
122
122
  }
123
- /** Hermes root: AW_HERMES_ROOT → ~/.hermes/hermes-agent (native home — never redirected). */
123
+ /** Hermes root: SUPERD_HERMES_ROOT → ~/.hermes/hermes-agent (native home — never redirected). */
124
124
  export function resolveHermesRoot() {
125
- return process.env.AW_HERMES_ROOT?.trim() || resolve(homedir(), ".hermes/hermes-agent");
125
+ return process.env.SUPERD_HERMES_ROOT?.trim() || resolve(homedir(), ".hermes/hermes-agent");
126
126
  }
127
127
  function asRecord(value) {
128
128
  if (value === null || typeof value !== "object" || Array.isArray(value))
@@ -946,7 +946,7 @@ export class HermesGatewayClient {
946
946
  return this.#stderrLines.slice(-20).join("\n");
947
947
  }
948
948
  #trace(line) {
949
- if (process.env.AW_HERMES_TRACE === "1") {
949
+ if (process.env.SUPERD_HERMES_TRACE === "1") {
950
950
  process.stderr.write(`[hermes-client] ${line}\n`);
951
951
  }
952
952
  }
@@ -19,15 +19,7 @@
19
19
  * degrades to "unknown session" rather than breaking every operation.
20
20
  */
21
21
  import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
22
- import { homedir } from "node:os";
23
22
  import { basename, dirname, join, resolve } from "node:path";
24
- /** Prod homes that must never be resolved into (repo red line). */
25
- const PROD_HOMES = [join(homedir(), ".dsh"), join(homedir(), ".superd")];
26
- function assertNotProdHome(path, label) {
27
- if (PROD_HOMES.includes(path) || PROD_HOMES.some((p) => path.startsWith(`${p}/`))) {
28
- throw new Error(`hermes-store: refusing prod home as ${label}: ${path}`);
29
- }
30
- }
31
23
  /**
32
24
  * The adapter's DSH-side state dir — `<dshHome>/agents/hermes`. This is DSH-SIDE
33
25
  * adapter state (the identity map), NOT hermes data: hermes keeps its native
@@ -40,13 +32,12 @@ function assertNotProdHome(path, label) {
40
32
  * - Form-B: the boot-provided home is ALREADY the world home
41
33
  * (`<root>/agents/hermes`) — passed through as-is, never double-nested.
42
34
  * Precedence: explicit home (boot-provided `dshHomePath`), then `$DSH_HOME`,
43
- * then the line's historical test-home default. Prod-guarded.
35
+ * then the line's historical test-home default.
44
36
  */
45
37
  export function resolveHermesAppDir(home) {
46
- const base = resolve(home ?? process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw"));
38
+ const base = resolve(home ?? process.env.DSH_HOME ?? join(process.cwd(), ".tests", "superd"));
47
39
  // Form-B world home is already `<root>/agents/hermes` — never double-nest.
48
40
  const dir = basename(base) === "hermes" && basename(dirname(base)) === "agents" ? base : join(base, "agents", "hermes");
49
- assertNotProdHome(dir, "hermes app dir");
50
41
  return dir;
51
42
  }
52
43
  /** The map file's path inside the adapter's DSH-side app dir. */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * agent-hermes provider — Hermes provider plugin for DeepSeek Harness
3
- * (Agent Worlds AW-H, TUI gateway line).
3
+ * (Super D, TUI gateway line).
4
4
  *
5
5
  * Replaces the built-in agent loop with an `AgentFactory` that drives a
6
6
  * `HermesGatewayClient` (one spawned `python -m tui_gateway.entry` child per
@@ -24,13 +24,12 @@
24
24
  import { realpathSync, statSync } from "node:fs";
25
25
  import { join } from "node:path";
26
26
  import { Service } from "@deepseek-ai/cordis";
27
- import { emitAgentEvent, installModelSelection } from "@deepseek-ai/dsh-agent";
27
+ import { installModelSelection } from "@deepseek-ai/dsh-agent";
28
28
  import { SessionLogOffset, SessionPreparation, interruptedTurnClosers, } from "@deepseek-ai/dsh-session";
29
29
  import { HermesGatewayClient, HERMES_SPAWN_GRACE_MS } from "./hermes-client.js";
30
30
  import { HermesAgent } from "./agent.js";
31
31
  import { HermesLlmAdapter, HERMES_PROVIDER_ID } from "./adapter.js";
32
- import { SingleHermesPresetRoster } from "./agent-preset-hermes.js";
33
- import { hermesAgentPresetProjection } from "./agent-preset-projection.js";
32
+ import { registerHermesPreset } from "./agent-preset-hermes.js";
34
33
  import { sessionRecord, upsertSession } from "./hermes-store.js";
35
34
  import { hermesProviderSlugs, readHermesModelCatalog } from "./models.js";
36
35
  import { envApprovalMode, defaultPermissionPreset, presetFromEvents } from "./permission.js";
@@ -96,11 +95,12 @@ export class HermesProvider extends Service {
96
95
  this.#registerDefaultModel();
97
96
  // The roster must be visible to the API gateway's root-level remote
98
97
  // enumeration; register it on this plugin's own (top-level) fiber.
99
- new SingleHermesPresetRoster(ctx);
100
- // Drive the `agentPreset` session projection ourselves.
101
- ctx.inject(["sessionProjections"], (scoped) => {
102
- scoped.sessionProjections.register(hermesAgentPresetProjection);
103
- });
98
+ // 0.1.7: roster/selection/document RPC + the `agentPreset` session
99
+ // projection all live in the host AgentPresetRegistry (mounted by the
100
+ // dsh-web-app bundle's `agent-preset-registry` row; the adapter patch
101
+ // pins its `default` to the Hermes preset). The adapter only registers
102
+ // its one fixed preset into the registry.
103
+ registerHermesPreset(ctx);
104
104
  }
105
105
  /**
106
106
  * The factory owns its sessions' route (user directive 2026-09-15,
@@ -217,7 +217,7 @@ export class HermesProvider extends Service {
217
217
  if (typeof resolved === "string" && resolved !== "")
218
218
  return resolved;
219
219
  }
220
- return process.env.DSH_HOME ?? join(process.cwd(), ".tests", "aw");
220
+ return process.env.DSH_HOME ?? join(process.cwd(), ".tests", "superd");
221
221
  }
222
222
  /**
223
223
  * Push the gateway's default model into the world's `agentDefaultModel`
@@ -499,8 +499,9 @@ async function setupAndPublish(loopCtx, ownerCtx, id, agentOptions, setup, sessi
499
499
  agent.ctx.sessions.announce(session);
500
500
  }
501
501
  detachAgent = loopCtx.agents.enter(agent, parentAgent);
502
- loopCtx.agents.announce(agent);
503
- emitAgentEvent(loopCtx, agent, "agent/session-start", { source });
502
+ // 0.1.6: announce(agent, source) is required, async, and emits agent/created
503
+ // itself — the manual agent/session-start emission is gone upstream.
504
+ await loopCtx.agents.announce(agent, source);
504
505
  let disposed = false;
505
506
  let unfollowOwner;
506
507
  const dispose = async () => {
@@ -1,28 +1,30 @@
1
1
  /**
2
- * aw.agent-adapter-hermes — the Hermes adapter's WORLD plugin (spec S2):
2
+ * agent-hermes — the Hermes adapter's WORLD plugin (spec S2):
3
3
  * activation IS roster membership.
4
4
  *
5
- * AW-B URL scheme (DL1–DL5), mirroring `@pgmi-builds/agent-adapter-omp/world`
6
- * and `@pgmi-builds/agent-adapter-codex/world` so the hub sees every foreign
7
- * runtime through one shape: the world is spawned as a sibling ROOT context
8
- * with NO listener (`worldMountPatches`) and mounts itself under `/hermes`
9
- * through the hub —
5
+ * AW-B data-plane shape (DL1–DL5 → path-separation T-D), mirroring
6
+ * `@pgmi-builds/agent-omp/world` and `@pgmi-builds/agent-codex/world` so the
7
+ * hub sees every foreign runtime through one shape: the world is spawned as a
8
+ * sibling ROOT context with NO listener and NO webui composition
9
+ * (`worldMountPatches`) — a pure data plane behind the hub's `/hub` family —
10
10
  *
11
- * 1. ctx0 publishes the host mount (real webServer instance) before spawn;
12
- * 2. the world's entry row provides the virtual `webServer` in the world
13
- * root, translating every route its plugins declare into `/hermes+path`;
14
- * 3. the hub's carrier answers `/hermes/api` + `/hermes/api/remote.mux` in
15
- * ctx0's auth domain and dispatches into this world's gateway instance.
11
+ * 1. ctx0 publishes the host mount record (the world's addressability
12
+ * entry — no webServer, no fence: those legs retired with the world
13
+ * pages) before spawn;
14
+ * 2. the world's entry row provides the virtual `webServer` (a silent
15
+ * sink) plus the neutral `webRuntime` facts its connection row injects;
16
+ * 3. the hub's `/hub` family answers `?agent=hermes` traffic in ctx0's auth
17
+ * domain and dispatches into this world's gateway instance (the
18
+ * per-label `/<label>/api` + `/<label>/api/remote.mux` mounts retired
19
+ * in T-C, `mountWorld` deleted in T-D).
16
20
  */
17
21
  import { mkdirSync } from 'node:fs';
18
22
  import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
19
23
  import { join } from 'node:path';
20
- import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, mountWorld, worldMountPatches, provisionWorldProfile, } from '../../agent-hub/dist/index.js';
21
- export const name = 'aw.agent-adapter-hermes';
24
+ import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../superd-hub/dist/index.js';
25
+ export const name = 'agent-hermes';
22
26
  /** Runtime key — also the mount label. */
23
27
  const KEY = 'hermes';
24
- const ANCHOR = process.env.SUPERD_DSH_ANCHOR
25
- ?? '/home/u1/.local/lib/node_modules/@deepseek-ai/dsh/package.json';
26
28
  export function apply(ctx) {
27
29
  registerAgent({ key: KEY, label: 'Hermes', ready: false });
28
30
  // Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
@@ -39,57 +41,34 @@ export function apply(ctx) {
39
41
  const worldHome = join(root, 'agents', KEY);
40
42
  mkdirSync(join(worldHome, 'profiles'), { recursive: true });
41
43
  // Publish story: a foreign install has no line bootstrap, so the nested
42
- // profile + @pgmi-builds links are provisioned HERE (idempotent; dev lines
43
- // keep parity — smoke.mjs wrote the same layout, and AW_BARE_BASE still
44
- // overrides the resolved base).
45
- const bareBase = provisionWorldProfile({
44
+ // profile + @pgmi-builds links are provisioned HERE (idempotent).
45
+ provisionWorldProfile({
46
46
  key: KEY,
47
- adapterPkg: '@pgmi-builds/agent-adapter-hermes',
47
+ adapterPkg: '@pgmi-builds/agent-hermes',
48
48
  worldHome,
49
49
  });
50
50
  const world = (async () => {
51
- // Wait for ctx0's listening stack: the mount needs the real webServer and
52
- // the browser-trust fence from the live connection service.
53
- const host = await new Promise((resolve) => {
54
- ctx.inject(['webServer', 'connection'], (hostCtx) => { resolve(hostCtx); });
55
- });
56
- const real = host['webServer'];
57
- const connection = host['connection'];
58
- const dropHostMount = registerHostMount({
59
- key: KEY,
60
- labelPath: `/${KEY}`,
61
- real,
62
- // ctx0's index gate, applied by the mount to this world's pages and assets:
63
- // the world is reached in-ctx and owns no listener, so ctx0 decides auth.
64
- authorize: (req, res) => connection.authorizeIndex(req, res),
65
- });
51
+ // T-D: no ctx0 listening-stack wait — the mount record is addressability
52
+ // only and the /hub family wires its own gate in ctx0 (gateway.ts).
53
+ const dropHostMount = registerHostMount({ key: KEY, labelPath: `/${KEY}` });
66
54
  const ctxW = await spawnWorld({
67
- appName: `aw-${KEY}`,
55
+ appName: `superd-${KEY}`,
68
56
  profileName: 'web',
69
- installAnchor: ANCHOR,
57
+ installAnchor: resolveInstallAnchor(ctx), // lazy: never at module scope — import must stay side-effect-free
70
58
  home: worldHome,
71
59
  dataHome: worldHome,
72
- // Adapter-local bundle names resolve from the profile's own
73
- // node_modules (heal owns @deepseek-ai there; @pgmi-builds links are
74
- // provisioned by provisionWorldProfile above, or by the line bootstrap
75
- // when the adapter package was not resolvable — env wins over both).
76
- bareModuleBaseUrl: process.env.AW_BARE_BASE ?? bareBase ?? undefined,
60
+ // The host's live table carries this world: spawnWorld republishes a
61
+ // widened successor before boot imports anything (spec §2.1), and
62
+ // @pgmi-builds rows resolve from the profile-local links written above.
63
+ host: ctx,
77
64
  extraPatches: worldMountPatches(KEY),
78
65
  });
79
66
  const gateway = ctxW.get('typertGateway');
80
67
  registerForeignTarget({ key: KEY, gateway });
81
- const mounted = mountWorld({
82
- real,
83
- label: KEY,
84
- gateway,
85
- requestRejection: (request) => connection
86
- .requestRejection(request),
87
- });
88
68
  setReady(KEY, true);
89
69
  ctx.effect?.(() => () => {
90
- mounted.dispose();
91
70
  dropHostMount();
92
- }, `aw.agent-adapter-${KEY}: mount`);
71
+ }, `agent-${KEY}: mount`);
93
72
  return ctxW;
94
73
  })().catch((cause) => {
95
74
  // A failed world degrades to a not-ready roster row; a rejected provided
@@ -97,5 +76,5 @@ export function apply(ctx) {
97
76
  console.error(`[super-dsh] ${KEY} world failed:`, cause);
98
77
  return null;
99
78
  });
100
- ctx.provide(`aw.world.${KEY}`, world);
79
+ ctx.provide(`superd.world.${KEY}`, world);
101
80
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "name": "@pgmi-builds/agent-adapter-hermes",
2
+ "name": "@pgmi-builds/agent-hermes",
3
3
  "version": "0.1.0",
4
- "description": "Hermes provider for DeepSeek Harness (dsh) — an AgentFactory that embeds Nous Research Hermes Agent via the TUI gateway JSON-RPC (python -m tui_gateway.entry) and bridges its session surface into Dash Agent/Session contracts (Agent Worlds AW-H).",
4
+ "description": "Hermes provider for DeepSeek Harness (dsh) — an AgentFactory that embeds Nous Research Hermes Agent via the TUI gateway JSON-RPC (python -m tui_gateway.entry) and bridges its session surface into Dash Agent/Session contracts .",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./dist/index.js",
@@ -22,18 +22,18 @@
22
22
  "test": "node --test test/*.test.mjs"
23
23
  },
24
24
  "dependencies": {
25
- "@pgmi-builds/agent-hub": "file:../agent-hub",
26
- "zod": "3.25.76"
25
+ "zod": "4.4.3"
27
26
  },
28
27
  "peerDependencies": {
29
28
  "@deepseek-ai/cordis": "^4.0.1",
30
- "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
31
- "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
32
- "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
33
- "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
34
- "@deepseek-ai/dsh-session": "0.1.5-rc.2",
35
- "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
36
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2"
29
+ "@deepseek-ai/dsh-agent": ">=0.1.5-0 <0.3.0-0",
30
+ "@deepseek-ai/dsh-agent-presets": ">=0.1.5-0 <0.3.0-0",
31
+ "@deepseek-ai/dsh-llm": ">=0.1.5-0 <0.3.0-0",
32
+ "@deepseek-ai/dsh-scope": ">=0.1.5-0 <0.3.0-0",
33
+ "@deepseek-ai/dsh-session": ">=0.1.5-0 <0.3.0-0",
34
+ "@deepseek-ai/dsh-session-persistence": ">=0.1.5-0 <0.3.0-0",
35
+ "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-0 <0.3.0-0",
36
+ "@pgmi-builds/superd-hub": "*"
37
37
  },
38
38
  "peerDependenciesMeta": {
39
39
  "@deepseek-ai/cordis": {
@@ -59,6 +59,9 @@
59
59
  },
60
60
  "@deepseek-ai/dsh-typert-protocol": {
61
61
  "optional": true
62
+ },
63
+ "@pgmi-builds/superd-hub": {
64
+ "optional": true
62
65
  }
63
66
  },
64
67
  "devDependencies": {