super-dsh 0.1.6 → 0.1.10-e
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/README.md +25 -3
- package/agent-agy/cordis.patch.yml +7 -4
- package/agent-agy/dist/agent.d.ts +12 -11
- package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
- package/agent-agy/dist/agy-auth-gateway.js +233 -0
- package/agent-agy/dist/agy-auth.d.ts +153 -0
- package/agent-agy/dist/agy-auth.js +179 -0
- package/agent-agy/dist/agy-cli-client.d.ts +39 -9
- package/agent-agy/dist/agy-cli-client.js +82 -18
- package/agent-agy/dist/agy-store.d.ts +8 -0
- package/agent-agy/dist/index.d.ts +46 -16
- package/agent-agy/dist/index.js +82 -56
- package/agent-agy/dist/models.d.ts +70 -0
- package/agent-agy/dist/models.js +102 -3
- package/agent-agy/package.json +7 -5
- package/agent-agy-sdk/cordis.patch.yml +58 -0
- package/agent-agy-sdk/dist/adapter.d.ts +15 -0
- package/agent-agy-sdk/dist/adapter.js +42 -0
- package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
- package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
- package/agent-agy-sdk/dist/agent.d.ts +138 -0
- package/agent-agy-sdk/dist/agent.js +494 -0
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
- package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
- package/agent-agy-sdk/dist/agy-sessions.js +107 -0
- package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
- package/agent-agy-sdk/dist/agy-store.js +83 -0
- package/agent-agy-sdk/dist/inbox.d.ts +26 -0
- package/agent-agy-sdk/dist/inbox.js +53 -0
- package/agent-agy-sdk/dist/index.d.ts +93 -0
- package/agent-agy-sdk/dist/index.js +476 -0
- package/agent-agy-sdk/dist/models.d.ts +41 -0
- package/agent-agy-sdk/dist/models.js +74 -0
- package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
- package/agent-agy-sdk/dist/sdk-venv.js +173 -0
- package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-agy-sdk/dist/world-plugin.js +82 -0
- package/agent-agy-sdk/package.json +64 -0
- package/agent-claude/dist/adapter.js +106 -31
- package/agent-claude/dist/agent.js +154 -17
- package/agent-claude/dist/claude-client.js +84 -43
- package/agent-claude/dist/claude-launch.js +101 -0
- package/agent-claude/dist/claude-native-config.js +169 -0
- package/agent-claude/dist/claude-provider-gateway.js +340 -0
- package/agent-claude/dist/claude-providers.js +391 -0
- package/agent-claude/dist/claude-route.js +152 -0
- package/agent-claude/dist/index.js +214 -37
- package/agent-claude/dist/models.js +14 -0
- package/agent-claude/dist/sdk-runtime.js +320 -0
- package/agent-claude/package.json +6 -4
- package/agent-codex/README.md +141 -36
- package/agent-codex/cordis.patch.yml +14 -10
- package/agent-codex/dist/adapter.js +64 -28
- package/agent-codex/dist/agent.js +255 -81
- package/agent-codex/dist/app-server-approvals.js +165 -0
- package/agent-codex/dist/app-server-client.js +723 -0
- package/agent-codex/dist/app-server-events.js +432 -0
- package/agent-codex/dist/app-server-protocol.js +95 -0
- package/agent-codex/dist/app-server-wire.js +299 -0
- package/agent-codex/dist/codex-launch.js +78 -0
- package/agent-codex/dist/codex-native-config.js +392 -0
- package/agent-codex/dist/codex-provider-gateway.js +402 -0
- package/agent-codex/dist/codex-providers.js +376 -0
- package/agent-codex/dist/codex-route.js +86 -0
- package/agent-codex/dist/index.js +256 -115
- package/agent-codex/dist/permission.js +75 -1
- package/agent-codex/package.json +1 -2
- package/agent-codex-sdk/README.md +79 -0
- package/agent-codex-sdk/cordis.patch.yml +81 -0
- package/agent-codex-sdk/dist/adapter.js +91 -0
- package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
- package/agent-codex-sdk/dist/agent.js +1085 -0
- package/agent-codex-sdk/dist/codex-native-config.js +392 -0
- package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
- package/agent-codex-sdk/dist/codex-providers.js +376 -0
- package/agent-codex-sdk/dist/codex-route.js +86 -0
- package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
- package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
- package/agent-codex-sdk/dist/codex-store.js +180 -0
- package/agent-codex-sdk/dist/inbox.js +53 -0
- package/agent-codex-sdk/dist/index.js +739 -0
- package/agent-codex-sdk/dist/permission.js +71 -0
- package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
- package/agent-codex-sdk/dist/session-map.js +167 -0
- package/agent-codex-sdk/dist/world-plugin.js +93 -0
- package/agent-codex-sdk/package.json +79 -0
- package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
- package/agent-omp/README.md +72 -55
- package/agent-omp/dist/agent.js +36 -11
- package/agent-omp/dist/index.js +92 -52
- package/agent-omp/dist/lazy-rpc.js +11 -4
- package/agent-omp/dist/omp-cli.js +114 -97
- package/agent-omp/dist/omp-store.js +12 -4
- package/agent-omp/dist/permission.js +70 -5
- package/agent-omp/dist/rpc-client.js +409 -0
- package/agent-omp/dist/world-plugin.js +36 -3
- package/agent-omp/package.json +2 -6
- package/agent-omp-sdk/README.md +103 -0
- package/agent-omp-sdk/cordis.patch.yml +108 -0
- package/agent-omp-sdk/dist/adapter.d.ts +21 -0
- package/agent-omp-sdk/dist/adapter.js +36 -0
- package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
- package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
- package/agent-omp-sdk/dist/agent.d.ts +64 -0
- package/agent-omp-sdk/dist/agent.js +1178 -0
- package/agent-omp-sdk/dist/discovery.d.ts +57 -0
- package/agent-omp-sdk/dist/discovery.js +116 -0
- package/agent-omp-sdk/dist/inbox.d.ts +28 -0
- package/agent-omp-sdk/dist/inbox.js +53 -0
- package/agent-omp-sdk/dist/index.d.ts +60 -0
- package/agent-omp-sdk/dist/index.js +632 -0
- package/agent-omp-sdk/dist/knobs.d.ts +34 -0
- package/agent-omp-sdk/dist/knobs.js +50 -0
- package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
- package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
- package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
- package/agent-omp-sdk/dist/mobile-boot.js +38 -0
- package/agent-omp-sdk/dist/models.d.ts +39 -0
- package/agent-omp-sdk/dist/models.js +299 -0
- package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
- package/agent-omp-sdk/dist/omp-cli.js +164 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
- package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
- package/agent-omp-sdk/dist/omp-executable.js +30 -0
- package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
- package/agent-omp-sdk/dist/omp-store.js +526 -0
- package/agent-omp-sdk/dist/pairing.d.ts +7 -0
- package/agent-omp-sdk/dist/pairing.js +45 -0
- package/agent-omp-sdk/dist/permission.d.ts +138 -0
- package/agent-omp-sdk/dist/permission.js +161 -0
- package/agent-omp-sdk/dist/protocol.d.ts +189 -0
- package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
- package/agent-omp-sdk/dist/rpc-types.js +1 -0
- package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
- package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
- package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
- package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
- package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
- package/agent-omp-sdk/dist/sidecar-client.js +197 -0
- package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
- package/agent-omp-sdk/dist/store/adapter.js +47 -0
- package/agent-omp-sdk/dist/store/db.d.ts +70 -0
- package/agent-omp-sdk/dist/store/db.js +210 -0
- package/agent-omp-sdk/dist/store/index.d.ts +23 -0
- package/agent-omp-sdk/dist/store/index.js +59 -0
- package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
- package/agent-omp-sdk/dist/store/reconcile.js +51 -0
- package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
- package/agent-omp-sdk/dist/store/schema.js +40 -0
- package/agent-omp-sdk/dist/transport.d.ts +49 -0
- package/agent-omp-sdk/dist/transport.js +35 -0
- package/agent-omp-sdk/dist/world-home.d.ts +4 -0
- package/agent-omp-sdk/dist/world-home.js +23 -0
- package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-omp-sdk/dist/world-plugin.js +137 -0
- package/agent-omp-sdk/package.json +87 -0
- package/client/index.js +1883 -287
- package/cordis.patch.yml +80 -0
- package/package.json +23 -9
- package/superd-hub/dist/a2a-delivery.d.ts +189 -0
- package/superd-hub/dist/a2a-delivery.js +240 -0
- package/superd-hub/dist/a2a-host.d.ts +76 -0
- package/superd-hub/dist/a2a-host.js +145 -0
- package/superd-hub/dist/a2a-ingest.d.ts +31 -0
- package/superd-hub/dist/a2a-ingest.js +636 -0
- package/superd-hub/dist/a2a-log.d.ts +17 -0
- package/superd-hub/dist/a2a-log.js +42 -0
- package/superd-hub/dist/a2a-row.d.ts +65 -0
- package/superd-hub/dist/a2a-row.js +162 -0
- package/superd-hub/dist/a2a-service.d.ts +357 -0
- package/superd-hub/dist/a2a-service.js +980 -0
- package/superd-hub/dist/a2a-wire.d.ts +220 -0
- package/superd-hub/dist/a2a-wire.js +305 -0
- package/superd-hub/dist/agent-ids.d.ts +10 -0
- package/superd-hub/dist/agent-ids.js +68 -0
- package/superd-hub/dist/agent-roster.d.ts +29 -18
- package/superd-hub/dist/agent-roster.js +54 -15
- package/superd-hub/dist/agent-status.d.ts +119 -0
- package/superd-hub/dist/agent-status.js +386 -0
- package/superd-hub/dist/client/agent-settings.d.ts +210 -0
- package/superd-hub/dist/client/agent-settings.js +300 -0
- package/superd-hub/dist/client/mesh-api.d.ts +134 -0
- package/superd-hub/dist/client/mesh-api.js +219 -0
- package/superd-hub/dist/client/mesh-groups.d.ts +63 -0
- package/superd-hub/dist/client/mesh-groups.js +66 -0
- package/superd-hub/dist/client/roster.d.ts +48 -0
- package/superd-hub/dist/client/roster.js +102 -0
- package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
- package/superd-hub/dist/client/runtime-settings-api.js +137 -0
- package/superd-hub/dist/client/switch.d.ts +165 -0
- package/superd-hub/dist/client/switch.js +295 -0
- package/superd-hub/dist/exec-pty-channel.d.ts +58 -0
- package/superd-hub/dist/exec-pty-channel.js +162 -0
- package/superd-hub/dist/exec-pty-framing.d.ts +32 -0
- package/superd-hub/dist/exec-pty-framing.js +81 -0
- package/superd-hub/dist/exec-pty-rpc.d.ts +21 -0
- package/superd-hub/dist/exec-pty-rpc.js +128 -0
- package/superd-hub/dist/exec-pty-session.d.ts +76 -0
- package/superd-hub/dist/exec-pty-session.js +234 -0
- package/superd-hub/dist/exec.d.ts +56 -0
- package/superd-hub/dist/exec.js +225 -0
- package/superd-hub/dist/gateway.d.ts +39 -2
- package/superd-hub/dist/gateway.js +62 -3
- package/superd-hub/dist/hub-tool.d.ts +174 -0
- package/superd-hub/dist/hub-tool.js +464 -0
- package/superd-hub/dist/index.d.ts +15 -1
- package/superd-hub/dist/index.js +16 -0
- package/superd-hub/dist/machines.d.ts +45 -0
- package/superd-hub/dist/machines.js +125 -0
- package/superd-hub/dist/mesh-federate.d.ts +138 -0
- package/superd-hub/dist/mesh-federate.js +223 -0
- package/superd-hub/dist/mesh-gateway.d.ts +67 -0
- package/superd-hub/dist/mesh-gateway.js +408 -0
- package/superd-hub/dist/mesh-link.d.ts +274 -0
- package/superd-hub/dist/mesh-link.js +441 -0
- package/superd-hub/dist/mesh-rpc.d.ts +123 -0
- package/superd-hub/dist/mesh-rpc.js +250 -0
- package/superd-hub/dist/mux-client.d.ts +71 -0
- package/superd-hub/dist/mux-client.js +281 -0
- package/superd-hub/dist/pack-version.d.ts +2 -0
- package/superd-hub/dist/pack-version.js +30 -0
- package/superd-hub/dist/roster.d.ts +6 -0
- package/superd-hub/dist/rpc.d.ts +18 -2
- package/superd-hub/dist/rpc.js +34 -4
- package/superd-hub/dist/spawn-world.js +3 -1
- package/superd-hub/dist/switch-core.d.ts +62 -25
- package/superd-hub/dist/switch-core.js +53 -30
- package/superd-hub/dist/system-head.d.ts +22 -12
- package/superd-hub/dist/system-head.js +100 -84
- package/superd-hub/dist/wire-endpoints.d.ts +264 -0
- package/superd-hub/dist/wire-endpoints.js +180 -0
- package/superd-hub/lib/client/index.js +1883 -287
- package/superd-hub/package.json +11 -2
- package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
- package/agent-agy/dist/agent-preset-projection.js +0 -33
- package/agent-claude/dist/agent-preset-projection.js +0 -30
- package/agent-codex/dist/agent-preset-projection.js +0 -37
- package/agent-codex/dist/app-home.js +0 -65
- package/agent-codex/dist/models.js +0 -152
- package/agent-codex/dist/spike.js +0 -46
- package/agent-hermes/dist/agent-preset-projection.js +0 -34
- package/agent-omp/dist/agent-preset-projection.js +0 -36
- package/agent-omp/dist/app-home.js +0 -86
- package/agent-omp/dist/sidecar-client.js +0 -195
- package/agent-pi/dist/agent-preset-projection.js +0 -29
- package/superd-hub/dist/client-shim.d.ts +0 -28
- package/superd-hub/dist/client-shim.js +0 -251
- package/superd-hub/dist/index-pass.d.ts +0 -22
- package/superd-hub/dist/index-pass.js +0 -47
- package/superd-hub/dist/labels.d.ts +0 -45
- package/superd-hub/dist/labels.js +0 -83
- /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
- /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
- /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
- /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
- /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
|
@@ -3,20 +3,28 @@
|
|
|
3
3
|
*
|
|
4
4
|
* OMP has no runtime approval control: `--approval-mode` is a launch flag, no
|
|
5
5
|
* RPC changes it mid-session. Dash's 3-way permission preset is therefore
|
|
6
|
-
* resolved
|
|
6
|
+
* resolved ONCE, at the spawn of that session's `omp --mode rpc` child, and
|
|
7
|
+
* mapped explicitly:
|
|
7
8
|
*
|
|
8
9
|
* danger-full-access → `--approval-mode yolo` (OMP's own native default)
|
|
9
10
|
* workspace-write → `--approval-mode write`
|
|
10
11
|
* read-only → `--approval-mode always-ask`
|
|
11
12
|
* no explicit preset → yolo (native default)
|
|
12
13
|
*
|
|
14
|
+
* "At the spawn" is load-bearing, not incidental. The Dash session is prepared
|
|
15
|
+
* (and `pinInitialPermission`-stamped) only AFTER the transport wrapper exists,
|
|
16
|
+
* and the new-chat permission pick arrives as a later `permission/preset` — the
|
|
17
|
+
* child materializes on the first prompt, so the launch flag must be read from
|
|
18
|
+
* the session at THAT moment, never frozen at create. See
|
|
19
|
+
* {@link resolveSpawnPermission}.
|
|
20
|
+
*
|
|
13
21
|
* `OMP_APPROVAL_MODE` (a valid mode) overrides the mapping — headless test
|
|
14
22
|
* runs pin the flag without composing a preset default.
|
|
15
23
|
*
|
|
16
|
-
* The preset is a Dash-side session fact OMP never records. It
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
24
|
+
* The preset is a Dash-side session fact OMP never records. It lives in the
|
|
25
|
+
* dsh session log (`permission/preset`, the event `/permission` writes) and is
|
|
26
|
+
* mirrored into the centralized index (`sessions.permission_preset`) at first
|
|
27
|
+
* spawn; the index row is only a fallback for logs predating the event.
|
|
20
28
|
*/
|
|
21
29
|
import { dirname, join } from "node:path";
|
|
22
30
|
/** The approval modes OMP actually implements (unknown modes degrade to yolo). */
|
|
@@ -71,6 +79,63 @@ export function presetFromEvents(events) {
|
|
|
71
79
|
}
|
|
72
80
|
return undefined;
|
|
73
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve a spawn's `--approval-mode` (and the preset to record for it) from
|
|
84
|
+
* the session's OWN log, evaluated at the moment the child materializes.
|
|
85
|
+
*
|
|
86
|
+
* Order of authority: the last valid `permission/preset` (= the user's pick in
|
|
87
|
+
* the new chat, or the draft's `pinInitialPermission` stamp) → `fallbackPreset`
|
|
88
|
+
* (the composition default for a create, the bridge-index row for a resume of a
|
|
89
|
+
* log that predates the event) → OMP's native default (`yolo`). An
|
|
90
|
+
* `OMP_APPROVAL_MODE` env override (headless runs) still wins over all of them.
|
|
91
|
+
*
|
|
92
|
+
* @param events - the live session's events (never a stale create-time read).
|
|
93
|
+
* @param fallbackPreset - used only when the log carries no valid preset.
|
|
94
|
+
* @param envMode - `envApprovalMode()`; undefined when unset or invalid.
|
|
95
|
+
* @returns the launch flag value plus the preset that produced it.
|
|
96
|
+
*/
|
|
97
|
+
export function resolveSpawnPermission(events, fallbackPreset, envMode) {
|
|
98
|
+
const preset = presetFromEvents(events) ?? (isPresetName(fallbackPreset) ? fallbackPreset : undefined);
|
|
99
|
+
return { approvalMode: envMode ?? ompApprovalMode(preset), preset };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Decide a `/permission` invocation for one OMP session.
|
|
103
|
+
*
|
|
104
|
+
* A permission pick can only become real at the child's launch, so the shadow
|
|
105
|
+
* accepts it exactly while no child exists (the new-chat draft, or a resumed
|
|
106
|
+
* session before its first prompt) and refuses it afterwards — appending a
|
|
107
|
+
* preset the running `omp` cannot honor would make the UI lie about the
|
|
108
|
+
* session's effective policy.
|
|
109
|
+
*
|
|
110
|
+
* @param input.rawInput - the preset name as typed (may be empty or padded).
|
|
111
|
+
* @param input.spawned - whether THIS session's `omp --mode rpc` child exists.
|
|
112
|
+
* @param input.names - the host's advertised preset names.
|
|
113
|
+
* @param input.current - the session's current preset (for the bare command).
|
|
114
|
+
* @returns the decision; the caller performs the write for `apply`.
|
|
115
|
+
*/
|
|
116
|
+
export function ompPermissionCommand(input) {
|
|
117
|
+
const available = input.names.join(", ");
|
|
118
|
+
const name = input.rawInput.trim();
|
|
119
|
+
if (name === "") {
|
|
120
|
+
return {
|
|
121
|
+
action: "settled",
|
|
122
|
+
result: { kind: "success", text: `current preset ${input.current} (available: ${available})` },
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (!input.names.includes(name)) {
|
|
126
|
+
return { action: "settled", result: { kind: "error", text: `unknown preset "${name}" (available: ${available})` } };
|
|
127
|
+
}
|
|
128
|
+
if (input.spawned) {
|
|
129
|
+
return {
|
|
130
|
+
action: "settled",
|
|
131
|
+
result: {
|
|
132
|
+
kind: "error",
|
|
133
|
+
text: `the OMP session is already running with a fixed approval policy: pick "${name}" in a new chat, before the first prompt`,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return { action: "apply", preset: name, result: { kind: "success", text: `preset ${name}` } };
|
|
138
|
+
}
|
|
74
139
|
/**
|
|
75
140
|
* The three Dash events `pinInitialPermission` stamps for a fresh session,
|
|
76
141
|
* in its append order (preset, sandbox, approval). Cold replay prepends
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OmpRpcClient — NDJSON client over `omp --mode rpc` stdio (RPC transport line).
|
|
3
|
+
*
|
|
4
|
+
* Ported from `git show 6d2fbe1:apps/multi-agent/agent-omp/src/rpc.ts`.
|
|
5
|
+
*
|
|
6
|
+
* Protocol: `ready` is a plain event; the current binary announces
|
|
7
|
+
* `{type:"ready",protocolVersion:1,supportedProtocolVersions:[1,2],
|
|
8
|
+
* maxFrameBytes:1048576,maxReassembledFrameBytes:67108864}`.
|
|
9
|
+
* We deliberately DO NOT call `negotiate_protocol`: v1 is plain NDJSON, which
|
|
10
|
+
* is exactly what this reader implements. Negotiating 2 would switch the peer
|
|
11
|
+
* to >1MiB frame chunking and require a reassembler (registered gap, spec §4).
|
|
12
|
+
*/
|
|
13
|
+
import { spawn } from "node:child_process";
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
/** `$OMP_EXECUTABLE` wins; else PATH, else the common native-installer spots. */
|
|
18
|
+
export function resolveOmpExecutable() {
|
|
19
|
+
const configured = process.env.OMP_EXECUTABLE?.trim();
|
|
20
|
+
if (configured !== undefined && configured !== "")
|
|
21
|
+
return configured;
|
|
22
|
+
for (const dir of (process.env.PATH ?? "").split(":").filter(Boolean)) {
|
|
23
|
+
if (existsSync(join(dir, "omp")))
|
|
24
|
+
return "omp";
|
|
25
|
+
}
|
|
26
|
+
for (const candidate of [join(homedir(), ".local/bin/omp"), "/usr/local/bin/omp"]) {
|
|
27
|
+
if (existsSync(candidate))
|
|
28
|
+
return candidate;
|
|
29
|
+
}
|
|
30
|
+
return "omp";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Readiness deadline: bound the `ready` handshake so a broken spawn fails
|
|
34
|
+
* instead of hanging the caller forever. OMP can take a long time to emit
|
|
35
|
+
* `ready` while it performs MCP server connection and model discovery — a
|
|
36
|
+
* localhost model provider that drops (rather than rejects) the connection can
|
|
37
|
+
* hang until its own timeout, and a cold `npx` MCP server can take tens of
|
|
38
|
+
* seconds to spawn. The default is therefore generous; `0` disables the
|
|
39
|
+
* deadline. Override with `OMP_READY_TIMEOUT_MS`.
|
|
40
|
+
*/
|
|
41
|
+
const READY_TIMEOUT_MS = parseTimeout(process.env.OMP_READY_TIMEOUT_MS, 120_000);
|
|
42
|
+
/**
|
|
43
|
+
* Per-command response deadline: bound every blocking request so an
|
|
44
|
+
* unresponsive OMP (e.g. a hung `get_messages` during resume) fails within a
|
|
45
|
+
* fixed window instead of stalling the caller indefinitely. `0` disables the
|
|
46
|
+
* deadline. Override with `OMP_COMMAND_TIMEOUT_MS`.
|
|
47
|
+
*/
|
|
48
|
+
const COMMAND_TIMEOUT_MS = parseTimeout(process.env.OMP_COMMAND_TIMEOUT_MS, 30_000);
|
|
49
|
+
/** Parse a non-negative millisecond timeout; empty/missing → `fallback`, invalid → `fallback`. */
|
|
50
|
+
function parseTimeout(raw, fallback) {
|
|
51
|
+
if (raw === undefined || raw.trim() === "")
|
|
52
|
+
return fallback;
|
|
53
|
+
const value = Number(raw);
|
|
54
|
+
return Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Grace period between SIGTERM and the SIGKILL escalation that guarantees a
|
|
58
|
+
* stubborn `omp` (and its tool subprocesses) never survives teardown.
|
|
59
|
+
*/
|
|
60
|
+
const KILL_GRACE_MS = 2_000;
|
|
61
|
+
export class OmpRpcClient {
|
|
62
|
+
#proc;
|
|
63
|
+
#listeners = new Set();
|
|
64
|
+
#titleListeners = new Set();
|
|
65
|
+
#failureListeners = new Set();
|
|
66
|
+
#pending = new Map();
|
|
67
|
+
#ready;
|
|
68
|
+
#readyResolve;
|
|
69
|
+
#readyReject;
|
|
70
|
+
#nextId = 0;
|
|
71
|
+
#buffer = "";
|
|
72
|
+
#closed = false;
|
|
73
|
+
#killed = false;
|
|
74
|
+
#killTimer = null;
|
|
75
|
+
#failure = null;
|
|
76
|
+
/** Spawn `omp --mode rpc` and resolve once the `ready` handshake arrives. */
|
|
77
|
+
static async spawn(args = [], cwd) {
|
|
78
|
+
const client = new OmpRpcClient(args, cwd);
|
|
79
|
+
await client.#ready;
|
|
80
|
+
return client;
|
|
81
|
+
}
|
|
82
|
+
constructor(args, cwd) {
|
|
83
|
+
this.#proc = spawn(resolveOmpExecutable(), ["--mode", "rpc", ...args], {
|
|
84
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
85
|
+
// Own process group so teardown can signal omp AND its tool subprocesses.
|
|
86
|
+
detached: true,
|
|
87
|
+
...(cwd === undefined ? {} : { cwd }),
|
|
88
|
+
});
|
|
89
|
+
this.#ready = new Promise((resolve, reject) => {
|
|
90
|
+
const timer = setTimeout(() => {
|
|
91
|
+
this.#fail(new Error("omp --mode rpc: timed out waiting for the `ready` event"));
|
|
92
|
+
}, READY_TIMEOUT_MS);
|
|
93
|
+
this.#readyResolve = () => {
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
resolve();
|
|
96
|
+
};
|
|
97
|
+
this.#readyReject = (error) => {
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
reject(error);
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
this.#proc.stdout.setEncoding("utf8");
|
|
103
|
+
this.#proc.stdout.on("data", (chunk) => this.#onData(chunk));
|
|
104
|
+
this.#proc.stderr.setEncoding("utf8");
|
|
105
|
+
this.#proc.stderr.on("data", (chunk) => {
|
|
106
|
+
// OMP writes diagnostics to stderr; surface them for debugging.
|
|
107
|
+
process.stderr.write(chunk);
|
|
108
|
+
});
|
|
109
|
+
this.#proc.on("error", (error) => this.#fail(error));
|
|
110
|
+
this.#proc.on("exit", (code) => {
|
|
111
|
+
if (this.#killTimer !== null) {
|
|
112
|
+
clearTimeout(this.#killTimer);
|
|
113
|
+
this.#killTimer = null;
|
|
114
|
+
}
|
|
115
|
+
if (!this.#closed)
|
|
116
|
+
this.#fail(new Error(`omp --mode rpc exited unexpectedly (code ${code})`));
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/** Register an event listener; returns the unsubscriber. */
|
|
120
|
+
on(listener) {
|
|
121
|
+
this.#listeners.add(listener);
|
|
122
|
+
return () => {
|
|
123
|
+
this.#listeners.delete(listener);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** Register a failure listener invoked when the child exits or errors. Returns the unsubscriber. */
|
|
127
|
+
onFailure(listener) {
|
|
128
|
+
this.#failureListeners.add(listener);
|
|
129
|
+
return () => {
|
|
130
|
+
this.#failureListeners.delete(listener);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Write one fire-and-forget command that must NOT carry a correlation id.
|
|
135
|
+
* `extension_ui_response` keys its `id` to the originating UI request, so the
|
|
136
|
+
* correlation-adding `send()` would clobber it.
|
|
137
|
+
*/
|
|
138
|
+
sendRaw(command) {
|
|
139
|
+
if (this.#failure !== null || this.#closed)
|
|
140
|
+
return;
|
|
141
|
+
try {
|
|
142
|
+
this.#proc.stdin.write(JSON.stringify(command) + "\n");
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
process.stderr.write(`omp rpc write error: ${String(error)}\n`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Send one command and resolve with its `response`. Fire-and-forget callers
|
|
150
|
+
* may ignore the promise. A per-command deadline (see COMMAND_TIMEOUT_MS)
|
|
151
|
+
* rejects the request if OMP never answers, so blocking callers
|
|
152
|
+
* (`getMessages`) can't stall indefinitely; pass `timeoutMs` to override,
|
|
153
|
+
* or `0` to disable the deadline.
|
|
154
|
+
*/
|
|
155
|
+
send(command, timeoutMs = COMMAND_TIMEOUT_MS) {
|
|
156
|
+
if (this.#failure !== null)
|
|
157
|
+
return Promise.reject(this.#failure);
|
|
158
|
+
if (this.#closed)
|
|
159
|
+
return Promise.reject(new Error("omp rpc client is closed"));
|
|
160
|
+
const id = `omp-${++this.#nextId}`;
|
|
161
|
+
return new Promise((resolve, reject) => {
|
|
162
|
+
const pending = {
|
|
163
|
+
resolve,
|
|
164
|
+
reject,
|
|
165
|
+
clear: () => { },
|
|
166
|
+
};
|
|
167
|
+
if (timeoutMs > 0) {
|
|
168
|
+
const timer = setTimeout(() => {
|
|
169
|
+
if (this.#pending.delete(id)) {
|
|
170
|
+
reject(new Error(`omp rpc command timed out after ${timeoutMs}ms`));
|
|
171
|
+
}
|
|
172
|
+
}, timeoutMs);
|
|
173
|
+
pending.clear = () => clearTimeout(timer);
|
|
174
|
+
}
|
|
175
|
+
this.#pending.set(id, pending);
|
|
176
|
+
try {
|
|
177
|
+
this.#proc.stdin.write(JSON.stringify({ ...command, id }) + "\n");
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
this.#pending.delete(id);
|
|
181
|
+
pending.clear();
|
|
182
|
+
reject(error);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/** Query `get_state`; returns the state payload. */
|
|
187
|
+
async getState() {
|
|
188
|
+
const response = await this.send({ type: "get_state" });
|
|
189
|
+
if (!response.success)
|
|
190
|
+
throw new Error(`omp get_state failed: ${String(response.error ?? "unknown error")}`);
|
|
191
|
+
return (response.data ?? { isStreaming: false });
|
|
192
|
+
}
|
|
193
|
+
/** Query `get_messages`; returns the full conversation. */
|
|
194
|
+
async getMessages() {
|
|
195
|
+
const response = await this.send({ type: "get_messages" });
|
|
196
|
+
if (!response.success)
|
|
197
|
+
throw new Error(`omp get_messages failed: ${String(response.error ?? "unknown error")}`);
|
|
198
|
+
const data = response.data;
|
|
199
|
+
return data?.messages ?? [];
|
|
200
|
+
}
|
|
201
|
+
/** Query `get_session_stats`; live token/context/cost accounting (live sessions only). */
|
|
202
|
+
async getSessionStats() {
|
|
203
|
+
const response = await this.send({ type: "get_session_stats" });
|
|
204
|
+
if (!response.success)
|
|
205
|
+
throw new Error(`omp get_session_stats failed: ${String(response.error ?? "unknown error")}`);
|
|
206
|
+
return (response.data ?? {});
|
|
207
|
+
}
|
|
208
|
+
/** Query `get_subagents`; live subagent registry (fail-soft: [] when unavailable). */
|
|
209
|
+
async getSubagents() {
|
|
210
|
+
try {
|
|
211
|
+
const response = await this.send({ type: "get_subagents" });
|
|
212
|
+
if (!response.success)
|
|
213
|
+
return [];
|
|
214
|
+
const data = response.data;
|
|
215
|
+
return data?.subagents ?? [];
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Start a turn with a user prompt. On an idle session `prompt` wakes the
|
|
223
|
+
* agent and starts a fresh turn. Never send this while OMP is streaming:
|
|
224
|
+
* without `streamingBehavior` OMP rejects it, and `prompt` with
|
|
225
|
+
* `streamingBehavior: "followUp"` queues with `resumeIfIdle: false` (delivered
|
|
226
|
+
* as a user message on idle, never auto-generating a turn).
|
|
227
|
+
*/
|
|
228
|
+
prompt(message) {
|
|
229
|
+
return this.send({ type: "prompt", message });
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Queue a follow-up on a busy session. OMP delivers it as the next turn's
|
|
233
|
+
* user message once the current turn ends AND auto-generates that turn —
|
|
234
|
+
* the dedicated `follow_up` command's connection layer hardcodes
|
|
235
|
+
* `resumeIfIdle: true` (unlike `prompt` + streamingBehavior). Verified
|
|
236
|
+
* empirically: docs/probe-omp-followup.mjs.
|
|
237
|
+
*/
|
|
238
|
+
followUp(message) {
|
|
239
|
+
return this.send({ type: "follow_up", message });
|
|
240
|
+
}
|
|
241
|
+
/** Steer an in-flight turn with a user message. */
|
|
242
|
+
steer(message) {
|
|
243
|
+
return this.send({ type: "steer", message });
|
|
244
|
+
}
|
|
245
|
+
/** Select the active model by provider + model id (e.g. `deepseek`/`deepseek-v4-pro`). */
|
|
246
|
+
setModel(provider, modelId) {
|
|
247
|
+
return this.send({ type: "set_model", provider, modelId });
|
|
248
|
+
}
|
|
249
|
+
/** Abort the current streaming run. */
|
|
250
|
+
abort() {
|
|
251
|
+
return this.send({ type: "abort" });
|
|
252
|
+
}
|
|
253
|
+
/** Discard the current conversation and start a fresh OMP session. */
|
|
254
|
+
newSession() {
|
|
255
|
+
return this.send({ type: "new_session" });
|
|
256
|
+
}
|
|
257
|
+
/** Title frames (OMP `session_info_update.title`, plus `setTitle` when the
|
|
258
|
+
* child runs with `PI_RPC_EMIT_TITLE=1`). Returns the unsubscriber. */
|
|
259
|
+
onTitle(listener) {
|
|
260
|
+
this.#titleListeners.add(listener);
|
|
261
|
+
return () => { this.#titleListeners.delete(listener); };
|
|
262
|
+
}
|
|
263
|
+
/** System prompt as OMP renders it (v18 `get_state.systemPrompt`). */
|
|
264
|
+
async getSystemPrompt() {
|
|
265
|
+
try {
|
|
266
|
+
const state = await this.getState();
|
|
267
|
+
return state.systemPrompt;
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/** Context-usage snapshot for pre/post compact metering (fail-soft). */
|
|
274
|
+
async contextUsage() {
|
|
275
|
+
try {
|
|
276
|
+
const state = await this.getState();
|
|
277
|
+
return state.contextUsage;
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return undefined;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/** Compact the live conversation (RPC `compact` command). */
|
|
284
|
+
compact(customInstructions) {
|
|
285
|
+
return this.send(customInstructions === undefined
|
|
286
|
+
? { type: "compact" }
|
|
287
|
+
: { type: "compact", customInstructions });
|
|
288
|
+
}
|
|
289
|
+
close() {
|
|
290
|
+
if (this.#closed)
|
|
291
|
+
return;
|
|
292
|
+
this.#closed = true;
|
|
293
|
+
if (process.env.OMP_TRACE === "1") {
|
|
294
|
+
process.stderr.write(`[omp-rpc ${Date.now() % 1_000_000}] close() stack=${new Error().stack?.split("\n").slice(1, 6).join(" <- ")}\n`);
|
|
295
|
+
}
|
|
296
|
+
this.#kill();
|
|
297
|
+
this.#fail(new Error("omp rpc client closed"));
|
|
298
|
+
}
|
|
299
|
+
/** SIGTERM the process group, escalating to SIGKILL if it lingers. */
|
|
300
|
+
#kill() {
|
|
301
|
+
if (this.#killed)
|
|
302
|
+
return;
|
|
303
|
+
this.#killed = true;
|
|
304
|
+
const pid = this.#proc.pid;
|
|
305
|
+
if (pid === undefined)
|
|
306
|
+
return;
|
|
307
|
+
try {
|
|
308
|
+
process.kill(-pid, "SIGTERM");
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
return; // group already gone
|
|
312
|
+
}
|
|
313
|
+
this.#killTimer = setTimeout(() => {
|
|
314
|
+
this.#killTimer = null;
|
|
315
|
+
try {
|
|
316
|
+
process.kill(-pid, "SIGKILL");
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
// already dead
|
|
320
|
+
}
|
|
321
|
+
}, KILL_GRACE_MS);
|
|
322
|
+
}
|
|
323
|
+
#onData(chunk) {
|
|
324
|
+
this.#buffer += chunk;
|
|
325
|
+
let index;
|
|
326
|
+
while ((index = this.#buffer.indexOf("\n")) >= 0) {
|
|
327
|
+
let line = this.#buffer.slice(0, index);
|
|
328
|
+
this.#buffer = this.#buffer.slice(index + 1);
|
|
329
|
+
if (line.endsWith("\r"))
|
|
330
|
+
line = line.slice(0, -1);
|
|
331
|
+
if (line.trim() === "")
|
|
332
|
+
continue;
|
|
333
|
+
this.#onLine(line);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
#onLine(line) {
|
|
337
|
+
let record;
|
|
338
|
+
try {
|
|
339
|
+
record = JSON.parse(line);
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return; // ignore malformed lines
|
|
343
|
+
}
|
|
344
|
+
if (record.type === "ready") {
|
|
345
|
+
this.#readyResolve();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (record.type === "session_info_update" && typeof record.title === "string" && record.title !== "") {
|
|
349
|
+
for (const listener of [...this.#titleListeners]) {
|
|
350
|
+
try {
|
|
351
|
+
listener(record.title);
|
|
352
|
+
}
|
|
353
|
+
catch { /* contained */ }
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (record.type === "setTitle" && typeof record.title === "string" && record.title !== "") {
|
|
357
|
+
for (const listener of [...this.#titleListeners]) {
|
|
358
|
+
try {
|
|
359
|
+
listener(record.title);
|
|
360
|
+
}
|
|
361
|
+
catch { /* contained */ }
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (record.type === "response") {
|
|
365
|
+
const response = record;
|
|
366
|
+
if (response.id !== undefined) {
|
|
367
|
+
const pending = this.#pending.get(response.id);
|
|
368
|
+
if (pending !== undefined) {
|
|
369
|
+
this.#pending.delete(response.id);
|
|
370
|
+
pending.clear();
|
|
371
|
+
pending.resolve(response);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
for (const listener of [...this.#listeners]) {
|
|
377
|
+
try {
|
|
378
|
+
listener(record);
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
// Listener failures are contained — one bad observer must not break the stream.
|
|
382
|
+
process.stderr.write(`omp rpc listener error: ${String(error)}\n`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
#fail(error) {
|
|
387
|
+
if (this.#failure !== null)
|
|
388
|
+
return;
|
|
389
|
+
this.#failure = error;
|
|
390
|
+
// Reject an in-flight handshake immediately (fix: not just via the 30s timeout).
|
|
391
|
+
this.#readyReject(error);
|
|
392
|
+
for (const pending of this.#pending.values()) {
|
|
393
|
+
pending.clear();
|
|
394
|
+
pending.reject(error);
|
|
395
|
+
}
|
|
396
|
+
this.#pending.clear();
|
|
397
|
+
// Any failure path (ready-timeout, pre-ready exit, spawn error) must also
|
|
398
|
+
// terminate the child so no orphan keeps the session file held.
|
|
399
|
+
this.#kill();
|
|
400
|
+
for (const listener of [...this.#failureListeners]) {
|
|
401
|
+
try {
|
|
402
|
+
listener(error);
|
|
403
|
+
}
|
|
404
|
+
catch (listenerError) {
|
|
405
|
+
process.stderr.write(`omp rpc failure listener error: ${String(listenerError)}\n`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
@@ -16,15 +16,42 @@
|
|
|
16
16
|
* per-label `/<label>/api` + `/<label>/api/remote.mux` mounts retired
|
|
17
17
|
* in T-C, `mountWorld` deleted in T-D).
|
|
18
18
|
*/
|
|
19
|
-
import { mkdirSync } from 'node:fs';
|
|
19
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
20
20
|
import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
|
|
21
21
|
import { join } from 'node:path';
|
|
22
|
-
import { spawnWorld, registerAgent, setReady, registerForeignTarget, registerHostMount, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../superd-hub/dist/index.js';
|
|
22
|
+
import { spawnWorld, registerAgent, unregisterAgent, setReady, registerForeignTarget, registerHostMount, worldMountPatches, provisionWorldProfile, resolveInstallAnchor, } from '../../superd-hub/dist/index.js';
|
|
23
|
+
import { resolveOmpExecutable } from './rpc-client.js';
|
|
23
24
|
export const name = 'agent-omp';
|
|
24
25
|
/** Runtime key — also the mount label. */
|
|
25
26
|
const KEY = 'omp';
|
|
27
|
+
/**
|
|
28
|
+
* Startup diagnostic (spec §3.5): the OMP world runs the operator's own `omp`
|
|
29
|
+
* binary over `omp --mode rpc` — the adapter bundles no OMP copy, so a missing
|
|
30
|
+
* binary fails at the FIRST PROMPT, not at boot. Probe the resolution order
|
|
31
|
+
* once and say so explicitly instead of mounting silently; readiness semantics
|
|
32
|
+
* are unchanged (they follow the world mount, not this probe).
|
|
33
|
+
*/
|
|
34
|
+
function diagnoseOmpBinary() {
|
|
35
|
+
const executable = resolveOmpExecutable();
|
|
36
|
+
// A bare name is what the resolver yields for BOTH a PATH hit and "nothing
|
|
37
|
+
// installed" — walk PATH to tell those apart. A slashed candidate is already
|
|
38
|
+
// a concrete path and is checked directly.
|
|
39
|
+
const present = executable.includes('/')
|
|
40
|
+
? existsSync(executable)
|
|
41
|
+
: (process.env.PATH ?? '').split(':').filter(Boolean).some((dir) => existsSync(join(dir, executable)));
|
|
42
|
+
if (!present) {
|
|
43
|
+
console.error('[super-dsh] omp binary not found (checked $OMP_EXECUTABLE, PATH, ~/.local/bin/omp) — the OMP world will fail at first prompt');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
26
46
|
export function apply(ctx) {
|
|
27
|
-
|
|
47
|
+
diagnoseOmpBinary();
|
|
48
|
+
// Fiber-scoped roster entry: disabling the row disposes this fiber and the
|
|
49
|
+
// entry must go with it, otherwise a re-enable dies on `roster: duplicate
|
|
50
|
+
// agent key omp` (same defect the omp-sdk acceptance surfaced live).
|
|
51
|
+
ctx.effect?.(() => {
|
|
52
|
+
registerAgent({ key: KEY, label: 'OMP', ready: false });
|
|
53
|
+
return () => unregisterAgent(KEY);
|
|
54
|
+
}, `agent-${KEY}: roster`);
|
|
28
55
|
// Harness resolver (env → ~/.dsh): a consumer install has no DSH_HOME and
|
|
29
56
|
// no cwd contract — deriving the world root from cwd spawns worlds into a
|
|
30
57
|
// garbage tree or throws inside apply() and kills the whole host boot.
|
|
@@ -64,6 +91,12 @@ export function apply(ctx) {
|
|
|
64
91
|
ctx.effect?.(() => () => {
|
|
65
92
|
dropHostMount();
|
|
66
93
|
}, `agent-${KEY}: mount`);
|
|
94
|
+
// Unloading the row must unload the world: disposing the world's fiber
|
|
95
|
+
// disposes its provider, which closes every held transport (and therefore
|
|
96
|
+
// the `omp --mode rpc` children).
|
|
97
|
+
ctx.effect?.(() => () => {
|
|
98
|
+
void ctxW.fiber?.dispose();
|
|
99
|
+
}, `agent-${KEY}: world teardown`);
|
|
67
100
|
return ctxW;
|
|
68
101
|
})().catch((cause) => {
|
|
69
102
|
// A failed world degrades to a not-ready roster row; a rejected provided
|
package/agent-omp/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgmi-builds/agent-omp",
|
|
3
3
|
"version": "0.1.0",
|
|
4
|
-
"description": "OMP Web: OMP provider for DeepSeek Harness (dsh) — an AgentFactory that
|
|
4
|
+
"description": "OMP Web: OMP provider for DeepSeek Harness (dsh) — an AgentFactory that drives the operator's own omp binary as an `omp --mode rpc` child (NDJSON protocol v1 over stdio) and bridges OMP's session surface into Dash Agent/Session contracts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./dist/index.js",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
13
|
"lib",
|
|
14
|
-
"sidecar",
|
|
15
14
|
"cordis.patch.yml",
|
|
16
15
|
"README.md"
|
|
17
16
|
],
|
|
@@ -32,10 +31,7 @@
|
|
|
32
31
|
"build-client": "npm run typecheck:client && tsx scripts/build-client.ts",
|
|
33
32
|
"test": "node --test test/*.test.mjs"
|
|
34
33
|
},
|
|
35
|
-
"dependencies": {
|
|
36
|
-
"@oh-my-pi/pi-coding-agent": "^18.1.14",
|
|
37
|
-
"bun": "^1.4.2"
|
|
38
|
-
},
|
|
34
|
+
"dependencies": {},
|
|
39
35
|
"peerDependencies": {
|
|
40
36
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
41
37
|
"@deepseek-ai/dsh-agent": ">=0.1.5-0 <0.3.0-0",
|