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
package/superd-hub/dist/rpc.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
|
|
2
|
+
import { PACK_VERSION } from './pack-version.js';
|
|
1
3
|
import { listRuntimeKeys } from './targets.js';
|
|
2
4
|
import { agentLinks } from './agent-roster.js';
|
|
5
|
+
import { ensureSelf } from './machines.js';
|
|
3
6
|
/** The shared-channel Fetch route path this RPC face owns. */
|
|
4
7
|
export const AGENT_RUNTIME_RPC_PATH = '/api/agent-runtime';
|
|
5
8
|
/** The live registry view: native plus every registered foreign context. */
|
|
6
9
|
export const registryTargets = {
|
|
7
10
|
listRuntimes: listRuntimeKeys,
|
|
8
11
|
};
|
|
12
|
+
/** The version this hub SERVES as `hub.version` — the super-dsh PACK version
|
|
13
|
+
* (D6): the subpackage's own 0.1.0 never moves, so peers comparing against it
|
|
14
|
+
* could never see a mismatch. The pack manifest ships exactly two hops above
|
|
15
|
+
* the compiled output in every layout (see pack-version.ts); 'unknown' when
|
|
16
|
+
* unreadable — an honest non-number, not a fake one. */
|
|
17
|
+
const HUB_VERSION = PACK_VERSION;
|
|
9
18
|
function json(status, body) {
|
|
10
19
|
return new Response(JSON.stringify(body), {
|
|
11
20
|
status,
|
|
@@ -14,16 +23,35 @@ function json(status, body) {
|
|
|
14
23
|
}
|
|
15
24
|
/**
|
|
16
25
|
* The control-plane handler: world inventory only.
|
|
26
|
+
*
|
|
27
|
+
* ADDITIVE contract (mesh P1): the GET body gained `hub: {machineId, label,
|
|
28
|
+
* version}` and every `agents` row gained `id` (a6); `available` and all
|
|
29
|
+
* pre-existing agents fields are unchanged — old clients ignore the new
|
|
30
|
+
* fields, new clients read them.
|
|
17
31
|
* @param request - the incoming `/api/agent-runtime` request.
|
|
18
32
|
* @param source - live runtime registry view.
|
|
33
|
+
* @param deps - optional home override; defaults to `resolveDshHome()`.
|
|
19
34
|
* @returns the JSON response.
|
|
20
35
|
*/
|
|
21
|
-
export async function handleAgentRuntime(request, source) {
|
|
36
|
+
export async function handleAgentRuntime(request, source, deps) {
|
|
22
37
|
const available = source.listRuntimes();
|
|
23
38
|
if (request.method === 'GET' || request.method === 'HEAD') {
|
|
24
39
|
// The selector asks this face for the roster: keys AND the mount path each
|
|
25
|
-
// key is addressed by. Read-only — the roster carries no selection.
|
|
26
|
-
|
|
40
|
+
// key is addressed by. Read-only — the roster carries no selection. The
|
|
41
|
+
// hub block (this machine's m4 + label + hub version) rides along for the
|
|
42
|
+
// multi-machine UI; the a6 row ids ride on every agents row.
|
|
43
|
+
const home = deps?.home ?? resolveDshHome();
|
|
44
|
+
const self = ensureSelf(home, 'local');
|
|
45
|
+
// Self-description discipline (2026-09-28 user ruling): a peer's discovery
|
|
46
|
+
// probe (`?mesh=1`) receives THIS machine's own rows only — a hub never
|
|
47
|
+
// re-broadcasts other remotes' agents to its peers (hub-to-hub is P2P;
|
|
48
|
+
// the requester fans out one probe per paired machine and merges itself).
|
|
49
|
+
// The plain browser GET keeps the full roster — the local UI's machine
|
|
50
|
+
// grouping consumes exactly that.
|
|
51
|
+
const links = new URL(request.url).searchParams.get('mesh') === '1'
|
|
52
|
+
? agentLinks(home).filter((l) => l.machine === 'local')
|
|
53
|
+
: agentLinks(home);
|
|
54
|
+
return json(200, { available, agents: links, hub: { machineId: self.id, label: self.label, version: HUB_VERSION } });
|
|
27
55
|
}
|
|
28
56
|
// A POST that used to switch a global selector has no meaning any more:
|
|
29
57
|
// the addressed world is the mount path of the request, not a shared value.
|
|
@@ -35,7 +63,9 @@ export async function handleAgentRuntime(request, source) {
|
|
|
35
63
|
/**
|
|
36
64
|
* Register the control-plane RPC face on the shared `/api` connection channel
|
|
37
65
|
* (behind the standard browser-trust + auth fence). No-op when the
|
|
38
|
-
* `connection` service is absent (e.g. fake-ctx unit tests).
|
|
66
|
+
* `connection` service is absent (e.g. fake-ctx unit tests). The route answers
|
|
67
|
+
* with the DEFAULT home (`resolveDshHome()` at request time); callers needing
|
|
68
|
+
* a pinned home invoke handleAgentRuntime directly with deps.
|
|
39
69
|
*/
|
|
40
70
|
export function registerSelectorRpc(ctx, source) {
|
|
41
71
|
ctx.inject(['connection'], (connCtx) => {
|
|
@@ -71,7 +71,9 @@ async function publishWorldInHostResolutionTurn(packages, launcher, opts, worldP
|
|
|
71
71
|
const declarer = join(worldProfileDir, 'package.json');
|
|
72
72
|
const worldScope = join(worldProfileDir, 'node_modules', '@pgmi-builds');
|
|
73
73
|
const baseNames = new Set(base.entries.map((entry) => entry.name));
|
|
74
|
-
|
|
74
|
+
// R0 scan guard: a dsh-base world has NO farm — a missing scope is not a
|
|
75
|
+
// publish failure, just nothing to add (existsSync before readdirSync).
|
|
76
|
+
for (const name of existsSync(worldScope) ? readdirSync(worldScope, { withFileTypes: true }) : []) {
|
|
75
77
|
if (!name.isDirectory() && !name.isSymbolicLink())
|
|
76
78
|
continue;
|
|
77
79
|
const pkgName = `@pgmi-builds/${name.name}`;
|
|
@@ -457,8 +457,13 @@ export interface HubRosterRow {
|
|
|
457
457
|
readonly label: string;
|
|
458
458
|
/** The row's mount path. */
|
|
459
459
|
readonly path: string;
|
|
460
|
-
/**
|
|
461
|
-
|
|
460
|
+
/**
|
|
461
|
+
* Machine the runtime comes from (mesh P2): `'local'` for this machine's
|
|
462
|
+
* rows, the owning machine's m4 for federated rows. Optional — the wire
|
|
463
|
+
* may omit it and the grouping now lives client-side (mesh-groups.ts,
|
|
464
|
+
* fed the machines API's label map).
|
|
465
|
+
*/
|
|
466
|
+
readonly machine?: string;
|
|
462
467
|
}
|
|
463
468
|
/**
|
|
464
469
|
* The active agent's display name for the Hub row's right-edge selector: the
|
|
@@ -470,25 +475,6 @@ export interface HubRosterRow {
|
|
|
470
475
|
* Host-half pure logic so `test/client-switch.test.mjs` pins it from `dist/`.
|
|
471
476
|
*/
|
|
472
477
|
export declare function activeAgentName(activeAgent: string | undefined, roster: readonly HubRosterRow[]): string | undefined;
|
|
473
|
-
/** Which machine one roster row groups under: the row's own machine (parser-guaranteed). */
|
|
474
|
-
export declare function machineGroup(row: HubRosterRow): string;
|
|
475
|
-
/** One machine's group of roster rows, in roster order. */
|
|
476
|
-
export interface MachineGroup {
|
|
477
|
-
/** The grouping key (the members' shared `machine`). */
|
|
478
|
-
readonly machine: string;
|
|
479
|
-
/** The rows of this machine, keeping the roster's own order. */
|
|
480
|
-
readonly agents: readonly HubRosterRow[];
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Group a roster by machine for the HubPanelIcon chevron menu's native
|
|
484
|
-
* workspace-list look: one group per distinct `machineGroup` key, groups in
|
|
485
|
-
* first-appearance order, members keeping the roster's order inside their
|
|
486
|
-
* group. A single-group roster (today's local-only shape) renders exactly
|
|
487
|
-
* like the old flat list minus the card border.
|
|
488
|
-
*
|
|
489
|
-
* Host-half pure logic so `test/client-switch.test.mjs` pins it from `dist/`.
|
|
490
|
-
*/
|
|
491
|
-
export declare function machineGroups(rows: readonly HubRosterRow[]): readonly MachineGroup[];
|
|
492
478
|
/**
|
|
493
479
|
* What the machine hands the host's gate composition (T-G): the machine-side
|
|
494
480
|
* ingredients of {@link LandingGateOptions}. Structurally a full
|
|
@@ -628,19 +614,70 @@ export interface SwitchController {
|
|
|
628
614
|
* switch's pointer-restored view).
|
|
629
615
|
*/
|
|
630
616
|
export declare function createSwitchController(host: SwitchHost, options?: SwitchOptions): SwitchController;
|
|
631
|
-
/** What attemptSwitch does with a roster row: run the machine / report failure / wait for readiness. */
|
|
632
|
-
export type PreFlightDecision = 'run' | 'failed' | 'wait';
|
|
633
|
-
/**
|
|
617
|
+
/** What attemptSwitch does with a roster row: run the machine / report failure / wait for readiness / fail fast on a degraded federated row. */
|
|
618
|
+
export type PreFlightDecision = 'run' | 'failed' | 'wait' | 'machine-down';
|
|
619
|
+
/**
|
|
620
|
+
* The roster fields the pre-flight reads (the projection carries both since
|
|
621
|
+
* C1 task 3; `machine` since the mesh P2 roster dimension).
|
|
622
|
+
*/
|
|
634
623
|
export interface PreFlightRow {
|
|
635
624
|
ready?: boolean;
|
|
636
625
|
failed?: boolean;
|
|
626
|
+
/**
|
|
627
|
+
* Owning machine (m4) for FEDERATED rows — `'local'` or absent means this
|
|
628
|
+
* machine's own world (the C1 spawn-wait semantics). The client's
|
|
629
|
+
* `AgentLink` satisfies this structurally; the field decides the I1(c)
|
|
630
|
+
* fail-fast branch.
|
|
631
|
+
*/
|
|
632
|
+
machine?: string;
|
|
637
633
|
}
|
|
638
634
|
/**
|
|
639
635
|
* The pure pre-flight decision. `native` always runs; an absent row (roster
|
|
640
636
|
* fetch failed, or the key is not listed) also runs — the machine's roster
|
|
641
|
-
* probe is the authority on unknown targets, exactly as before C1.
|
|
637
|
+
* probe is the authority on unknown targets, exactly as before C1. A
|
|
638
|
+
* not-ready FEDERATED row (`machine` set and not `'local'`) decides
|
|
639
|
+
* `'machine-down'` — an immediate actionable failure, never a wait loop
|
|
640
|
+
* (the hub's probe already knows the machine is unreachable or its auth
|
|
641
|
+
* expired); `failed` keeps precedence everywhere (a peer-reported spawn
|
|
642
|
+
* rejection still reports as failed).
|
|
642
643
|
*/
|
|
643
644
|
export declare function decidePreFlight(label: string, row: PreFlightRow | undefined): PreFlightDecision;
|
|
645
|
+
/** Bound on the machine-down branch's enrichment fetch (mesh P3 Task 5a:
|
|
646
|
+
* the parked P2 minor — an unbounded `fetchMachines` await — folds here; a
|
|
647
|
+
* hung hub answer must never swallow the toast). */
|
|
648
|
+
export declare const MACHINE_DOWN_ENRICH_MS = 3000;
|
|
649
|
+
/** The machines-face slice the machine-down feedback reads (the client's
|
|
650
|
+
* `fetchMachines()` satisfies this structurally). */
|
|
651
|
+
export interface MachineDownMachinesFace {
|
|
652
|
+
machines: readonly {
|
|
653
|
+
id: string;
|
|
654
|
+
label: string;
|
|
655
|
+
status: string;
|
|
656
|
+
}[];
|
|
657
|
+
}
|
|
658
|
+
/** The branch's injected faces — the browser wiring supplies the real
|
|
659
|
+
* fetch/reprobe/toast; tests fake all of them. */
|
|
660
|
+
export interface MachineDownFaces {
|
|
661
|
+
/** Same-origin GET of the hub machine list (enrichment only). */
|
|
662
|
+
fetchMachines(): Promise<MachineDownMachinesFace>;
|
|
663
|
+
/** The I1(b) light probe: POST `{op: 'reprobe', id}` — fire-and-forget. */
|
|
664
|
+
reprobe(id: string): Promise<void>;
|
|
665
|
+
toast(message: string): void;
|
|
666
|
+
setTimeout(fn: () => void, ms: number): unknown;
|
|
667
|
+
clearTimeout(handle: unknown): void;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* The machine-down branch's pure half (I1(c) feedback + I1(b) light probe,
|
|
671
|
+
* mesh P3 Task 5a): enrich the toast through the machines face — BOUNDED at
|
|
672
|
+
* {@link MACHINE_DOWN_ENRICH_MS} — then, after toasting, fire ONE reprobe
|
|
673
|
+
* for the row's machine and forget it: a stale-unreachable machine gets a
|
|
674
|
+
* fresh attempt per failed click, so the NEXT click can succeed without
|
|
675
|
+
* waiting for the hub's 5-minute sweep. Never blocks the UI path (the whole
|
|
676
|
+
* body is detached), never surfaces a reprobe failure (the sweep retries).
|
|
677
|
+
*/
|
|
678
|
+
export declare function runMachineDownFeedback(label: string, row: PreFlightRow & {
|
|
679
|
+
label?: string;
|
|
680
|
+
}, faces: MachineDownFaces): void;
|
|
644
681
|
/** Default bound on one readiness wait (the page never locks behind a stuck world). */
|
|
645
682
|
export declare const WAIT_BOUND_MS = 120000;
|
|
646
683
|
/** Default poll interval for one readiness wait. */
|
|
@@ -502,34 +502,6 @@ export function activeAgentName(activeAgent, roster) {
|
|
|
502
502
|
return undefined;
|
|
503
503
|
return roster.find((row) => row.key === activeAgent)?.label ?? activeAgent;
|
|
504
504
|
}
|
|
505
|
-
/** Which machine one roster row groups under: the row's own machine (parser-guaranteed). */
|
|
506
|
-
export function machineGroup(row) {
|
|
507
|
-
return row.machine;
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* Group a roster by machine for the HubPanelIcon chevron menu's native
|
|
511
|
-
* workspace-list look: one group per distinct `machineGroup` key, groups in
|
|
512
|
-
* first-appearance order, members keeping the roster's order inside their
|
|
513
|
-
* group. A single-group roster (today's local-only shape) renders exactly
|
|
514
|
-
* like the old flat list minus the card border.
|
|
515
|
-
*
|
|
516
|
-
* Host-half pure logic so `test/client-switch.test.mjs` pins it from `dist/`.
|
|
517
|
-
*/
|
|
518
|
-
export function machineGroups(rows) {
|
|
519
|
-
const groups = [];
|
|
520
|
-
const byMachine = new Map();
|
|
521
|
-
for (const row of rows) {
|
|
522
|
-
const machine = machineGroup(row);
|
|
523
|
-
let group = byMachine.get(machine);
|
|
524
|
-
if (group === undefined) {
|
|
525
|
-
group = { machine, agents: [] };
|
|
526
|
-
byMachine.set(machine, group);
|
|
527
|
-
groups.push(group);
|
|
528
|
-
}
|
|
529
|
-
group.agents.push(row);
|
|
530
|
-
}
|
|
531
|
-
return groups;
|
|
532
|
-
}
|
|
533
505
|
/**
|
|
534
506
|
* Build the switch machine over an injected {@link SwitchHost}.
|
|
535
507
|
*
|
|
@@ -735,7 +707,12 @@ export function createSwitchController(host, options = {}) {
|
|
|
735
707
|
/**
|
|
736
708
|
* The pure pre-flight decision. `native` always runs; an absent row (roster
|
|
737
709
|
* fetch failed, or the key is not listed) also runs — the machine's roster
|
|
738
|
-
* probe is the authority on unknown targets, exactly as before C1.
|
|
710
|
+
* probe is the authority on unknown targets, exactly as before C1. A
|
|
711
|
+
* not-ready FEDERATED row (`machine` set and not `'local'`) decides
|
|
712
|
+
* `'machine-down'` — an immediate actionable failure, never a wait loop
|
|
713
|
+
* (the hub's probe already knows the machine is unreachable or its auth
|
|
714
|
+
* expired); `failed` keeps precedence everywhere (a peer-reported spawn
|
|
715
|
+
* rejection still reports as failed).
|
|
739
716
|
*/
|
|
740
717
|
export function decidePreFlight(label, row) {
|
|
741
718
|
if (label === NATIVE_AGENT)
|
|
@@ -744,10 +721,56 @@ export function decidePreFlight(label, row) {
|
|
|
744
721
|
return 'run';
|
|
745
722
|
if (row.failed === true)
|
|
746
723
|
return 'failed';
|
|
747
|
-
if (row.ready !== true)
|
|
724
|
+
if (row.ready !== true) {
|
|
725
|
+
// I1(c): a federated not-ready row is DEGRADED, not spawning — fail fast.
|
|
726
|
+
if (row.machine !== undefined && row.machine !== 'local')
|
|
727
|
+
return 'machine-down';
|
|
748
728
|
return 'wait';
|
|
729
|
+
}
|
|
749
730
|
return 'run';
|
|
750
731
|
}
|
|
732
|
+
// ---- I1(b): the machine-down feedback (preflight light probe) ----------------
|
|
733
|
+
/** Bound on the machine-down branch's enrichment fetch (mesh P3 Task 5a:
|
|
734
|
+
* the parked P2 minor — an unbounded `fetchMachines` await — folds here; a
|
|
735
|
+
* hung hub answer must never swallow the toast). */
|
|
736
|
+
export const MACHINE_DOWN_ENRICH_MS = 3_000;
|
|
737
|
+
/**
|
|
738
|
+
* The machine-down branch's pure half (I1(c) feedback + I1(b) light probe,
|
|
739
|
+
* mesh P3 Task 5a): enrich the toast through the machines face — BOUNDED at
|
|
740
|
+
* {@link MACHINE_DOWN_ENRICH_MS} — then, after toasting, fire ONE reprobe
|
|
741
|
+
* for the row's machine and forget it: a stale-unreachable machine gets a
|
|
742
|
+
* fresh attempt per failed click, so the NEXT click can succeed without
|
|
743
|
+
* waiting for the hub's 5-minute sweep. Never blocks the UI path (the whole
|
|
744
|
+
* body is detached), never surfaces a reprobe failure (the sweep retries).
|
|
745
|
+
*/
|
|
746
|
+
export function runMachineDownFeedback(label, row, faces) {
|
|
747
|
+
void (async () => {
|
|
748
|
+
let machineName = row.machine;
|
|
749
|
+
let status;
|
|
750
|
+
const enriched = await new Promise((resolve) => {
|
|
751
|
+
const bound = faces.setTimeout(() => resolve(undefined), MACHINE_DOWN_ENRICH_MS);
|
|
752
|
+
faces.fetchMachines().then((list) => { faces.clearTimeout(bound); resolve(list); }, () => { faces.clearTimeout(bound); resolve(undefined); });
|
|
753
|
+
});
|
|
754
|
+
if (enriched !== undefined) {
|
|
755
|
+
const found = enriched.machines.find((entry) => entry.id === row.machine);
|
|
756
|
+
if (found !== undefined) {
|
|
757
|
+
machineName = found.label;
|
|
758
|
+
if (found.status === 'unreachable' || found.status === 'auth-expired')
|
|
759
|
+
status = found.status;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
const who = row.label ?? label;
|
|
763
|
+
const machine = machineName ?? 'its machine';
|
|
764
|
+
faces.toast(status === undefined
|
|
765
|
+
? `Super D: ${who} is unavailable — machine ${machine} is not ready. Reprobe or re-add it in the Hub machines panel.`
|
|
766
|
+
: `Super D: ${who} is unavailable — machine ${machine} reports ${status}. Reprobe or re-add it in the Hub machines panel.`);
|
|
767
|
+
// I1(b): exactly ONE fresh attempt per failed click — keyed by the row's
|
|
768
|
+
// machine id (the machine-down decision guarantees it is set; a malformed
|
|
769
|
+
// row simply skips the light probe).
|
|
770
|
+
if (row.machine !== undefined)
|
|
771
|
+
faces.reprobe(row.machine).catch(() => { });
|
|
772
|
+
})();
|
|
773
|
+
}
|
|
751
774
|
/** Default bound on one readiness wait (the page never locks behind a stuck world). */
|
|
752
775
|
export const WAIT_BOUND_MS = 120_000;
|
|
753
776
|
/** Default poll interval for one readiness wait. */
|
|
@@ -10,16 +10,10 @@
|
|
|
10
10
|
* (before any step) — so every bridge-written log violated one rule or the
|
|
11
11
|
* other and became unresumable across restarts.
|
|
12
12
|
*
|
|
13
|
-
* The
|
|
14
|
-
*
|
|
15
|
-
* and
|
|
16
|
-
*
|
|
17
|
-
* a one-line wrap:
|
|
18
|
-
*
|
|
19
|
-
* this.session = withSystemHead(session, () => createSystemMessage(""))
|
|
20
|
-
*
|
|
21
|
-
* The wrap is a transparent Proxy that tracks the open turn/step (exactly as
|
|
22
|
-
* the v4 reader does) and intervenes minimally:
|
|
13
|
+
* The wrap installs the co-writer as OWN PROPERTIES on the session object
|
|
14
|
+
* itself (an `append` own-property shadow over the prototype method, plus
|
|
15
|
+
* `stampSystemPrompt`) and tracks the open turn/step (exactly as the v4
|
|
16
|
+
* reader does), intervening minimally:
|
|
23
17
|
*
|
|
24
18
|
* - the FIRST `user/message` append on a still-headless, still-empty
|
|
25
19
|
* surface first opens the turn's next step (when a turn is open but no
|
|
@@ -35,6 +29,18 @@
|
|
|
35
29
|
* queued and flushed inside the next step the adapter opens;
|
|
36
30
|
* - everything else delegates unchanged.
|
|
37
31
|
*
|
|
32
|
+
* IDENTITY IS THE CONTRACT (2026-09-28, D1): the wrap must return the session
|
|
33
|
+
* object ITSELF, never a wrapper. Upstream identity-checks live sessions by
|
|
34
|
+
* object equality — `session-title`'s `rename()` refuses unless
|
|
35
|
+
* `ctx.sessions.get(session.id) === session` (session-title/src/index.ts),
|
|
36
|
+
* and adapters register the RAW prepared session with `sessions.enter()` /
|
|
37
|
+
* `announce()` (e.g. agent-pi/src/index.ts). An earlier revision returned a
|
|
38
|
+
* transparent `Proxy`; every world-context rename then failed with
|
|
39
|
+
* `session "<id>" is not live in this store` because the Agent handle's
|
|
40
|
+
* `session` (the Proxy) was never the store-registered object. Returning the
|
|
41
|
+
* same object keeps `agent.session === ctx.sessions.get(id)` true, so the
|
|
42
|
+
* whole upstream session plane (rename included) sees one identity.
|
|
43
|
+
*
|
|
38
44
|
* A surface that already starts with a user message and has no head (legacy
|
|
39
45
|
* logs) stays headless — valid — and is never stamped: appending a head
|
|
40
46
|
* there is exactly the corruption this module exists to prevent.
|
|
@@ -54,7 +60,7 @@ export interface HeadAwareSessionFace {
|
|
|
54
60
|
}
|
|
55
61
|
/** Builds the placeholder head message (adapters pass their createSystemMessage). */
|
|
56
62
|
export type HeadPlaceholder = () => unknown;
|
|
57
|
-
/** One co-written session:
|
|
63
|
+
/** One co-written session: the session itself, carrying head bookkeeping (object identity preserved — see the module note). */
|
|
58
64
|
export type WithSystemHead<S> = S & {
|
|
59
65
|
/** Append-or-replace the protected head with the runtime's system prompt. */
|
|
60
66
|
stampSystemPrompt(turn: number, step: number, message: unknown): void;
|
|
@@ -64,6 +70,10 @@ export type WithSystemHead<S> = S & {
|
|
|
64
70
|
* @param session - the adapter's real Session.
|
|
65
71
|
* @param placeholder - builds the placeholder head message when the first
|
|
66
72
|
* user message arrives on an empty surface.
|
|
67
|
-
* @returns the session
|
|
73
|
+
* @returns the SAME session object with the co-writer installed as own
|
|
74
|
+
* properties (`append` shadow + `stampSystemPrompt`). Identity is the
|
|
75
|
+
* contract (D1): upstream liveness checks compare
|
|
76
|
+
* `ctx.sessions.get(id) === agent.session`, so the returned object must be
|
|
77
|
+
* the one registered with `sessions.enter()` — never a wrapper.
|
|
68
78
|
*/
|
|
69
79
|
export declare function withSystemHead<S extends HeadAwareSessionFace>(session: S, placeholder: HeadPlaceholder): WithSystemHead<S>;
|
|
@@ -10,16 +10,10 @@
|
|
|
10
10
|
* (before any step) — so every bridge-written log violated one rule or the
|
|
11
11
|
* other and became unresumable across restarts.
|
|
12
12
|
*
|
|
13
|
-
* The
|
|
14
|
-
*
|
|
15
|
-
* and
|
|
16
|
-
*
|
|
17
|
-
* a one-line wrap:
|
|
18
|
-
*
|
|
19
|
-
* this.session = withSystemHead(session, () => createSystemMessage(""))
|
|
20
|
-
*
|
|
21
|
-
* The wrap is a transparent Proxy that tracks the open turn/step (exactly as
|
|
22
|
-
* the v4 reader does) and intervenes minimally:
|
|
13
|
+
* The wrap installs the co-writer as OWN PROPERTIES on the session object
|
|
14
|
+
* itself (an `append` own-property shadow over the prototype method, plus
|
|
15
|
+
* `stampSystemPrompt`) and tracks the open turn/step (exactly as the v4
|
|
16
|
+
* reader does), intervening minimally:
|
|
23
17
|
*
|
|
24
18
|
* - the FIRST `user/message` append on a still-headless, still-empty
|
|
25
19
|
* surface first opens the turn's next step (when a turn is open but no
|
|
@@ -35,6 +29,18 @@
|
|
|
35
29
|
* queued and flushed inside the next step the adapter opens;
|
|
36
30
|
* - everything else delegates unchanged.
|
|
37
31
|
*
|
|
32
|
+
* IDENTITY IS THE CONTRACT (2026-09-28, D1): the wrap must return the session
|
|
33
|
+
* object ITSELF, never a wrapper. Upstream identity-checks live sessions by
|
|
34
|
+
* object equality — `session-title`'s `rename()` refuses unless
|
|
35
|
+
* `ctx.sessions.get(session.id) === session` (session-title/src/index.ts),
|
|
36
|
+
* and adapters register the RAW prepared session with `sessions.enter()` /
|
|
37
|
+
* `announce()` (e.g. agent-pi/src/index.ts). An earlier revision returned a
|
|
38
|
+
* transparent `Proxy`; every world-context rename then failed with
|
|
39
|
+
* `session "<id>" is not live in this store` because the Agent handle's
|
|
40
|
+
* `session` (the Proxy) was never the store-registered object. Returning the
|
|
41
|
+
* same object keeps `agent.session === ctx.sessions.get(id)` true, so the
|
|
42
|
+
* whole upstream session plane (rename included) sees one identity.
|
|
43
|
+
*
|
|
38
44
|
* A surface that already starts with a user message and has no head (legacy
|
|
39
45
|
* logs) stays headless — valid — and is never stamped: appending a head
|
|
40
46
|
* there is exactly the corruption this module exists to prevent.
|
|
@@ -59,14 +65,22 @@ function surfaceIsEmpty(events) {
|
|
|
59
65
|
* @param session - the adapter's real Session.
|
|
60
66
|
* @param placeholder - builds the placeholder head message when the first
|
|
61
67
|
* user message arrives on an empty surface.
|
|
62
|
-
* @returns the session
|
|
68
|
+
* @returns the SAME session object with the co-writer installed as own
|
|
69
|
+
* properties (`append` shadow + `stampSystemPrompt`). Identity is the
|
|
70
|
+
* contract (D1): upstream liveness checks compare
|
|
71
|
+
* `ctx.sessions.get(id) === agent.session`, so the returned object must be
|
|
72
|
+
* the one registered with `sessions.enter()` — never a wrapper.
|
|
63
73
|
*/
|
|
64
74
|
export function withSystemHead(session, placeholder) {
|
|
75
|
+
// Idempotent: a session already carrying the co-writer is returned as-is.
|
|
76
|
+
if (Object.prototype.hasOwnProperty.call(session, 'stampSystemPrompt'))
|
|
77
|
+
return session;
|
|
65
78
|
// The one narrow this module performs: the loose face above is what makes
|
|
66
79
|
// the generic real Session assignable; every call below issues exactly the
|
|
67
80
|
// SystemHeadAppend shape.
|
|
68
81
|
const appendHead = session.append.bind(session);
|
|
69
82
|
const rawAppend = session.append.bind(session);
|
|
83
|
+
const rawAppendFull = session.append.bind(session);
|
|
70
84
|
// Reader-mirrored turn/step state.
|
|
71
85
|
let turn = null;
|
|
72
86
|
let step = null;
|
|
@@ -115,80 +129,82 @@ export function withSystemHead(session, placeholder) {
|
|
|
115
129
|
}
|
|
116
130
|
headSeq = appendHead('system/message', { turn: turn ?? turnArg, step: step ?? stepArg, message }, { surfaceOp: { op: 'replace', startSeq: headSeq, endSeq: headSeq }, sourceEventSeqs: [headSeq] }).seq;
|
|
117
131
|
};
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
132
|
+
const interceptAppend = (type, data, opts) => {
|
|
133
|
+
if (type === 'turn/start') {
|
|
134
|
+
turn = data.turn;
|
|
135
|
+
nextStep = 1;
|
|
136
|
+
wrapOpenedStep = false;
|
|
137
|
+
wrapClosedStep = undefined;
|
|
138
|
+
}
|
|
139
|
+
else if (type === 'turn/end') {
|
|
140
|
+
// A step THIS wrap opened must not survive the turn boundary.
|
|
141
|
+
if (step !== null && wrapOpenedStep) {
|
|
142
|
+
rawAppend('step/end', { turn, step });
|
|
143
|
+
wrapClosedStep = step;
|
|
144
|
+
step = null;
|
|
145
|
+
nextStep += 1;
|
|
146
|
+
}
|
|
147
|
+
turn = null;
|
|
148
|
+
}
|
|
149
|
+
else if (type === 'step/start') {
|
|
150
|
+
const dataStep = data;
|
|
151
|
+
if (step !== null && wrapOpenedStep && dataStep.turn === turn && dataStep.step === step) {
|
|
152
|
+
// The adapter opened the step the wrap already wrote: drop the
|
|
153
|
+
// duplicate (the adapter's own counters stay consistent).
|
|
154
|
+
return { type, seq: session.snapshotEvents().length, time: Date.now(), data };
|
|
155
|
+
}
|
|
156
|
+
if (step === null && dataStep.step !== undefined)
|
|
157
|
+
step = dataStep.step;
|
|
158
|
+
wrapOpenedStep = false;
|
|
159
|
+
const applied = rawAppendFull(type, data);
|
|
160
|
+
if (queuedStamp !== undefined && step !== null) {
|
|
161
|
+
const pending = queuedStamp;
|
|
162
|
+
queuedStamp = undefined;
|
|
163
|
+
stamp(pending.turn, pending.step, pending.message);
|
|
122
164
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const applied = rawAppend(type, data);
|
|
152
|
-
if (queuedStamp !== undefined && step !== null) {
|
|
153
|
-
const pending = queuedStamp;
|
|
154
|
-
queuedStamp = undefined;
|
|
155
|
-
stamp(pending.turn, pending.step, pending.message);
|
|
156
|
-
}
|
|
157
|
-
return applied;
|
|
158
|
-
}
|
|
159
|
-
else if (type === 'step/end') {
|
|
160
|
-
const dataStep = data;
|
|
161
|
-
if (step === null && wrapClosedStep !== undefined && dataStep.step === wrapClosedStep) {
|
|
162
|
-
wrapClosedStep = undefined;
|
|
163
|
-
return { type, seq: session.snapshotEvents().length, time: Date.now(), data }; // the wrap already closed it
|
|
164
|
-
}
|
|
165
|
-
step = null;
|
|
166
|
-
if (dataStep.step !== undefined)
|
|
167
|
-
nextStep = dataStep.step + 1;
|
|
168
|
-
}
|
|
169
|
-
else if (type === 'user/message') {
|
|
170
|
-
ensureHead();
|
|
171
|
-
}
|
|
172
|
-
else if (type === 'system/message') {
|
|
173
|
-
// A direct adapter append (notices, bootstraps): give it the step
|
|
174
|
-
// context the reader demands — open the turn's next step when
|
|
175
|
-
// none is open and NORMALIZE the coordinates to that context
|
|
176
|
-
// (requireStep compares them for equality; a mismatched append
|
|
177
|
-
// is doomed otherwise). Surface ordering beyond the head rules
|
|
178
|
-
// stays the adapter's own responsibility.
|
|
179
|
-
if (step === null && turn !== null)
|
|
180
|
-
openWrapStep();
|
|
181
|
-
if (step !== null && turn !== null) {
|
|
182
|
-
const direct = data;
|
|
183
|
-
if (direct.turn !== turn || direct.step !== step)
|
|
184
|
-
data = { ...data, turn, step };
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return Reflect.apply(target.append, target, [type, data, opts]);
|
|
188
|
-
};
|
|
165
|
+
return applied;
|
|
166
|
+
}
|
|
167
|
+
else if (type === 'step/end') {
|
|
168
|
+
const dataStep = data;
|
|
169
|
+
if (step === null && wrapClosedStep !== undefined && dataStep.step === wrapClosedStep) {
|
|
170
|
+
wrapClosedStep = undefined;
|
|
171
|
+
return { type, seq: session.snapshotEvents().length, time: Date.now(), data }; // the wrap already closed it
|
|
172
|
+
}
|
|
173
|
+
step = null;
|
|
174
|
+
if (dataStep.step !== undefined)
|
|
175
|
+
nextStep = dataStep.step + 1;
|
|
176
|
+
}
|
|
177
|
+
else if (type === 'user/message') {
|
|
178
|
+
ensureHead();
|
|
179
|
+
}
|
|
180
|
+
else if (type === 'system/message') {
|
|
181
|
+
// A direct adapter append (notices, bootstraps): give it the step
|
|
182
|
+
// context the reader demands — open the turn's next step when
|
|
183
|
+
// none is open and NORMALIZE the coordinates to that context
|
|
184
|
+
// (requireStep compares them for equality; a mismatched append
|
|
185
|
+
// is doomed otherwise). Surface ordering beyond the head rules
|
|
186
|
+
// stays the adapter's own responsibility.
|
|
187
|
+
if (step === null && turn !== null)
|
|
188
|
+
openWrapStep();
|
|
189
|
+
if (step !== null && turn !== null) {
|
|
190
|
+
const direct = data;
|
|
191
|
+
if (direct.turn !== turn || direct.step !== step)
|
|
192
|
+
data = { ...data, turn, step };
|
|
189
193
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
}
|
|
195
|
+
return rawAppendFull(type, data, opts);
|
|
196
|
+
};
|
|
197
|
+
// Install the co-writer as OWN PROPERTIES on the session itself. The
|
|
198
|
+
// `append` shadow covers every holder of the object (the adapter's Agent
|
|
199
|
+
// AND upstream services that resolved the session from the store); both
|
|
200
|
+
// properties are non-enumerable so scans/serialization of the session see
|
|
201
|
+
// nothing, and writable/configurable so it stays an ordinary instance.
|
|
202
|
+
Object.defineProperty(session, 'append', {
|
|
203
|
+
value: interceptAppend, writable: true, configurable: true, enumerable: false,
|
|
204
|
+
});
|
|
205
|
+
Object.defineProperty(session, 'stampSystemPrompt', {
|
|
206
|
+
value: (turnArg, stepArg, message) => { stamp(turnArg, stepArg, message); },
|
|
207
|
+
writable: true, configurable: true, enumerable: false,
|
|
193
208
|
});
|
|
209
|
+
return session;
|
|
194
210
|
}
|