dsh-openwrite 0.2.27 → 0.2.33
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/LICENSE +1 -1
- package/README.md +55 -6
- package/THIRD_PARTY_NOTICES.md +4 -3
- package/companions.mjs +508 -0
- package/cordis.patch.yml +0 -2
- package/docs/CLOSED_ISSUE_FOLLOWUPS.md +5 -3
- package/docs/COMPANION_PLUGINS.md +142 -0
- package/docs/CONTEXT_SLOTS.md +60 -0
- package/docs/COST_MEASUREMENT.md +2 -2
- package/docs/DEVELOPMENT.md +6 -11
- package/docs/DSH_STORE.md +14 -2
- package/docs/EDITOR_SAFETY_REPAIRS.md +17 -0
- package/docs/INSTALL.md +112 -4
- package/docs/ISSUES_121_123.md +97 -0
- package/docs/ISSUES_140_142.md +58 -0
- package/docs/ISSUES_149_150_151.md +77 -0
- package/docs/ISSUES_98_100.md +2 -0
- package/docs/ISSUE_123_FOLLOWUP.md +55 -0
- package/docs/ISSUE_146_REVIEW_EVIDENCE.md +53 -0
- package/docs/LEARNING.md +1 -1
- package/docs/MOBILE_READINESS.md +62 -0
- package/docs/PLUGIN_MAINTENANCE.md +1 -3
- package/docs/RELEASE_ACCEPTANCE.md +90 -3
- package/docs/REVIEW_ROUND_22.md +67 -0
- package/docs/REVIEW_ROUND_23.md +48 -0
- package/docs/REVIEW_ROUND_25.md +51 -0
- package/docs/SELECTION_UPGRADE_REPAIRS.md +16 -0
- package/docs/TOOLS.md +933 -0
- package/docs/WORKFLOWS.md +5 -5
- package/package.json +18 -21
- package/packages/openwrite-bridge/lib/client.d.ts +0 -1
- package/packages/openwrite-bridge/lib/client.js +90 -9
- package/packages/openwrite-bridge/lib/contracts-generated.js +2 -1
- package/packages/openwrite-bridge/lib/dog-delivery.d.ts +1 -0
- package/packages/openwrite-bridge/lib/dog-delivery.js +10 -4
- package/packages/openwrite-bridge/lib/dog-review.js +15 -3
- package/packages/openwrite-bridge/lib/domain.d.ts +27 -0
- package/packages/openwrite-bridge/lib/domain.js +250 -29
- package/packages/openwrite-bridge/lib/host-llm.d.ts +188 -0
- package/packages/openwrite-bridge/lib/host-llm.js +657 -0
- package/packages/openwrite-bridge/lib/host-web.d.ts +61 -0
- package/packages/openwrite-bridge/lib/host-web.js +166 -0
- package/packages/openwrite-bridge/lib/index.d.ts +4 -0
- package/packages/openwrite-bridge/lib/index.js +150 -6
- package/packages/openwrite-bridge/lib/managed-runtime.d.ts +47 -2
- package/packages/openwrite-bridge/lib/managed-runtime.js +179 -35
- package/packages/openwrite-bridge/lib/tool-policy.js +39 -12
- package/packages/openwrite-bridge/lib/tools.js +1238 -1219
- package/packages/openwrite-bridge/package.json +7 -5
- package/packages/studio-panel/lib/client.js +116667 -114773
- package/packages/studio-panel/lib/client.js.map +1 -1
- package/packages/studio-panel/lib/types/client/LaunchOpenWrite.d.ts +10 -0
- package/packages/studio-panel/lib/types/client/ModelView.d.ts +28 -4
- package/packages/studio-panel/lib/types/client/OpenWriteSettings.d.ts +64 -0
- package/packages/studio-panel/lib/types/client/SceneWorkbench.d.ts +2 -0
- package/packages/studio-panel/lib/types/client/SearchSettings.d.ts +2 -0
- package/packages/studio-panel/lib/types/client/SerialWritingView.d.ts +2 -1
- package/packages/studio-panel/lib/types/client/TurnMutationSummary.d.ts +2 -0
- package/packages/studio-panel/lib/types/client/VditorBody.d.ts +8 -2
- package/packages/studio-panel/lib/types/client/api.d.ts +41 -2
- package/packages/studio-panel/lib/types/client/browser-download.d.ts +4 -0
- package/packages/studio-panel/lib/types/client/companions.d.ts +46 -0
- package/packages/studio-panel/lib/types/client/dto.d.ts +22 -0
- package/packages/studio-panel/lib/types/client/locales.d.ts +1 -1
- package/packages/studio-panel/lib/types/client/manuscript-annotations.d.ts +2 -1
- package/packages/studio-panel/lib/types/client/manuscript-overlay.d.ts +2 -1
- package/packages/studio-panel/lib/types/client/manuscript-selection.d.ts +18 -5
- package/packages/studio-panel/lib/types/client/selection-coordinates.d.ts +15 -0
- package/packages/studio-panel/lib/types/client/workspace-chrome.d.ts +41 -0
- package/packages/studio-panel/package.json +5 -3
- package/plugin.mjs +159 -20
- package/preset-definition.mjs +144 -4
- package/presets/openwrite/agent.cordis.yml +7 -9
- package/presets/openwrite/ops-integration.mjs +28 -0
- package/presets/openwrite/preset.yml +2 -1
- package/presets/openwrite/skills/canon/SKILL.md +3 -3
- package/presets/openwrite/skills/delivery-artifact-query/SKILL.md +41 -0
- package/presets/openwrite/skills/dialoguequality/SKILL.md +16 -17
- package/presets/openwrite/skills/dog-delivery-verification/SKILL.md +113 -0
- package/presets/openwrite/skills/export-book/SKILL.md +3 -3
- package/presets/openwrite/skills/foreshadow/SKILL.md +1 -1
- package/presets/openwrite/skills/foreshadowing-system/SKILL.md +16 -25
- package/presets/openwrite/skills/import-artifact-query/SKILL.md +30 -0
- package/presets/openwrite/skills/learn/SKILL.md +3 -3
- package/presets/openwrite/skills/novel-creator/SKILL.md +10 -10
- package/presets/openwrite/skills/novel-reviewer/SKILL.md +11 -11
- package/presets/openwrite/skills/progress/SKILL.md +1 -1
- package/presets/openwrite/skills/review-artifact-query/SKILL.md +41 -0
- package/presets/openwrite/skills/review-chapter/SKILL.md +2 -2
- package/presets/openwrite/skills/revise-span/SKILL.md +5 -5
- package/presets/openwrite/skills/style-system/SKILL.md +13 -6
- package/presets/openwrite/skills/truth-validation/SKILL.md +9 -12
- package/presets/openwrite/skills/workflow-manager/SKILL.md +13 -13
- package/presets/openwrite/skills/world-query/SKILL.md +16 -11
- package/presets/openwrite/skills/write-next/SKILL.md +1 -1
- package/release/{openwrite-5.8.16-py3-none-any.whl → openwrite-5.8.30-py3-none-any.whl} +0 -0
- package/release/runtime-manifest.json +4 -12
- package/release/source.json +21 -21
- package/release/wheels/licenses/OPENSSL-3.6.3-LICENSE.txt +225 -0
- package/scripts/maintenance.mjs +67 -7
- package/scripts/plugin-doctor.mjs +179 -0
- package/scripts/prepare.mjs +11 -2
- package/scripts/safe-upgrade.mjs +141 -13
- package/dog-tools.mjs +0 -11
- package/presets/openwrite/skills/dog-delivery-query/SKILL.md +0 -42
- package/presets/openwrite/skills/dog-import-query/SKILL.md +0 -29
- package/presets/openwrite/skills/dog-review-query/SKILL.md +0 -42
- package/scripts/dog/delivery-stage.js +0 -32
- package/scripts/dog/import-chapter.js +0 -20
- package/scripts/dog/import-record.js +0 -35
- package/scripts/dog/review-dimension.js +0 -41
- package/scripts/dog/review-record.js +0 -42
- package/vendor/dsh-dog/LICENSE +0 -29
- package/vendor/dsh-dog/README.md +0 -114
- package/vendor/dsh-dog/UPSTREAM.md +0 -30
- package/vendor/dsh-dog/cordis.patch.yml +0 -14
- package/vendor/dsh-dog/lib/client.js +0 -2960
- package/vendor/dsh-dog/lib/client.js.map +0 -1
- package/vendor/dsh-dog/lib/core-BAlgZpLq.js +0 -2074
- package/vendor/dsh-dog/lib/core-BiEBMLz3.d.ts +0 -495
- package/vendor/dsh-dog/lib/core.d.ts +0 -2
- package/vendor/dsh-dog/lib/core.js +0 -2
- package/vendor/dsh-dog/lib/index.d.ts +0 -143
- package/vendor/dsh-dog/lib/index.js +0 -1279
- package/vendor/dsh-dog/package.json +0 -110
- package/vendor/dsh-dog/schemas/schema-0.2/graph.schema.json +0 -139
- package/vendor/dsh-dog/schemas/schema-0.2/report.schema.json +0 -87
- package/vendor/dsh-dog/schemas/schema-0.2/run.schema.json +0 -259
- package/vendor/dsh-dog/schemas/schema-0.2/runtime-event.schema.json +0 -105
- package/vendor/dsh-dog/schemas/schema-0.2/verification.schema.json +0 -40
|
@@ -1,2960 +0,0 @@
|
|
|
1
|
-
window.__ModuleLoader__.load({
|
|
2
|
-
id: "@dsh-external/dsh-dog",
|
|
3
|
-
factory: (require) => {
|
|
4
|
-
var module = { exports: {} };
|
|
5
|
-
var exports = module.exports;
|
|
6
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
let react = require("react");
|
|
8
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
-
//#region src/debug-contract.ts
|
|
10
|
-
/**
|
|
11
|
-
* Dedicated debugger channel. It is served by this plugin directly on the Web
|
|
12
|
-
* carrier (see serveDogDebugRpc): Connection's generic channel registry mounts
|
|
13
|
-
* its HTTP route through the Connection plugin's own context, which only sees
|
|
14
|
-
* `webServer` when a bundle patch injects it into the shared connection row —
|
|
15
|
-
* and per-key patch semantics make any such patch clobber other bundles
|
|
16
|
-
* (OpenWrite issue #81), while the shared `/api` channel already belongs to
|
|
17
|
-
* the host's Typert gateway. The wire envelope mirrors Connection's, so the
|
|
18
|
-
* browser side keeps using its stock `connection.rpc.call`.
|
|
19
|
-
*/
|
|
20
|
-
const DOG_DEBUG_RPC_CHANNEL = "/dog-rpc";
|
|
21
|
-
const DOG_DEBUG_SNAPSHOT_ENDPOINT = "snapshot";
|
|
22
|
-
const DOG_RUNTIME_TRACE_ENDPOINT = "goal-runtime";
|
|
23
|
-
//#endregion
|
|
24
|
-
//#region src/client/agentTelemetry.ts
|
|
25
|
-
/** Stable, de-duplicated bindings for one goal. */
|
|
26
|
-
function goalAgentRefs(run, goalId) {
|
|
27
|
-
if (run === void 0) return [];
|
|
28
|
-
const seen = /* @__PURE__ */ new Set();
|
|
29
|
-
const result = [];
|
|
30
|
-
for (const ref of run.goals[goalId]?.agentSessions ?? []) {
|
|
31
|
-
if (seen.has(ref.sessionId)) continue;
|
|
32
|
-
seen.add(ref.sessionId);
|
|
33
|
-
result.push(ref);
|
|
34
|
-
}
|
|
35
|
-
return result;
|
|
36
|
-
}
|
|
37
|
-
/** Stable, de-duplicated Agent bindings across a run. */
|
|
38
|
-
function runAgentRefs(run) {
|
|
39
|
-
if (run === void 0) return [];
|
|
40
|
-
const seen = /* @__PURE__ */ new Set();
|
|
41
|
-
const result = [];
|
|
42
|
-
for (const goal of Object.values(run.goals)) for (const ref of goal.agentSessions ?? []) {
|
|
43
|
-
if (seen.has(ref.sessionId)) continue;
|
|
44
|
-
seen.add(ref.sessionId);
|
|
45
|
-
result.push(ref);
|
|
46
|
-
}
|
|
47
|
-
return result;
|
|
48
|
-
}
|
|
49
|
-
/** Direct parent catalogs that can resolve bound subagent sessions in the host UI. */
|
|
50
|
-
function agentParentSessionIds(snapshot) {
|
|
51
|
-
const parents = /* @__PURE__ */ new Set();
|
|
52
|
-
for (const revision of snapshot.graphs) for (const run of revision.runs) for (const ref of runAgentRefs(run)) if (ref.parentSessionId !== void 0) parents.add(ref.parentSessionId);
|
|
53
|
-
return [...parents];
|
|
54
|
-
}
|
|
55
|
-
/** Merge one persisted binding with the newest host-projected session facts. */
|
|
56
|
-
function goalAgentTelemetry(ref, sessions, now = Date.now()) {
|
|
57
|
-
const summary = sessions.byId[ref.sessionId];
|
|
58
|
-
const tokens = summary === void 0 ? void 0 : sessionTokenTotal(summary);
|
|
59
|
-
const durationMs = summary === void 0 ? void 0 : sessionDuration(summary, now);
|
|
60
|
-
return {
|
|
61
|
-
ref,
|
|
62
|
-
label: summary?.displayTitle ?? summary?.title ?? `${capitalize(ref.role)} Agent`,
|
|
63
|
-
available: summary !== void 0,
|
|
64
|
-
running: summary?.running ?? false,
|
|
65
|
-
needsInput: sessions.pendingInteractions?.has(ref.sessionId) ?? false,
|
|
66
|
-
...tokens === void 0 ? {} : { tokens },
|
|
67
|
-
...durationMs === void 0 ? {} : { durationMs }
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
/** DoG-level Agent counts and de-duplicated token usage. */
|
|
71
|
-
function summarizeRunAgents(run, sessions, now = Date.now()) {
|
|
72
|
-
const refs = runAgentRefs(run);
|
|
73
|
-
let visible = 0;
|
|
74
|
-
let running = 0;
|
|
75
|
-
let tokens = 0;
|
|
76
|
-
let measured = 0;
|
|
77
|
-
for (const ref of refs) {
|
|
78
|
-
const telemetry = goalAgentTelemetry(ref, sessions, now);
|
|
79
|
-
if (telemetry.available) visible += 1;
|
|
80
|
-
if (telemetry.running) running += 1;
|
|
81
|
-
if (telemetry.tokens !== void 0) {
|
|
82
|
-
tokens += telemetry.tokens;
|
|
83
|
-
measured += 1;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
linked: refs.length,
|
|
88
|
-
visible,
|
|
89
|
-
running,
|
|
90
|
-
...measured === 0 ? {} : { tokens },
|
|
91
|
-
partialTokens: measured > 0 && measured < refs.length
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
/** Count goals that reached any terminal state, independently of success. */
|
|
95
|
-
function settledGoalCount(run) {
|
|
96
|
-
if (run === void 0) return 0;
|
|
97
|
-
return Object.values(run.goals).filter((result) => isTerminalGoalState(result.state)).length;
|
|
98
|
-
}
|
|
99
|
-
function isTerminalGoalState(state) {
|
|
100
|
-
return state !== "pending" && state !== "running";
|
|
101
|
-
}
|
|
102
|
-
function sessionTokenTotal(summary) {
|
|
103
|
-
const usage = summary.projectionValues?.tokenUsage;
|
|
104
|
-
if (!isRecord$1(usage)) return void 0;
|
|
105
|
-
const uncached = finiteNonNegative(usage.uncachedInputTokens);
|
|
106
|
-
const output = finiteNonNegative(usage.outputTokens);
|
|
107
|
-
const cacheRead = finiteNonNegative(usage.cacheReadTokens);
|
|
108
|
-
const cacheWrite = finiteNonNegative(usage.cacheWriteTokens);
|
|
109
|
-
if (uncached === void 0 || output === void 0 || cacheRead === void 0 || cacheWrite === void 0) return void 0;
|
|
110
|
-
return uncached + output + cacheRead + cacheWrite;
|
|
111
|
-
}
|
|
112
|
-
function sessionDuration(summary, now) {
|
|
113
|
-
const timing = summary.projectionValues?.subagentTiming;
|
|
114
|
-
if (!isRecord$1(timing)) return void 0;
|
|
115
|
-
const settledMs = finiteNonNegative(timing.settledMs);
|
|
116
|
-
if (settledMs === void 0) return void 0;
|
|
117
|
-
if (!isRecord$1(timing.active)) return settledMs;
|
|
118
|
-
const since = finiteNumber(timing.active.since);
|
|
119
|
-
const through = finiteNumber(timing.active.through);
|
|
120
|
-
if (since === void 0 || through === void 0) return settledMs;
|
|
121
|
-
const end = summary.running ? now : through;
|
|
122
|
-
return settledMs + Math.max(0, end - since);
|
|
123
|
-
}
|
|
124
|
-
function finiteNonNegative(value) {
|
|
125
|
-
const number = finiteNumber(value);
|
|
126
|
-
return number === void 0 || number < 0 ? void 0 : number;
|
|
127
|
-
}
|
|
128
|
-
function finiteNumber(value) {
|
|
129
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
130
|
-
}
|
|
131
|
-
function isRecord$1(value) {
|
|
132
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
133
|
-
}
|
|
134
|
-
function capitalize(value) {
|
|
135
|
-
return value.length === 0 ? value : `${value[0]?.toUpperCase() ?? ""}${value.slice(1)}`;
|
|
136
|
-
}
|
|
137
|
-
const HORIZONTAL_GAP = 44;
|
|
138
|
-
const CANVAS_PADDING_Y = 48;
|
|
139
|
-
const MIN_CANVAS_WIDTH = 700;
|
|
140
|
-
/** Lay containment levels top-to-bottom while retaining declared node order within a level. */
|
|
141
|
-
function layoutDag(graph) {
|
|
142
|
-
const parents = /* @__PURE__ */ new Map();
|
|
143
|
-
for (const edge of graph.contains) {
|
|
144
|
-
const values = parents.get(edge.child) ?? [];
|
|
145
|
-
values.push(edge.parent);
|
|
146
|
-
parents.set(edge.child, values);
|
|
147
|
-
}
|
|
148
|
-
const depths = /* @__PURE__ */ new Map();
|
|
149
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
150
|
-
const depthOf = (id) => {
|
|
151
|
-
const known = depths.get(id);
|
|
152
|
-
if (known !== void 0) return known;
|
|
153
|
-
if (id === graph.root) {
|
|
154
|
-
depths.set(id, 0);
|
|
155
|
-
return 0;
|
|
156
|
-
}
|
|
157
|
-
if (visiting.has(id)) return 0;
|
|
158
|
-
visiting.add(id);
|
|
159
|
-
const incoming = parents.get(id) ?? [];
|
|
160
|
-
const depth = incoming.length === 0 ? 0 : Math.max(...incoming.map((parent) => depthOf(parent) + 1));
|
|
161
|
-
visiting.delete(id);
|
|
162
|
-
depths.set(id, depth);
|
|
163
|
-
return depth;
|
|
164
|
-
};
|
|
165
|
-
const layers = /* @__PURE__ */ new Map();
|
|
166
|
-
for (const id of Object.keys(graph.nodes)) {
|
|
167
|
-
const depth = depthOf(id);
|
|
168
|
-
const layer = layers.get(depth) ?? [];
|
|
169
|
-
layer.push(id);
|
|
170
|
-
layers.set(depth, layer);
|
|
171
|
-
}
|
|
172
|
-
const layerEntries = [...layers.entries()].sort(([left], [right]) => left - right);
|
|
173
|
-
const widest = Math.max(1, ...layerEntries.map(([, ids]) => ids.length));
|
|
174
|
-
const naturalWidth = widest * 218 + Math.max(0, widest - 1) * HORIZONTAL_GAP + 112;
|
|
175
|
-
const width = Math.max(MIN_CANVAS_WIDTH, naturalWidth);
|
|
176
|
-
const positioned = [];
|
|
177
|
-
for (const [depth, ids] of layerEntries) {
|
|
178
|
-
const startX = (width - (ids.length * 218 + Math.max(0, ids.length - 1) * HORIZONTAL_GAP)) / 2;
|
|
179
|
-
ids.forEach((id, index) => positioned.push({
|
|
180
|
-
id,
|
|
181
|
-
x: startX + index * 262,
|
|
182
|
-
y: CANVAS_PADDING_Y + depth * 180,
|
|
183
|
-
width: 218,
|
|
184
|
-
height: 88,
|
|
185
|
-
depth
|
|
186
|
-
}));
|
|
187
|
-
}
|
|
188
|
-
const height = 184 + Math.max(0, ...positioned.map((node) => node.depth)) * 180;
|
|
189
|
-
const byId = new Map(positioned.map((node) => [node.id, node]));
|
|
190
|
-
const edges = [];
|
|
191
|
-
graph.contains.forEach((edge, index) => {
|
|
192
|
-
const source = byId.get(edge.parent);
|
|
193
|
-
const target = byId.get(edge.child);
|
|
194
|
-
if (source === void 0 || target === void 0) return;
|
|
195
|
-
edges.push({
|
|
196
|
-
id: `contains:${index}:${edge.parent}:${edge.child}`,
|
|
197
|
-
kind: "contains",
|
|
198
|
-
source: edge.parent,
|
|
199
|
-
target: edge.child,
|
|
200
|
-
path: containmentPath(source, target)
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
graph.dependsOn.forEach((edge, index) => {
|
|
204
|
-
const source = byId.get(edge.source);
|
|
205
|
-
const target = byId.get(edge.target);
|
|
206
|
-
if (source === void 0 || target === void 0) return;
|
|
207
|
-
edges.push({
|
|
208
|
-
id: `depends:${index}:${edge.source}:${edge.target}`,
|
|
209
|
-
kind: "dependsOn",
|
|
210
|
-
source: edge.source,
|
|
211
|
-
target: edge.target,
|
|
212
|
-
path: dependencyPath(target, source, index)
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
return {
|
|
216
|
-
width,
|
|
217
|
-
height,
|
|
218
|
-
nodes: positioned,
|
|
219
|
-
edges
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
function containmentPath(source, target) {
|
|
223
|
-
const startX = source.x + source.width / 2;
|
|
224
|
-
const startY = source.y + source.height;
|
|
225
|
-
const endX = target.x + target.width / 2;
|
|
226
|
-
const endY = target.y;
|
|
227
|
-
const middleY = startY + (endY - startY) / 2;
|
|
228
|
-
return `M ${startX} ${startY} C ${startX} ${middleY}, ${endX} ${middleY}, ${endX} ${endY}`;
|
|
229
|
-
}
|
|
230
|
-
function dependencyPath(source, target, index) {
|
|
231
|
-
const sourceCenterX = source.x + source.width / 2;
|
|
232
|
-
const rightward = target.x + target.width / 2 >= sourceCenterX;
|
|
233
|
-
const startX = rightward ? source.x + source.width : source.x;
|
|
234
|
-
const endX = rightward ? target.x : target.x + target.width;
|
|
235
|
-
const startY = source.y + source.height / 2;
|
|
236
|
-
const endY = target.y + target.height / 2;
|
|
237
|
-
const bend = (rightward ? 1 : -1) * (54 + index % 3 * 12);
|
|
238
|
-
return `M ${startX} ${startY} C ${startX + bend} ${startY}, ${endX - bend} ${endY}, ${endX} ${endY}`;
|
|
239
|
-
}
|
|
240
|
-
//#endregion
|
|
241
|
-
//#region src/logic.ts
|
|
242
|
-
/**
|
|
243
|
-
* Parse and type-check the only expression language accepted by DoG.
|
|
244
|
-
* @param value - untrusted JSON value from a graph draft.
|
|
245
|
-
* @param allowedRefs - child IDs that the enclosing composite may reference.
|
|
246
|
-
* @param limits - expression size limits.
|
|
247
|
-
* @returns a typed AST or validation errors; never evaluates source text.
|
|
248
|
-
*/
|
|
249
|
-
function parseBoolExpr(value, allowedRefs, limits) {
|
|
250
|
-
const errors = [];
|
|
251
|
-
let nodeCount = 0;
|
|
252
|
-
function visit(candidate, depth, path) {
|
|
253
|
-
if (depth > limits.maxDepth) {
|
|
254
|
-
errors.push(`${path}: expression depth exceeds ${limits.maxDepth}`);
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
if (!isRecord(candidate)) {
|
|
258
|
-
errors.push(`${path}: expression must be an object`);
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
nodeCount += 1;
|
|
262
|
-
if (nodeCount > limits.maxNodes) {
|
|
263
|
-
errors.push(`expression exceeds ${limits.maxNodes} nodes`);
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const keys = Object.keys(candidate);
|
|
267
|
-
if (!Object.prototype.hasOwnProperty.call(candidate, "op") || keys.length === 0) {
|
|
268
|
-
errors.push(`${path}: expression requires exactly one operator`);
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
const op = candidate.op;
|
|
272
|
-
if (typeof op !== "string") {
|
|
273
|
-
errors.push(`${path}.op: operator must be a string`);
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
if (op === "ref") return parseRef(candidate, allowedRefs, errors, path);
|
|
277
|
-
if (op === "not") return parseNot(candidate, depth, path, visit, errors);
|
|
278
|
-
if (op === "all" || op === "any") return parseNary(candidate, op, depth, path, visit, errors);
|
|
279
|
-
if (op === "atLeast") return parseThreshold(candidate, depth, path, visit, errors);
|
|
280
|
-
errors.push(`${path}.op: unsupported operator ${JSON.stringify(op)}`);
|
|
281
|
-
}
|
|
282
|
-
const expression = visit(value, 0, "$");
|
|
283
|
-
return errors.length === 0 && expression !== void 0 ? {
|
|
284
|
-
expression,
|
|
285
|
-
errors
|
|
286
|
-
} : { errors };
|
|
287
|
-
}
|
|
288
|
-
function parseRef(candidate, allowedRefs, errors, path) {
|
|
289
|
-
if (Object.keys(candidate).length !== 2 || typeof candidate.id !== "string" || candidate.id.length === 0) {
|
|
290
|
-
errors.push(`${path}: ref requires only a non-empty string id`);
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
if (!allowedRefs.has(candidate.id)) {
|
|
294
|
-
errors.push(`${path}.id: ${JSON.stringify(candidate.id)} is not a containment child`);
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
return {
|
|
298
|
-
op: "ref",
|
|
299
|
-
id: candidate.id
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
function parseNot(candidate, depth, path, visit, errors) {
|
|
303
|
-
if (Object.keys(candidate).length !== 2 || !Object.prototype.hasOwnProperty.call(candidate, "item")) {
|
|
304
|
-
errors.push(`${path}: not requires only item`);
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
const item = visit(candidate.item, depth + 1, `${path}.item`);
|
|
308
|
-
return item === void 0 ? void 0 : {
|
|
309
|
-
op: "not",
|
|
310
|
-
item
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
function parseNary(candidate, op, depth, path, visit, errors) {
|
|
314
|
-
if (Object.keys(candidate).length !== 2 || !Array.isArray(candidate.items) || candidate.items.length === 0) {
|
|
315
|
-
errors.push(`${path}: ${op} requires only a non-empty items array`);
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
const items = [];
|
|
319
|
-
for (const [index, itemValue] of candidate.items.entries()) {
|
|
320
|
-
const item = visit(itemValue, depth + 1, `${path}.items[${index}]`);
|
|
321
|
-
if (item !== void 0) items.push(item);
|
|
322
|
-
}
|
|
323
|
-
if (items.length !== candidate.items.length) return void 0;
|
|
324
|
-
return op === "all" ? {
|
|
325
|
-
op,
|
|
326
|
-
items
|
|
327
|
-
} : {
|
|
328
|
-
op,
|
|
329
|
-
items
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
function parseThreshold(candidate, depth, path, visit, errors) {
|
|
333
|
-
if (Object.keys(candidate).length !== 3 || !Array.isArray(candidate.items) || candidate.items.length === 0 || typeof candidate.count !== "number" || !Number.isInteger(candidate.count) || candidate.count < 1 || candidate.count > candidate.items.length) {
|
|
334
|
-
errors.push(`${path}: atLeast requires count and a non-empty items array with 1 <= count <= items.length`);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
const items = [];
|
|
338
|
-
for (const [index, itemValue] of candidate.items.entries()) {
|
|
339
|
-
const item = visit(itemValue, depth + 1, `${path}.items[${index}]`);
|
|
340
|
-
if (item !== void 0) items.push(item);
|
|
341
|
-
}
|
|
342
|
-
if (items.length !== candidate.items.length) return void 0;
|
|
343
|
-
return {
|
|
344
|
-
op: "atLeast",
|
|
345
|
-
count: candidate.count,
|
|
346
|
-
items
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
function isRecord(value) {
|
|
350
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
351
|
-
}
|
|
352
|
-
//#endregion
|
|
353
|
-
//#region src/model.ts
|
|
354
|
-
function isJsonValue(value) {
|
|
355
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
356
|
-
if (typeof value === "number") return Number.isFinite(value);
|
|
357
|
-
if (Array.isArray(value)) return value.every(isJsonValue);
|
|
358
|
-
if (typeof value !== "object") return false;
|
|
359
|
-
return Object.values(value).every(isJsonValue);
|
|
360
|
-
}
|
|
361
|
-
//#endregion
|
|
362
|
-
//#region src/graph.ts
|
|
363
|
-
/** Graph parser, structural validator, and cycle checker for DoG v0.2. */
|
|
364
|
-
const ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
365
|
-
/** Structured validation failure at the model-to-core boundary. */
|
|
366
|
-
var DogValidationError = class extends Error {
|
|
367
|
-
errors;
|
|
368
|
-
constructor(errors) {
|
|
369
|
-
super(`invalid DoG graph: ${errors.join("; ")}`);
|
|
370
|
-
this.name = "DogValidationError";
|
|
371
|
-
this.errors = errors;
|
|
372
|
-
}
|
|
373
|
-
};
|
|
374
|
-
/** Parse an untrusted graph value into a normalized, acyclic DoG graph. */
|
|
375
|
-
function parseGraph(value, limits) {
|
|
376
|
-
const errors = [];
|
|
377
|
-
const root = asRecord(value, "$", errors);
|
|
378
|
-
if (root === void 0) throw new DogValidationError(errors);
|
|
379
|
-
checkExactKeys(root, [
|
|
380
|
-
"schemaVersion",
|
|
381
|
-
"id",
|
|
382
|
-
"root",
|
|
383
|
-
"nodes",
|
|
384
|
-
"contains",
|
|
385
|
-
"dependsOn"
|
|
386
|
-
], "$", errors);
|
|
387
|
-
if (root.schemaVersion !== "0.9") errors.push(`$.schemaVersion: expected 0.9`);
|
|
388
|
-
const graphId = parseId(root.id, "$.id", errors);
|
|
389
|
-
const rootId = parseId(root.root, "$.root", errors);
|
|
390
|
-
const nodes = parseNodes(root.nodes, limits, errors);
|
|
391
|
-
const contains = parseContains(root.contains, errors);
|
|
392
|
-
const dependsOn = parseDependencies(root.dependsOn, errors);
|
|
393
|
-
if (graphId === void 0 || rootId === void 0 || nodes === void 0 || contains === void 0 || dependsOn === void 0) throw new DogValidationError(errors);
|
|
394
|
-
validateGraphReferences(rootId, nodes, contains, dependsOn, limits, errors);
|
|
395
|
-
validateAcyclic(nodes, contains, dependsOn, errors);
|
|
396
|
-
if (errors.length > 0) throw new DogValidationError(errors);
|
|
397
|
-
return {
|
|
398
|
-
schemaVersion: "0.9",
|
|
399
|
-
id: graphId,
|
|
400
|
-
root: rootId,
|
|
401
|
-
nodes,
|
|
402
|
-
contains,
|
|
403
|
-
dependsOn
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
function parseNodes(value, limits, errors) {
|
|
407
|
-
const record = asRecord(value, "$.nodes", errors);
|
|
408
|
-
if (record === void 0) return void 0;
|
|
409
|
-
const ids = Object.keys(record);
|
|
410
|
-
if (ids.length === 0) errors.push("$.nodes: must not be empty");
|
|
411
|
-
if (ids.length > limits.maxGraphNodes) errors.push(`$.nodes: exceeds ${limits.maxGraphNodes} nodes`);
|
|
412
|
-
const nodes = {};
|
|
413
|
-
for (const id of ids) {
|
|
414
|
-
if (!ID_PATTERN.test(id)) errors.push(`$.nodes.${id}: invalid goal ID`);
|
|
415
|
-
const node = asRecord(record[id], `$.nodes.${id}`, errors);
|
|
416
|
-
if (node === void 0) continue;
|
|
417
|
-
checkExactKeys(node, [
|
|
418
|
-
"kind",
|
|
419
|
-
"title",
|
|
420
|
-
"constraint",
|
|
421
|
-
"target",
|
|
422
|
-
"completion",
|
|
423
|
-
"verifier"
|
|
424
|
-
], `$.nodes.${id}`, errors);
|
|
425
|
-
const kind = parseEnum(node.kind, ["leaf", "composite"], `$.nodes.${id}.kind`, errors);
|
|
426
|
-
const title = parseNonEmptyString(node.title, `$.nodes.${id}.title`, errors);
|
|
427
|
-
const constraint = parseEnum(node.constraint, ["hard", "soft"], `$.nodes.${id}.constraint`, errors);
|
|
428
|
-
const target = parseNonEmptyString(node.target, `$.nodes.${id}.target`, errors);
|
|
429
|
-
const verifier = parseVerifier(node.verifier, `$.nodes.${id}.verifier`, errors);
|
|
430
|
-
if (kind === void 0 || title === void 0 || constraint === void 0 || target === void 0) continue;
|
|
431
|
-
if (kind === "leaf" && verifier === void 0) errors.push(`$.nodes.${id}: leaf requires verifier`);
|
|
432
|
-
if (kind === "composite" && verifier !== void 0) {}
|
|
433
|
-
if (kind === "composite" && node.completion === void 0) errors.push(`$.nodes.${id}: composite requires completion`);
|
|
434
|
-
if (kind === "leaf" && node.completion !== void 0) errors.push(`$.nodes.${id}: leaf cannot declare completion`);
|
|
435
|
-
nodes[id] = {
|
|
436
|
-
kind,
|
|
437
|
-
title,
|
|
438
|
-
constraint,
|
|
439
|
-
target,
|
|
440
|
-
...verifier === void 0 ? {} : { verifier },
|
|
441
|
-
...kind === "composite" && node.completion !== void 0 ? { completion: node.completion } : {}
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
return nodes;
|
|
445
|
-
}
|
|
446
|
-
function parseContains(value, errors) {
|
|
447
|
-
if (!Array.isArray(value)) {
|
|
448
|
-
errors.push("$.contains: must be an array");
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
const edges = [];
|
|
452
|
-
for (const [index, candidate] of value.entries()) {
|
|
453
|
-
const path = `$.contains[${index}]`;
|
|
454
|
-
const record = asRecord(candidate, path, errors);
|
|
455
|
-
if (record === void 0) continue;
|
|
456
|
-
checkExactKeys(record, [
|
|
457
|
-
"parent",
|
|
458
|
-
"child",
|
|
459
|
-
"required",
|
|
460
|
-
"failure",
|
|
461
|
-
"degradeTo"
|
|
462
|
-
], path, errors);
|
|
463
|
-
const parent = parseId(record.parent, `${path}.parent`, errors);
|
|
464
|
-
const child = parseId(record.child, `${path}.child`, errors);
|
|
465
|
-
const required = parseBoolean(record.required, `${path}.required`, errors);
|
|
466
|
-
const failure = parseEnum(record.failure, [
|
|
467
|
-
"fatal",
|
|
468
|
-
"tolerable",
|
|
469
|
-
"degrade"
|
|
470
|
-
], `${path}.failure`, errors);
|
|
471
|
-
const degradeTo = record.degradeTo === void 0 ? void 0 : parseId(record.degradeTo, `${path}.degradeTo`, errors);
|
|
472
|
-
if (failure !== "degrade" && degradeTo !== void 0) errors.push(`${path}.degradeTo: only valid with failure=degrade`);
|
|
473
|
-
if (failure === "degrade" && degradeTo === void 0) errors.push(`${path}: failure=degrade requires degradeTo`);
|
|
474
|
-
if (parent !== void 0 && child !== void 0 && required !== void 0 && failure !== void 0) edges.push({
|
|
475
|
-
parent,
|
|
476
|
-
child,
|
|
477
|
-
required,
|
|
478
|
-
failure,
|
|
479
|
-
...degradeTo === void 0 ? {} : { degradeTo }
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
return edges;
|
|
483
|
-
}
|
|
484
|
-
function parseDependencies(value, errors) {
|
|
485
|
-
if (!Array.isArray(value)) {
|
|
486
|
-
errors.push("$.dependsOn: must be an array");
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
const edges = [];
|
|
490
|
-
for (const [index, candidate] of value.entries()) {
|
|
491
|
-
const path = `$.dependsOn[${index}]`;
|
|
492
|
-
const record = asRecord(candidate, path, errors);
|
|
493
|
-
if (record === void 0) continue;
|
|
494
|
-
checkExactKeys(record, [
|
|
495
|
-
"source",
|
|
496
|
-
"target",
|
|
497
|
-
"data"
|
|
498
|
-
], path, errors);
|
|
499
|
-
const source = parseId(record.source, `${path}.source`, errors);
|
|
500
|
-
const target = parseId(record.target, `${path}.target`, errors);
|
|
501
|
-
const data = parseStringArray(record.data, `${path}.data`, errors);
|
|
502
|
-
if (source !== void 0 && target !== void 0) edges.push({
|
|
503
|
-
source,
|
|
504
|
-
target,
|
|
505
|
-
...data === void 0 ? {} : { data }
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
return edges;
|
|
509
|
-
}
|
|
510
|
-
function parseVerifier(value, path, errors) {
|
|
511
|
-
if (value === void 0) return void 0;
|
|
512
|
-
const record = asRecord(value, path, errors);
|
|
513
|
-
if (record === void 0) return void 0;
|
|
514
|
-
const mode = parseEnum(record.mode, ["programmatic", "agentic"], `${path}.mode`, errors);
|
|
515
|
-
if (mode === void 0) return void 0;
|
|
516
|
-
if (mode === "programmatic") {
|
|
517
|
-
checkExactKeys(record, ["mode", "script"], path, errors);
|
|
518
|
-
const script = parseNonEmptyString(record.script, `${path}.script`, errors);
|
|
519
|
-
return script === void 0 ? void 0 : {
|
|
520
|
-
mode: "programmatic",
|
|
521
|
-
script
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
checkExactKeys(record, ["mode", "instruction"], path, errors);
|
|
525
|
-
const instruction = parseNonEmptyString(record.instruction, `${path}.instruction`, errors);
|
|
526
|
-
return instruction === void 0 ? void 0 : {
|
|
527
|
-
mode: "agentic",
|
|
528
|
-
instruction
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
function validateGraphReferences(root, nodes, contains, dependsOn, limits, errors) {
|
|
532
|
-
if (!Object.prototype.hasOwnProperty.call(nodes, root)) errors.push(`$.root: unknown node ${root}`);
|
|
533
|
-
const rootNode = nodes[root];
|
|
534
|
-
if (rootNode !== void 0 && rootNode.constraint !== "hard") errors.push("$.root: root goal must be a hard constraint");
|
|
535
|
-
const children = /* @__PURE__ */ new Map();
|
|
536
|
-
const edgeKeys = /* @__PURE__ */ new Set();
|
|
537
|
-
for (const edge of contains) {
|
|
538
|
-
const key = `${edge.parent}\u0000${edge.child}`;
|
|
539
|
-
if (edgeKeys.has(key)) errors.push(`$.contains: duplicate edge ${edge.parent}->${edge.child}`);
|
|
540
|
-
edgeKeys.add(key);
|
|
541
|
-
if (!Object.prototype.hasOwnProperty.call(nodes, edge.parent)) errors.push(`$.contains: unknown parent ${edge.parent}`);
|
|
542
|
-
if (!Object.prototype.hasOwnProperty.call(nodes, edge.child)) errors.push(`$.contains: unknown child ${edge.child}`);
|
|
543
|
-
const parent = nodes[edge.parent];
|
|
544
|
-
if (parent !== void 0 && parent.kind !== "composite") errors.push(`$.contains: ${edge.parent} is not composite`);
|
|
545
|
-
const siblings = children.get(edge.parent) ?? [];
|
|
546
|
-
siblings.push(edge.child);
|
|
547
|
-
children.set(edge.parent, siblings);
|
|
548
|
-
}
|
|
549
|
-
for (const edge of contains) if (edge.degradeTo === edge.child) errors.push(`$.contains: degradeTo cannot equal child ${edge.child}`);
|
|
550
|
-
else if (edge.degradeTo !== void 0 && !(children.get(edge.parent) ?? []).includes(edge.degradeTo)) errors.push(`$.contains: degradeTo ${edge.degradeTo} is not a child of ${edge.parent}`);
|
|
551
|
-
const dependencyKeys = /* @__PURE__ */ new Set();
|
|
552
|
-
for (const edge of dependsOn) {
|
|
553
|
-
const key = `${edge.source}\u0000${edge.target}`;
|
|
554
|
-
if (dependencyKeys.has(key)) errors.push(`$.dependsOn: duplicate edge ${edge.source}->${edge.target}`);
|
|
555
|
-
dependencyKeys.add(key);
|
|
556
|
-
if (edge.source === edge.target) errors.push(`$.dependsOn: self-dependency ${edge.source}`);
|
|
557
|
-
if (!Object.prototype.hasOwnProperty.call(nodes, edge.source)) errors.push(`$.dependsOn: unknown source ${edge.source}`);
|
|
558
|
-
if (!Object.prototype.hasOwnProperty.call(nodes, edge.target)) errors.push(`$.dependsOn: unknown target ${edge.target}`);
|
|
559
|
-
}
|
|
560
|
-
for (const [parent, node] of Object.entries(nodes)) {
|
|
561
|
-
if (node.kind !== "composite") continue;
|
|
562
|
-
const childIds = children.get(parent) ?? [];
|
|
563
|
-
if (childIds.length === 0) errors.push(`$.nodes.${parent}: composite requires at least one child`);
|
|
564
|
-
if (node.completion === void 0) {
|
|
565
|
-
errors.push(`$.nodes.${parent}.completion: missing completion expression`);
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
const parsed = parseBoolExpr(node.completion, new Set(childIds), {
|
|
569
|
-
maxNodes: limits.maxExpressionNodes,
|
|
570
|
-
maxDepth: limits.maxExpressionDepth
|
|
571
|
-
});
|
|
572
|
-
if (parsed.errors.length > 0) errors.push(...parsed.errors.map((error) => `$.nodes.${parent}.completion${error.slice(1)}`));
|
|
573
|
-
else if (parsed.expression !== void 0) nodes[parent] = {
|
|
574
|
-
...node,
|
|
575
|
-
completion: parsed.expression
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
|
-
const reachable = /* @__PURE__ */ new Set();
|
|
579
|
-
const queue = [root];
|
|
580
|
-
while (queue.length > 0) {
|
|
581
|
-
const current = queue.shift();
|
|
582
|
-
if (current === void 0 || reachable.has(current)) continue;
|
|
583
|
-
reachable.add(current);
|
|
584
|
-
for (const child of children.get(current) ?? []) queue.push(child);
|
|
585
|
-
}
|
|
586
|
-
for (const id of Object.keys(nodes)) if (!reachable.has(id)) errors.push(`$.nodes.${id}: unreachable from root through containment`);
|
|
587
|
-
}
|
|
588
|
-
function validateAcyclic(nodes, contains, dependsOn, errors) {
|
|
589
|
-
const outgoing = /* @__PURE__ */ new Map();
|
|
590
|
-
for (const id of Object.keys(nodes)) outgoing.set(id, []);
|
|
591
|
-
for (const edge of contains) outgoing.get(edge.parent)?.push(edge.child);
|
|
592
|
-
for (const edge of dependsOn) outgoing.get(edge.source)?.push(edge.target);
|
|
593
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
594
|
-
const visited = /* @__PURE__ */ new Set();
|
|
595
|
-
function visit(id, path) {
|
|
596
|
-
if (visiting.has(id)) {
|
|
597
|
-
errors.push(`graph contains a cycle: ${[...path, id].join(" -> ")}`);
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
if (visited.has(id)) return;
|
|
601
|
-
visiting.add(id);
|
|
602
|
-
for (const target of outgoing.get(id) ?? []) visit(target, [...path, id]);
|
|
603
|
-
visiting.delete(id);
|
|
604
|
-
visited.add(id);
|
|
605
|
-
}
|
|
606
|
-
for (const id of Object.keys(nodes)) visit(id, []);
|
|
607
|
-
}
|
|
608
|
-
function asRecord(value, path, errors) {
|
|
609
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
610
|
-
errors.push(`${path}: must be an object`);
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
return value;
|
|
614
|
-
}
|
|
615
|
-
function checkExactKeys(value, allowed, path, errors) {
|
|
616
|
-
const allowedSet = new Set(allowed);
|
|
617
|
-
for (const key of Object.keys(value)) if (!allowedSet.has(key)) errors.push(`${path}: unknown field ${key}`);
|
|
618
|
-
}
|
|
619
|
-
function parseId(value, path, errors) {
|
|
620
|
-
if (typeof value !== "string" || !ID_PATTERN.test(value)) {
|
|
621
|
-
errors.push(`${path}: must be an ASCII ID matching ${ID_PATTERN.source}`);
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
return value;
|
|
625
|
-
}
|
|
626
|
-
function parseNonEmptyString(value, path, errors) {
|
|
627
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
628
|
-
errors.push(`${path}: must be a non-empty string`);
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
return value;
|
|
632
|
-
}
|
|
633
|
-
function parseBoolean(value, path, errors) {
|
|
634
|
-
if (typeof value !== "boolean") {
|
|
635
|
-
errors.push(`${path}: must be boolean`);
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
return value;
|
|
639
|
-
}
|
|
640
|
-
function parseEnum(value, allowed, path, errors) {
|
|
641
|
-
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
642
|
-
errors.push(`${path}: expected one of ${allowed.join(", ")}`);
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
return value;
|
|
646
|
-
}
|
|
647
|
-
function parseStringArray(value, path, errors) {
|
|
648
|
-
if (value === void 0) return void 0;
|
|
649
|
-
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
650
|
-
errors.push(`${path}: must be an array of strings`);
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
return [...value];
|
|
654
|
-
}
|
|
655
|
-
//#endregion
|
|
656
|
-
//#region src/client/snapshot.ts
|
|
657
|
-
/** Runtime validation for trusted debugger RPC responses. */
|
|
658
|
-
const DIGEST = /^[a-f0-9]{64}$/u;
|
|
659
|
-
const GOAL_STATES = /* @__PURE__ */ new Set([
|
|
660
|
-
"pending",
|
|
661
|
-
"running",
|
|
662
|
-
"success",
|
|
663
|
-
"failure",
|
|
664
|
-
"blocked",
|
|
665
|
-
"needs_human",
|
|
666
|
-
"cancelled",
|
|
667
|
-
"invalidated",
|
|
668
|
-
"partial",
|
|
669
|
-
"inherited"
|
|
670
|
-
]);
|
|
671
|
-
const ROOT_STATES = /* @__PURE__ */ new Set([
|
|
672
|
-
"success",
|
|
673
|
-
"partial_success",
|
|
674
|
-
"failure",
|
|
675
|
-
"infeasible",
|
|
676
|
-
"needs_replan",
|
|
677
|
-
"cancelled"
|
|
678
|
-
]);
|
|
679
|
-
const GOAL_AGENT_ROLES = /* @__PURE__ */ new Set([
|
|
680
|
-
"orchestrator",
|
|
681
|
-
"verifier",
|
|
682
|
-
"reviewer"
|
|
683
|
-
]);
|
|
684
|
-
const RUNTIME_PHASES = /* @__PURE__ */ new Set([
|
|
685
|
-
"goal_started",
|
|
686
|
-
"dependency_blocked",
|
|
687
|
-
"grounding_extracted",
|
|
688
|
-
"workspace_allocated",
|
|
689
|
-
"verifier_started",
|
|
690
|
-
"verifier_released",
|
|
691
|
-
"verifier_passed",
|
|
692
|
-
"verifier_failed",
|
|
693
|
-
"verifier_inconclusive",
|
|
694
|
-
"composite_evaluated",
|
|
695
|
-
"result_inherited",
|
|
696
|
-
"structured_error",
|
|
697
|
-
"goal_settled",
|
|
698
|
-
"run_warning"
|
|
699
|
-
]);
|
|
700
|
-
/** Parse JSON from the debugger endpoint before it reaches render code. */
|
|
701
|
-
function parseDogDebugSnapshot(value) {
|
|
702
|
-
const root = requireRecord(value, "$");
|
|
703
|
-
if (root.schemaVersion !== "0.1") throw new Error("debug snapshot schemaVersion must be 0.1");
|
|
704
|
-
const graphs = requireArray(root.graphs, "$.graphs").map((item, index) => parseRevision(item, `$.graphs[${index}]`));
|
|
705
|
-
return {
|
|
706
|
-
schemaVersion: "0.1",
|
|
707
|
-
generatedAt: requireString(root.generatedAt, "$.generatedAt"),
|
|
708
|
-
graphs
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
/** Parse one lazy per-goal runtime trace before it reaches render code. */
|
|
712
|
-
function parseGoalRuntimeTrace(value) {
|
|
713
|
-
const root = requireRecord(value, "$");
|
|
714
|
-
if (root.schemaVersion !== "0.1") throw new Error("runtime trace schemaVersion must be 0.1");
|
|
715
|
-
const runId = requireBoundedString(root.runId, "$.runId");
|
|
716
|
-
const graphDigest = requireDigest(root.graphDigest, "$.graphDigest");
|
|
717
|
-
const goalId = requireBoundedString(root.goalId, "$.goalId");
|
|
718
|
-
const runState = parseRunState(root.runState, "$.runState");
|
|
719
|
-
const result = parseGoalResult(root.result, "$.result");
|
|
720
|
-
const rootState = root.rootState === void 0 ? void 0 : parseRootState(root.rootState, "$.rootState");
|
|
721
|
-
const invocation = root.invocation === void 0 ? void 0 : parseInvocation(root.invocation, "$.invocation");
|
|
722
|
-
const events = requireArray(root.events, "$.events").map((item, index) => parseRuntimeEvent(item, `$.events[${index}]`, {
|
|
723
|
-
runId,
|
|
724
|
-
goalId
|
|
725
|
-
}));
|
|
726
|
-
if (typeof root.truncated !== "boolean") throw new Error("$.truncated must be a boolean");
|
|
727
|
-
const runtimeWarning = root.runtimeWarning === void 0 ? void 0 : requireBoundedString(root.runtimeWarning, "$.runtimeWarning");
|
|
728
|
-
return {
|
|
729
|
-
schemaVersion: "0.1",
|
|
730
|
-
runId,
|
|
731
|
-
graphId: requireBoundedString(root.graphId, "$.graphId"),
|
|
732
|
-
graphDigest,
|
|
733
|
-
runState,
|
|
734
|
-
...rootState === void 0 ? {} : { rootState },
|
|
735
|
-
goalId,
|
|
736
|
-
result,
|
|
737
|
-
...invocation === void 0 ? {} : { invocation },
|
|
738
|
-
...runtimeWarning === void 0 ? {} : { runtimeWarning },
|
|
739
|
-
events,
|
|
740
|
-
truncated: root.truncated
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
function parseRuntimeEvent(value, path, expected) {
|
|
744
|
-
const root = requireRecord(value, path);
|
|
745
|
-
if (root.schemaVersion !== "0.1") throw new Error(`${path}.schemaVersion must be 0.1`);
|
|
746
|
-
const runId = requireBoundedString(root.runId, `${path}.runId`);
|
|
747
|
-
const goalId = requireBoundedString(root.goalId, `${path}.goalId`);
|
|
748
|
-
if (runId !== expected.runId || goalId !== expected.goalId) throw new Error(`${path} does not belong to the requested goal trace`);
|
|
749
|
-
const phase = requireString(root.phase, `${path}.phase`);
|
|
750
|
-
if (!RUNTIME_PHASES.has(phase)) throw new Error(`${path}.phase is invalid`);
|
|
751
|
-
const state = root.state === void 0 ? void 0 : parseGoalState(root.state, `${path}.state`);
|
|
752
|
-
const reason = root.reason === void 0 ? void 0 : requireBoundedString(root.reason, `${path}.reason`);
|
|
753
|
-
const durationMs = root.durationMs === void 0 ? void 0 : requireNonNegativeInteger(root.durationMs, `${path}.durationMs`);
|
|
754
|
-
const attempt = root.attempt === void 0 ? void 0 : requireNonNegativeInteger(root.attempt, `${path}.attempt`);
|
|
755
|
-
const gmDigest = root.gmDigest === void 0 ? void 0 : requireString(root.gmDigest, `${path}.gmDigest`);
|
|
756
|
-
const verifierRecord = root.verifier === void 0 ? void 0 : requireRecord(root.verifier, `${path}.verifier`);
|
|
757
|
-
const verifier = verifierRecord === void 0 ? void 0 : { mode: requireEnumValue(verifierRecord.mode, ["programmatic", "agentic"], `${path}.verifier.mode`) };
|
|
758
|
-
return {
|
|
759
|
-
schemaVersion: "0.1",
|
|
760
|
-
runId,
|
|
761
|
-
goalId,
|
|
762
|
-
phase,
|
|
763
|
-
at: requireString(root.at, `${path}.at`),
|
|
764
|
-
...state === void 0 ? {} : { state },
|
|
765
|
-
...reason === void 0 ? {} : { reason },
|
|
766
|
-
...verifier === void 0 ? {} : { verifier },
|
|
767
|
-
...gmDigest === void 0 ? {} : { gmDigest },
|
|
768
|
-
...attempt === void 0 ? {} : { attempt },
|
|
769
|
-
...durationMs === void 0 ? {} : { durationMs }
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
function parseRevision(value, path) {
|
|
773
|
-
const root = requireRecord(value, path);
|
|
774
|
-
const graphRecord = requireRecord(root.graph, `${path}.graph`);
|
|
775
|
-
const graphDigest = requireDigest(graphRecord.graphDigest, `${path}.graph.graphDigest`);
|
|
776
|
-
const input = parseGraph(graphRecord.input, {
|
|
777
|
-
maxGraphNodes: 4096,
|
|
778
|
-
maxExpressionNodes: 8192,
|
|
779
|
-
maxExpressionDepth: 256
|
|
780
|
-
});
|
|
781
|
-
const acceptancePlans = parseAcceptancePlans(graphRecord.acceptancePlans, `${path}.graph.acceptancePlans`);
|
|
782
|
-
const runs = requireArray(root.runs, `${path}.runs`).map((item, index) => {
|
|
783
|
-
const run = parseRun(item, `${path}.runs[${index}]`);
|
|
784
|
-
if (run.graphDigest !== graphDigest) throw new Error(`${path}.runs[${index}]: graph digest mismatch`);
|
|
785
|
-
return run;
|
|
786
|
-
});
|
|
787
|
-
if (typeof root.current !== "boolean") throw new Error(`${path}.current must be a boolean`);
|
|
788
|
-
return {
|
|
789
|
-
graph: {
|
|
790
|
-
input,
|
|
791
|
-
graphDigest,
|
|
792
|
-
acceptancePlans
|
|
793
|
-
},
|
|
794
|
-
current: root.current,
|
|
795
|
-
runs
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
function parseAcceptancePlans(value, path) {
|
|
799
|
-
const root = requireRecord(value, path);
|
|
800
|
-
const result = {};
|
|
801
|
-
for (const [key, item] of Object.entries(root)) {
|
|
802
|
-
const plan = parseAcceptancePlan(item, `${path}.${key}`);
|
|
803
|
-
if (plan.goalId !== key) throw new Error(`${path}.${key}: goalId mismatch`);
|
|
804
|
-
result[key] = plan;
|
|
805
|
-
}
|
|
806
|
-
return result;
|
|
807
|
-
}
|
|
808
|
-
function parseAcceptancePlan(value, path) {
|
|
809
|
-
const root = requireRecord(value, path);
|
|
810
|
-
const input = root.input === void 0 ? void 0 : parseCapturedInput(root.input, `${path}.input`);
|
|
811
|
-
const verifier = parseVerifierShape(root.verifier ?? root.v09Verifier, `${path}.verifier`);
|
|
812
|
-
const judgment = parseJudgment(root.judgment, `${path}.judgment`);
|
|
813
|
-
return {
|
|
814
|
-
goalId: requireString(root.goalId, `${path}.goalId`),
|
|
815
|
-
verifier,
|
|
816
|
-
judgment,
|
|
817
|
-
target: requireString(root.target, `${path}.target`),
|
|
818
|
-
...input === void 0 ? {} : { input },
|
|
819
|
-
...root.gmDigest === void 0 ? {} : { gmDigest: requireString(root.gmDigest, `${path}.gmDigest`) }
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
function parseVerifierShape(value, path) {
|
|
823
|
-
const record = requireRecord(value, path);
|
|
824
|
-
const mode = requireString(record.mode, `${path}.mode`);
|
|
825
|
-
if (mode === "programmatic") return {
|
|
826
|
-
mode: "programmatic",
|
|
827
|
-
script: requireString(record.script, `${path}.script`)
|
|
828
|
-
};
|
|
829
|
-
if (mode === "agentic") return {
|
|
830
|
-
mode: "agentic",
|
|
831
|
-
instruction: requireString(record.instruction, `${path}.instruction`)
|
|
832
|
-
};
|
|
833
|
-
throw new Error(`${path}.mode is invalid`);
|
|
834
|
-
}
|
|
835
|
-
function parseJudgment(value, path) {
|
|
836
|
-
const record = requireRecord(value, path);
|
|
837
|
-
if (requireString(record.mode, `${path}.mode`) === "programmatic") return {
|
|
838
|
-
mode: "programmatic",
|
|
839
|
-
script: requireString(record.script, `${path}.script`),
|
|
840
|
-
scriptDigest: requireString(record.scriptDigest, `${path}.scriptDigest`)
|
|
841
|
-
};
|
|
842
|
-
return {
|
|
843
|
-
mode: "agentic",
|
|
844
|
-
instructionHash: requireString(record.instructionHash, `${path}.instructionHash`)
|
|
845
|
-
};
|
|
846
|
-
}
|
|
847
|
-
function parseCapturedInput(value, path) {
|
|
848
|
-
const root = requireRecord(value, path);
|
|
849
|
-
const exists = root.exists;
|
|
850
|
-
const byteLength = root.byteLength;
|
|
851
|
-
if (typeof exists !== "boolean") throw new Error(`${path}.exists must be a boolean`);
|
|
852
|
-
if (typeof byteLength !== "number" || !Number.isSafeInteger(byteLength) || byteLength < 0) throw new Error(`${path}.byteLength must be a non-negative safe integer`);
|
|
853
|
-
return {
|
|
854
|
-
path: requireBoundedString(root.path, `${path}.path`),
|
|
855
|
-
digest: requireString(root.digest, `${path}.digest`),
|
|
856
|
-
exists,
|
|
857
|
-
byteLength,
|
|
858
|
-
sha256: requireString(root.sha256, `${path}.sha256`)
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
function parseRun(value, path) {
|
|
862
|
-
const root = requireRecord(value, path);
|
|
863
|
-
const state = parseRunState(root.state, `${path}.state`);
|
|
864
|
-
const goalsRecord = requireRecord(root.goals, `${path}.goals`);
|
|
865
|
-
const goals = {};
|
|
866
|
-
for (const [id, result] of Object.entries(goalsRecord)) goals[id] = parseGoalResult(result, `${path}.goals.${id}`);
|
|
867
|
-
const rootState = root.rootState === void 0 ? void 0 : parseRootState(root.rootState, `${path}.rootState`);
|
|
868
|
-
const invocation = root.invocation === void 0 ? void 0 : parseInvocation(root.invocation, `${path}.invocation`);
|
|
869
|
-
const runtimeWarning = root.runtimeWarning === void 0 ? void 0 : requireBoundedString(root.runtimeWarning, `${path}.runtimeWarning`);
|
|
870
|
-
const gmDigestsRecord = root.gmDigests === void 0 ? {} : requireRecord(root.gmDigests, `${path}.gmDigests`);
|
|
871
|
-
const gmDigests = {};
|
|
872
|
-
for (const [id, digest] of Object.entries(gmDigestsRecord)) gmDigests[id] = requireString(digest, `${path}.gmDigests.${id}`);
|
|
873
|
-
return {
|
|
874
|
-
runId: requireString(root.runId, `${path}.runId`),
|
|
875
|
-
graphId: requireString(root.graphId, `${path}.graphId`),
|
|
876
|
-
graphDigest: requireDigest(root.graphDigest, `${path}.graphDigest`),
|
|
877
|
-
state,
|
|
878
|
-
...rootState === void 0 ? {} : { rootState },
|
|
879
|
-
gmDigests,
|
|
880
|
-
goals,
|
|
881
|
-
...invocation === void 0 ? {} : { invocation },
|
|
882
|
-
...runtimeWarning === void 0 ? {} : { runtimeWarning },
|
|
883
|
-
createdAt: requireString(root.createdAt, `${path}.createdAt`),
|
|
884
|
-
updatedAt: requireString(root.updatedAt, `${path}.updatedAt`)
|
|
885
|
-
};
|
|
886
|
-
}
|
|
887
|
-
function parseInvocation(value, path) {
|
|
888
|
-
const root = requireRecord(value, path);
|
|
889
|
-
const agentSessionId = root.agentSessionId === void 0 ? void 0 : requireBoundedString(root.agentSessionId, `${path}.agentSessionId`);
|
|
890
|
-
const parentSessionId = root.parentSessionId === void 0 ? void 0 : requireBoundedString(root.parentSessionId, `${path}.parentSessionId`);
|
|
891
|
-
if (parentSessionId !== void 0 && agentSessionId === void 0) throw new Error(`${path}.parentSessionId requires agentSessionId`);
|
|
892
|
-
return {
|
|
893
|
-
callId: requireBoundedString(root.callId, `${path}.callId`),
|
|
894
|
-
...agentSessionId === void 0 ? {} : { agentSessionId },
|
|
895
|
-
...parentSessionId === void 0 ? {} : { parentSessionId },
|
|
896
|
-
invokedAt: requireString(root.invokedAt, `${path}.invokedAt`)
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
function parseGoalResult(value, path) {
|
|
900
|
-
const root = requireRecord(value, path);
|
|
901
|
-
const state = parseGoalState(root.state, `${path}.state`);
|
|
902
|
-
const reason = root.reason === void 0 ? void 0 : requireString(root.reason, `${path}.reason`);
|
|
903
|
-
const verification = root.verification === void 0 ? void 0 : parseVerification(root.verification, `${path}.verification`);
|
|
904
|
-
const agentSessions = root.agentSessions === void 0 ? void 0 : requireArray(root.agentSessions, `${path}.agentSessions`).map((agent, index) => parseGoalAgentSession(agent, `${path}.agentSessions[${index}]`));
|
|
905
|
-
const inheritedFrom = root.inheritedFrom === void 0 ? void 0 : requireString(root.inheritedFrom, `${path}.inheritedFrom`);
|
|
906
|
-
return {
|
|
907
|
-
state,
|
|
908
|
-
...reason === void 0 ? {} : { reason },
|
|
909
|
-
...verification === void 0 ? {} : { verification },
|
|
910
|
-
...inheritedFrom === void 0 ? {} : { inheritedFrom },
|
|
911
|
-
...agentSessions === void 0 ? {} : { agentSessions }
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
function parseGoalAgentSession(value, path) {
|
|
915
|
-
const root = requireRecord(value, path);
|
|
916
|
-
const role = requireBoundedString(root.role, `${path}.role`);
|
|
917
|
-
if (!GOAL_AGENT_ROLES.has(role)) throw new Error(`${path}.role is invalid`);
|
|
918
|
-
const parentSessionId = root.parentSessionId === void 0 ? void 0 : requireBoundedString(root.parentSessionId, `${path}.parentSessionId`);
|
|
919
|
-
return {
|
|
920
|
-
sessionId: requireBoundedString(root.sessionId, `${path}.sessionId`),
|
|
921
|
-
...parentSessionId === void 0 ? {} : { parentSessionId },
|
|
922
|
-
role,
|
|
923
|
-
boundAt: requireBoundedString(root.boundAt, `${path}.boundAt`)
|
|
924
|
-
};
|
|
925
|
-
}
|
|
926
|
-
function parseVerification(value, path) {
|
|
927
|
-
const root = requireRecord(value, path);
|
|
928
|
-
if (root.passed !== null && typeof root.passed !== "boolean") throw new Error(`${path}.passed must be a boolean or null`);
|
|
929
|
-
return {
|
|
930
|
-
schemaVersion: "0.1",
|
|
931
|
-
goalId: requireString(root.goalId, `${path}.goalId`),
|
|
932
|
-
runId: requireString(root.runId, `${path}.runId`),
|
|
933
|
-
graphId: requireString(root.graphId, `${path}.graphId`),
|
|
934
|
-
graphDigest: requireDigest(root.graphDigest, `${path}.graphDigest`),
|
|
935
|
-
judgment: parseJudgment(root.judgment, `${path}.judgment`),
|
|
936
|
-
...root.gmDigest === void 0 ? {} : { gmDigest: requireString(root.gmDigest, `${path}.gmDigest`) },
|
|
937
|
-
passed: root.passed === null ? null : root.passed,
|
|
938
|
-
...root.evidence === void 0 ? {} : { evidence: requireJson(root.evidence, `${path}.evidence`) },
|
|
939
|
-
at: requireString(root.at, `${path}.at`)
|
|
940
|
-
};
|
|
941
|
-
}
|
|
942
|
-
function requireEnumValue(value, allowed, path) {
|
|
943
|
-
const candidate = requireString(value, path);
|
|
944
|
-
if (!allowed.includes(candidate)) throw new Error(`${path} is invalid`);
|
|
945
|
-
return candidate;
|
|
946
|
-
}
|
|
947
|
-
function requireJson(value, path) {
|
|
948
|
-
if (!isJsonValue(value)) throw new Error(`${path} must be JSON-compatible`);
|
|
949
|
-
return value;
|
|
950
|
-
}
|
|
951
|
-
function parseGoalState(value, path) {
|
|
952
|
-
if (typeof value !== "string" || !GOAL_STATES.has(value)) throw new Error(`${path} is invalid`);
|
|
953
|
-
return value;
|
|
954
|
-
}
|
|
955
|
-
function parseRootState(value, path) {
|
|
956
|
-
if (typeof value !== "string" || !ROOT_STATES.has(value)) throw new Error(`${path} is invalid`);
|
|
957
|
-
return value;
|
|
958
|
-
}
|
|
959
|
-
function parseRunState(value, path) {
|
|
960
|
-
if (value !== "running" && value !== "completed" && value !== "cancelled" && value !== "failed") throw new Error(`${path} is invalid`);
|
|
961
|
-
return value;
|
|
962
|
-
}
|
|
963
|
-
function requireDigest(value, path) {
|
|
964
|
-
const text = requireString(value, path);
|
|
965
|
-
if (!DIGEST.test(text)) throw new Error(`${path} must be a SHA-256 digest`);
|
|
966
|
-
return text;
|
|
967
|
-
}
|
|
968
|
-
function requireRecord(value, path) {
|
|
969
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${path} must be an object`);
|
|
970
|
-
return Object.fromEntries(Object.entries(value));
|
|
971
|
-
}
|
|
972
|
-
function requireArray(value, path) {
|
|
973
|
-
if (!Array.isArray(value)) throw new Error(`${path} must be an array`);
|
|
974
|
-
return value;
|
|
975
|
-
}
|
|
976
|
-
function requireString(value, path) {
|
|
977
|
-
if (typeof value !== "string") throw new Error(`${path} must be a string`);
|
|
978
|
-
return value;
|
|
979
|
-
}
|
|
980
|
-
function requireBoundedString(value, path) {
|
|
981
|
-
const text = requireString(value, path);
|
|
982
|
-
if (text.length === 0 || text.length > 512) throw new Error(`${path} must contain 1-512 characters`);
|
|
983
|
-
return text;
|
|
984
|
-
}
|
|
985
|
-
function requireNonNegativeInteger(value, path) {
|
|
986
|
-
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new Error(`${path} must be a non-negative safe integer`);
|
|
987
|
-
return value;
|
|
988
|
-
}
|
|
989
|
-
//#endregion
|
|
990
|
-
//#region src/client/DogDebugger.tsx
|
|
991
|
-
const REFRESH_INTERVAL_MS = 3e3;
|
|
992
|
-
const RECENT_DOG_LIMIT = 4;
|
|
993
|
-
const DOG_DOCK_RESERVED_WIDTH = 370;
|
|
994
|
-
const HOST_CENTER_MIN_WIDTH = 640;
|
|
995
|
-
const DOG_DOCK_COLLAPSED_KEY = "@dsh-external/dsh-dog/dock-collapsed";
|
|
996
|
-
const MIN_ZOOM = .6;
|
|
997
|
-
const MAX_ZOOM = 1.2;
|
|
998
|
-
function DogDebugger({ initialOpen = false, hideDock = false, readSnapshot, readGoalRuntime, openSession, getSessionState, subscribeSessions, refreshAgentCatalog }) {
|
|
999
|
-
const [open, setOpen] = (0, react.useState)(initialOpen);
|
|
1000
|
-
const [dockCollapsed, setDockCollapsed] = (0, react.useState)(readDogDockCollapsed);
|
|
1001
|
-
const [snapshot, setSnapshot] = (0, react.useState)();
|
|
1002
|
-
const [selectedDigest, setSelectedDigest] = (0, react.useState)();
|
|
1003
|
-
const [selectedRunId, setSelectedRunId] = (0, react.useState)();
|
|
1004
|
-
const [selectedNodeId, setSelectedNodeId] = (0, react.useState)();
|
|
1005
|
-
const [loading, setLoading] = (0, react.useState)(false);
|
|
1006
|
-
const [error, setError] = (0, react.useState)();
|
|
1007
|
-
const [zoom, setZoom] = (0, react.useState)(.9);
|
|
1008
|
-
const inFlight = (0, react.useRef)(false);
|
|
1009
|
-
const dialogRef = (0, react.useRef)(null);
|
|
1010
|
-
const overlayRootRef = (0, react.useRef)(null);
|
|
1011
|
-
const sessionState = (0, react.useSyncExternalStore)(subscribeSessions, getSessionState, getSessionState);
|
|
1012
|
-
const updateDockCollapsed = (0, react.useCallback)((collapsed) => {
|
|
1013
|
-
setDockCollapsed(collapsed);
|
|
1014
|
-
writeDogDockCollapsed(collapsed);
|
|
1015
|
-
}, []);
|
|
1016
|
-
(0, react.useEffect)(() => {
|
|
1017
|
-
if (hideDock) return;
|
|
1018
|
-
const root = overlayRootRef.current;
|
|
1019
|
-
const overlayLayer = root?.parentElement?.parentElement;
|
|
1020
|
-
const details = overlayLayer?.previousElementSibling;
|
|
1021
|
-
const center = details?.previousElementSibling;
|
|
1022
|
-
const sidebar = center?.previousElementSibling;
|
|
1023
|
-
const frame = overlayLayer?.parentElement;
|
|
1024
|
-
if (!(root instanceof HTMLElement) || !(overlayLayer instanceof HTMLElement) || !(details instanceof HTMLElement) || !(center instanceof HTMLElement) || !(sidebar instanceof HTMLElement) || !(frame instanceof HTMLElement)) return;
|
|
1025
|
-
const previousMarginRight = center.style.marginRight;
|
|
1026
|
-
const previousMinWidth = center.style.minWidth;
|
|
1027
|
-
const update = () => {
|
|
1028
|
-
const frameWidth = frame.getBoundingClientRect().width;
|
|
1029
|
-
const sidebarWidth = sidebar.getBoundingClientRect().width;
|
|
1030
|
-
const detailsWidth = details.getBoundingClientRect().width;
|
|
1031
|
-
const centerWidth = frameWidth - sidebarWidth - detailsWidth;
|
|
1032
|
-
if (!open && !dockCollapsed && detailsWidth < 1 && centerWidth - DOG_DOCK_RESERVED_WIDTH >= HOST_CENTER_MIN_WIDTH) {
|
|
1033
|
-
center.style.marginRight = `${DOG_DOCK_RESERVED_WIDTH}px`;
|
|
1034
|
-
center.style.minWidth = "0";
|
|
1035
|
-
root.dataset.dogDockLayout = "reserved";
|
|
1036
|
-
return;
|
|
1037
|
-
}
|
|
1038
|
-
center.style.marginRight = previousMarginRight;
|
|
1039
|
-
center.style.minWidth = previousMinWidth;
|
|
1040
|
-
root.dataset.dogDockLayout = open || detailsWidth >= 1 ? "hidden" : dockCollapsed ? "collapsed" : "floating";
|
|
1041
|
-
};
|
|
1042
|
-
update();
|
|
1043
|
-
const observer = new ResizeObserver(update);
|
|
1044
|
-
observer.observe(frame);
|
|
1045
|
-
observer.observe(sidebar);
|
|
1046
|
-
observer.observe(details);
|
|
1047
|
-
window.addEventListener("resize", update);
|
|
1048
|
-
return () => {
|
|
1049
|
-
window.removeEventListener("resize", update);
|
|
1050
|
-
observer.disconnect();
|
|
1051
|
-
center.style.marginRight = previousMarginRight;
|
|
1052
|
-
center.style.minWidth = previousMinWidth;
|
|
1053
|
-
delete root.dataset.dogDockLayout;
|
|
1054
|
-
};
|
|
1055
|
-
}, [
|
|
1056
|
-
dockCollapsed,
|
|
1057
|
-
open,
|
|
1058
|
-
hideDock
|
|
1059
|
-
]);
|
|
1060
|
-
const refresh = (0, react.useCallback)(async () => {
|
|
1061
|
-
if (inFlight.current) return;
|
|
1062
|
-
inFlight.current = true;
|
|
1063
|
-
setLoading(true);
|
|
1064
|
-
try {
|
|
1065
|
-
const next = parseDogDebugSnapshot(await readSnapshot(new AbortController().signal));
|
|
1066
|
-
setSnapshot(next);
|
|
1067
|
-
setError(void 0);
|
|
1068
|
-
await Promise.allSettled(agentParentSessionIds(next).map(refreshAgentCatalog));
|
|
1069
|
-
} catch (cause) {
|
|
1070
|
-
setError(cause instanceof Error ? cause.message : String(cause));
|
|
1071
|
-
} finally {
|
|
1072
|
-
inFlight.current = false;
|
|
1073
|
-
setLoading(false);
|
|
1074
|
-
}
|
|
1075
|
-
}, [readSnapshot, refreshAgentCatalog]);
|
|
1076
|
-
const openInvokingSession = (0, react.useCallback)(async (sessionId, parentSessionId) => {
|
|
1077
|
-
const opened = await openSession(sessionId, parentSessionId);
|
|
1078
|
-
if (opened) setOpen(false);
|
|
1079
|
-
return opened;
|
|
1080
|
-
}, [openSession]);
|
|
1081
|
-
(0, react.useEffect)(() => {
|
|
1082
|
-
if (hideDock && !open) return;
|
|
1083
|
-
refresh();
|
|
1084
|
-
const timer = window.setInterval(() => void refresh(), REFRESH_INTERVAL_MS);
|
|
1085
|
-
return () => window.clearInterval(timer);
|
|
1086
|
-
}, [
|
|
1087
|
-
refresh,
|
|
1088
|
-
open,
|
|
1089
|
-
hideDock
|
|
1090
|
-
]);
|
|
1091
|
-
(0, react.useEffect)(() => {
|
|
1092
|
-
if (!open) return;
|
|
1093
|
-
const previouslyFocused = document.activeElement;
|
|
1094
|
-
dialogRef.current?.focus();
|
|
1095
|
-
const onKeyDown = (event) => {
|
|
1096
|
-
if (event.key === "Escape") setOpen(false);
|
|
1097
|
-
};
|
|
1098
|
-
window.addEventListener("keydown", onKeyDown);
|
|
1099
|
-
return () => {
|
|
1100
|
-
window.removeEventListener("keydown", onKeyDown);
|
|
1101
|
-
if (previouslyFocused instanceof HTMLElement) previouslyFocused.focus();
|
|
1102
|
-
};
|
|
1103
|
-
}, [open]);
|
|
1104
|
-
const selectedRevision = snapshot?.graphs.find((item) => item.graph.graphDigest === selectedDigest) ?? snapshot?.graphs[0];
|
|
1105
|
-
const selectedRun = selectedRevision?.runs.find((run) => run.runId === selectedRunId) ?? selectedRevision?.runs[0];
|
|
1106
|
-
const effectiveNodeId = selectedNodeId !== void 0 && selectedRevision?.graph.input.nodes[selectedNodeId] !== void 0 ? selectedNodeId : selectedRevision?.graph.input.root;
|
|
1107
|
-
const chooseRevision = (revision) => {
|
|
1108
|
-
setSelectedDigest(revision.graph.graphDigest);
|
|
1109
|
-
setSelectedRunId(revision.runs[0]?.runId);
|
|
1110
|
-
setSelectedNodeId(revision.graph.input.root);
|
|
1111
|
-
};
|
|
1112
|
-
const enterRevision = (revision) => {
|
|
1113
|
-
chooseRevision(revision);
|
|
1114
|
-
setOpen(true);
|
|
1115
|
-
};
|
|
1116
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1117
|
-
ref: overlayRootRef,
|
|
1118
|
-
className: "dog-overlay-root",
|
|
1119
|
-
children: [open || hideDock ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DogDock, {
|
|
1120
|
-
snapshot,
|
|
1121
|
-
sessions: sessionState,
|
|
1122
|
-
loading,
|
|
1123
|
-
error,
|
|
1124
|
-
onOpenRevision: enterRevision,
|
|
1125
|
-
collapsed: dockCollapsed,
|
|
1126
|
-
onCollapsedChange: updateDockCollapsed,
|
|
1127
|
-
onRefresh: () => void refresh()
|
|
1128
|
-
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1129
|
-
className: "dog-backdrop",
|
|
1130
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1131
|
-
ref: dialogRef,
|
|
1132
|
-
className: "dog-dialog",
|
|
1133
|
-
role: "dialog",
|
|
1134
|
-
"aria-modal": "true",
|
|
1135
|
-
"aria-label": "DoG graph",
|
|
1136
|
-
tabIndex: -1,
|
|
1137
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
1138
|
-
className: "dog-header",
|
|
1139
|
-
children: [
|
|
1140
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1141
|
-
className: "dog-brand",
|
|
1142
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1143
|
-
className: "dog-brand-mark",
|
|
1144
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NetworkIcon, { size: 18 })
|
|
1145
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1146
|
-
className: "dog-brand-copy",
|
|
1147
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
1148
|
-
className: "dog-brand-title",
|
|
1149
|
-
children: "DoG"
|
|
1150
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1151
|
-
className: "dog-brand-subtitle",
|
|
1152
|
-
children: "Goals · Agents · trusted evidence"
|
|
1153
|
-
})]
|
|
1154
|
-
})]
|
|
1155
|
-
}),
|
|
1156
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dog-header-divider" }),
|
|
1157
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1158
|
-
className: "dog-context",
|
|
1159
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1160
|
-
className: "dog-context-title",
|
|
1161
|
-
children: selectedRevision?.graph.input.nodes[selectedRevision.graph.input.root]?.title ?? "No graph selected"
|
|
1162
|
-
}), selectedRevision?.current ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1163
|
-
className: "dog-revision-chip",
|
|
1164
|
-
children: "Current revision"
|
|
1165
|
-
}) : null]
|
|
1166
|
-
}),
|
|
1167
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1168
|
-
className: "dog-header-actions",
|
|
1169
|
-
children: [
|
|
1170
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1171
|
-
className: "dog-sync-copy",
|
|
1172
|
-
title: error,
|
|
1173
|
-
children: error === void 0 ? "Live · 3s" : "Refresh failed"
|
|
1174
|
-
}),
|
|
1175
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
|
|
1176
|
-
label: "Refresh DoG data",
|
|
1177
|
-
busy: loading,
|
|
1178
|
-
onClick: () => void refresh(),
|
|
1179
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RefreshIcon, {})
|
|
1180
|
-
}),
|
|
1181
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
|
|
1182
|
-
label: "Close DoG",
|
|
1183
|
-
busy: false,
|
|
1184
|
-
onClick: () => setOpen(false),
|
|
1185
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CloseIcon, {})
|
|
1186
|
-
})
|
|
1187
|
-
]
|
|
1188
|
-
})
|
|
1189
|
-
]
|
|
1190
|
-
}), selectedRevision === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmptyWorkspace, {
|
|
1191
|
-
loading,
|
|
1192
|
-
error
|
|
1193
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1194
|
-
className: loading ? "dog-workspace dog-loading" : "dog-workspace",
|
|
1195
|
-
children: [
|
|
1196
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Sidebar, {
|
|
1197
|
-
snapshot,
|
|
1198
|
-
selectedRevision,
|
|
1199
|
-
selectedRun,
|
|
1200
|
-
onSelectRevision: chooseRevision,
|
|
1201
|
-
onSelectRun: setSelectedRunId
|
|
1202
|
-
}),
|
|
1203
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
|
|
1204
|
-
className: "dog-main",
|
|
1205
|
-
children: [
|
|
1206
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Summary, {
|
|
1207
|
-
revision: selectedRevision,
|
|
1208
|
-
run: selectedRun,
|
|
1209
|
-
sessions: sessionState
|
|
1210
|
-
}),
|
|
1211
|
-
error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1212
|
-
className: "dog-error-banner",
|
|
1213
|
-
role: "status",
|
|
1214
|
-
children: ["Live refresh failed: ", error]
|
|
1215
|
-
}),
|
|
1216
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1217
|
-
className: "dog-canvas-shell",
|
|
1218
|
-
"aria-label": "Goal DAG canvas",
|
|
1219
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CanvasToolbar, {
|
|
1220
|
-
zoom,
|
|
1221
|
-
onZoom: setZoom
|
|
1222
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GraphCanvas, {
|
|
1223
|
-
graph: selectedRevision.graph,
|
|
1224
|
-
run: selectedRun,
|
|
1225
|
-
sessions: sessionState,
|
|
1226
|
-
selectedNodeId: effectiveNodeId,
|
|
1227
|
-
zoom,
|
|
1228
|
-
onSelectNode: setSelectedNodeId,
|
|
1229
|
-
openSession: openInvokingSession
|
|
1230
|
-
})]
|
|
1231
|
-
})
|
|
1232
|
-
]
|
|
1233
|
-
}),
|
|
1234
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Inspector, {
|
|
1235
|
-
graph: selectedRevision.graph,
|
|
1236
|
-
run: selectedRun,
|
|
1237
|
-
nodeId: effectiveNodeId,
|
|
1238
|
-
readGoalRuntime,
|
|
1239
|
-
openSession: openInvokingSession
|
|
1240
|
-
})
|
|
1241
|
-
]
|
|
1242
|
-
})]
|
|
1243
|
-
})
|
|
1244
|
-
}) : null]
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
function DogDock({ snapshot, sessions, loading, error, onOpenRevision, onRefresh, collapsed, onCollapsedChange }) {
|
|
1248
|
-
const revisions = snapshot?.graphs.filter((revision) => revision.current).slice(0, RECENT_DOG_LIMIT) ?? [];
|
|
1249
|
-
if (collapsed) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
|
|
1250
|
-
className: "dog-dock",
|
|
1251
|
-
"data-collapsed": "true",
|
|
1252
|
-
"aria-label": "Collapsed DoG panel",
|
|
1253
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1254
|
-
className: "dog-dock-rail",
|
|
1255
|
-
type: "button",
|
|
1256
|
-
"aria-label": "Expand DoG panel",
|
|
1257
|
-
title: "Expand DoG panel",
|
|
1258
|
-
"aria-expanded": "false",
|
|
1259
|
-
onClick: () => onCollapsedChange(false),
|
|
1260
|
-
children: [
|
|
1261
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1262
|
-
className: "dog-dock-rail-mark",
|
|
1263
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NetworkIcon, { size: 16 })
|
|
1264
|
-
}),
|
|
1265
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "DoG" }),
|
|
1266
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DockExpandIcon, {})
|
|
1267
|
-
]
|
|
1268
|
-
})
|
|
1269
|
-
});
|
|
1270
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
1271
|
-
className: "dog-dock",
|
|
1272
|
-
"data-collapsed": "false",
|
|
1273
|
-
"aria-label": "Recent DoG runs",
|
|
1274
|
-
"aria-busy": loading,
|
|
1275
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1276
|
-
className: "dog-dock-collapse-slot",
|
|
1277
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1278
|
-
className: "dog-dock-collapse-handle",
|
|
1279
|
-
type: "button",
|
|
1280
|
-
"aria-label": "Collapse DoG panel",
|
|
1281
|
-
title: "Collapse DoG panel",
|
|
1282
|
-
"aria-expanded": "true",
|
|
1283
|
-
onClick: () => onCollapsedChange(true),
|
|
1284
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DockCollapseIcon, {})
|
|
1285
|
-
})
|
|
1286
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1287
|
-
className: "dog-dock-content",
|
|
1288
|
-
children: [
|
|
1289
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
1290
|
-
className: "dog-dock-header",
|
|
1291
|
-
children: [
|
|
1292
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1293
|
-
className: "dog-dock-mark",
|
|
1294
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NetworkIcon, { size: 16 })
|
|
1295
|
-
}),
|
|
1296
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1297
|
-
className: "dog-dock-heading",
|
|
1298
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: "DoG" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: loading ? "Syncing…" : error === void 0 ? "Live goals" : "Refresh failed" })]
|
|
1299
|
-
}),
|
|
1300
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
|
|
1301
|
-
label: "Refresh recent DoGs",
|
|
1302
|
-
busy: loading,
|
|
1303
|
-
onClick: onRefresh,
|
|
1304
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RefreshIcon, {})
|
|
1305
|
-
})
|
|
1306
|
-
]
|
|
1307
|
-
}),
|
|
1308
|
-
error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1309
|
-
className: "dog-dock-error",
|
|
1310
|
-
title: error,
|
|
1311
|
-
children: "Last sync failed"
|
|
1312
|
-
}),
|
|
1313
|
-
revisions.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1314
|
-
className: "dog-dock-empty",
|
|
1315
|
-
children: [
|
|
1316
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1317
|
-
className: "dog-dock-empty-icon",
|
|
1318
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NetworkIcon, { size: 19 })
|
|
1319
|
-
}),
|
|
1320
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: loading ? "Loading DoGs" : "No DoG yet" }),
|
|
1321
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "dog_create adds the first graph." })
|
|
1322
|
-
]
|
|
1323
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1324
|
-
className: "dog-dock-list",
|
|
1325
|
-
children: revisions.map((revision) => {
|
|
1326
|
-
const run = latestRun(revision);
|
|
1327
|
-
const total = Object.keys(revision.graph.input.nodes).length;
|
|
1328
|
-
const settled = settledGoalCount(run);
|
|
1329
|
-
const agents = summarizeRunAgents(run, sessions);
|
|
1330
|
-
const state = run?.rootState ?? run?.state ?? "pending";
|
|
1331
|
-
const progress = total === 0 ? 0 : Math.round(settled / total * 100);
|
|
1332
|
-
const rootTitle = revision.graph.input.nodes[revision.graph.input.root]?.title ?? revision.graph.input.id;
|
|
1333
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1334
|
-
className: "dog-dock-card",
|
|
1335
|
-
type: "button",
|
|
1336
|
-
onClick: () => onOpenRevision(revision),
|
|
1337
|
-
"aria-label": `Open ${rootTitle}: ${humanizeState(state)}, ${settled} of ${total} goals complete`,
|
|
1338
|
-
children: [
|
|
1339
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1340
|
-
className: "dog-dock-card-head",
|
|
1341
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1342
|
-
className: "dog-dock-title-wrap",
|
|
1343
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1344
|
-
className: "dog-dock-title",
|
|
1345
|
-
children: rootTitle
|
|
1346
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1347
|
-
className: "dog-dock-id",
|
|
1348
|
-
children: revision.graph.input.id
|
|
1349
|
-
})]
|
|
1350
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusChip, { state })]
|
|
1351
|
-
}),
|
|
1352
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1353
|
-
className: "dog-dock-progress",
|
|
1354
|
-
"aria-hidden": "true",
|
|
1355
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${progress}%` } })
|
|
1356
|
-
}),
|
|
1357
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1358
|
-
className: "dog-dock-metrics",
|
|
1359
|
-
children: [
|
|
1360
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [
|
|
1361
|
-
settled,
|
|
1362
|
-
"/",
|
|
1363
|
-
total
|
|
1364
|
-
] }), " nodes"] }),
|
|
1365
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: agents.linked }), " agents"] }),
|
|
1366
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: agents.running }), " live"] }),
|
|
1367
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatTokenMetric(agents.tokens, agents.partialTokens) }), " tok"] })
|
|
1368
|
-
]
|
|
1369
|
-
})
|
|
1370
|
-
]
|
|
1371
|
-
}) }, revision.graph.graphDigest);
|
|
1372
|
-
})
|
|
1373
|
-
}),
|
|
1374
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1375
|
-
className: "dog-dock-footer",
|
|
1376
|
-
children: "Open a DoG to inspect its graph and Agents"
|
|
1377
|
-
})
|
|
1378
|
-
]
|
|
1379
|
-
})]
|
|
1380
|
-
});
|
|
1381
|
-
}
|
|
1382
|
-
function Sidebar({ snapshot, selectedRevision, selectedRun, onSelectRevision, onSelectRun }) {
|
|
1383
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
1384
|
-
className: "dog-sidebar",
|
|
1385
|
-
"aria-label": "Graphs and run history",
|
|
1386
|
-
children: [
|
|
1387
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
1388
|
-
className: "dog-section-label",
|
|
1389
|
-
children: "Graph revisions"
|
|
1390
|
-
}),
|
|
1391
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1392
|
-
className: "dog-graph-list",
|
|
1393
|
-
children: snapshot?.graphs.map((revision) => {
|
|
1394
|
-
const run = latestRun(revision);
|
|
1395
|
-
const state = run?.rootState ?? run?.state ?? "pending";
|
|
1396
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1397
|
-
className: "dog-list-button",
|
|
1398
|
-
type: "button",
|
|
1399
|
-
"data-selected": revision.graph.graphDigest === selectedRevision.graph.graphDigest,
|
|
1400
|
-
onClick: () => onSelectRevision(revision),
|
|
1401
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1402
|
-
className: "dog-list-row",
|
|
1403
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `dog-state-dot ${stateClass(state)}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1404
|
-
className: "dog-list-title",
|
|
1405
|
-
children: revision.graph.input.id
|
|
1406
|
-
})]
|
|
1407
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1408
|
-
className: "dog-list-meta",
|
|
1409
|
-
children: [
|
|
1410
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1411
|
-
className: revision.current ? "dog-list-current" : void 0,
|
|
1412
|
-
children: revision.current ? "current" : "historical"
|
|
1413
|
-
}),
|
|
1414
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "·" }),
|
|
1415
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [Object.keys(revision.graph.input.nodes).length, " goals"] }),
|
|
1416
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "·" }),
|
|
1417
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1418
|
-
className: "dog-mono",
|
|
1419
|
-
children: shortDigest(revision.graph.graphDigest)
|
|
1420
|
-
})
|
|
1421
|
-
]
|
|
1422
|
-
})]
|
|
1423
|
-
}) }, revision.graph.graphDigest);
|
|
1424
|
-
})
|
|
1425
|
-
}),
|
|
1426
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "dog-sidebar-divider" }),
|
|
1427
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
1428
|
-
className: "dog-section-label",
|
|
1429
|
-
children: "Run history"
|
|
1430
|
-
}),
|
|
1431
|
-
selectedRevision.runs.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1432
|
-
className: "dog-empty-small",
|
|
1433
|
-
children: "No runs are bound to this immutable revision."
|
|
1434
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1435
|
-
className: "dog-run-list",
|
|
1436
|
-
children: selectedRevision.runs.map((run) => {
|
|
1437
|
-
const state = run.rootState ?? run.state;
|
|
1438
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1439
|
-
className: "dog-list-button",
|
|
1440
|
-
type: "button",
|
|
1441
|
-
"data-selected": run.runId === selectedRun?.runId,
|
|
1442
|
-
onClick: () => onSelectRun(run.runId),
|
|
1443
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1444
|
-
className: "dog-list-row",
|
|
1445
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `dog-state-dot ${stateClass(state)}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1446
|
-
className: "dog-list-title",
|
|
1447
|
-
children: humanizeState(state)
|
|
1448
|
-
})]
|
|
1449
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1450
|
-
className: "dog-list-meta",
|
|
1451
|
-
children: [
|
|
1452
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatTime(run.updatedAt) }),
|
|
1453
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "·" }),
|
|
1454
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1455
|
-
className: "dog-mono",
|
|
1456
|
-
children: shortId(run.runId)
|
|
1457
|
-
})
|
|
1458
|
-
]
|
|
1459
|
-
})]
|
|
1460
|
-
}) }, run.runId);
|
|
1461
|
-
})
|
|
1462
|
-
})
|
|
1463
|
-
]
|
|
1464
|
-
});
|
|
1465
|
-
}
|
|
1466
|
-
function Summary({ revision, run, sessions }) {
|
|
1467
|
-
const attention = Object.values(run?.goals ?? {}).filter((result) => isAttentionGoal(result.state)).length;
|
|
1468
|
-
const total = Object.keys(revision.graph.input.nodes).length;
|
|
1469
|
-
const settled = settledGoalCount(run);
|
|
1470
|
-
const agents = summarizeRunAgents(run, sessions);
|
|
1471
|
-
const state = run?.rootState ?? run?.state ?? "pending";
|
|
1472
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1473
|
-
className: "dog-summary",
|
|
1474
|
-
"aria-label": "Run summary",
|
|
1475
|
-
children: [
|
|
1476
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1477
|
-
className: `dog-summary-primary ${stateClass(state)}`,
|
|
1478
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1479
|
-
className: "dog-root-orb",
|
|
1480
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RootIcon, {})
|
|
1481
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1482
|
-
className: "dog-summary-copy",
|
|
1483
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1484
|
-
className: "dog-summary-kicker",
|
|
1485
|
-
children: "Root outcome"
|
|
1486
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1487
|
-
className: "dog-summary-value",
|
|
1488
|
-
children: humanizeState(state)
|
|
1489
|
-
})]
|
|
1490
|
-
})]
|
|
1491
|
-
}),
|
|
1492
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Metric, {
|
|
1493
|
-
label: "Nodes",
|
|
1494
|
-
value: `${settled}/${total}`
|
|
1495
|
-
}),
|
|
1496
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Metric, {
|
|
1497
|
-
label: "Agent tokens",
|
|
1498
|
-
value: formatTokenMetric(agents.tokens, agents.partialTokens)
|
|
1499
|
-
}),
|
|
1500
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Metric, {
|
|
1501
|
-
label: "Agents",
|
|
1502
|
-
value: `${agents.linked} · ${agents.running} live`
|
|
1503
|
-
}),
|
|
1504
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Metric, {
|
|
1505
|
-
label: "Attention",
|
|
1506
|
-
value: String(attention)
|
|
1507
|
-
})
|
|
1508
|
-
]
|
|
1509
|
-
});
|
|
1510
|
-
}
|
|
1511
|
-
function Metric({ label, value }) {
|
|
1512
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1513
|
-
className: "dog-metric",
|
|
1514
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1515
|
-
className: "dog-metric-label",
|
|
1516
|
-
children: label
|
|
1517
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1518
|
-
className: "dog-metric-value",
|
|
1519
|
-
children: value
|
|
1520
|
-
})]
|
|
1521
|
-
});
|
|
1522
|
-
}
|
|
1523
|
-
function CanvasToolbar({ zoom, onZoom }) {
|
|
1524
|
-
const adjust = (delta) => onZoom(clampZoom(zoom + delta));
|
|
1525
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1526
|
-
className: "dog-canvas-toolbar",
|
|
1527
|
-
children: [
|
|
1528
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1529
|
-
className: "dog-legend",
|
|
1530
|
-
"aria-label": "Edge legend",
|
|
1531
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1532
|
-
className: "dog-legend-item",
|
|
1533
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dog-legend-line" }), "Contains"]
|
|
1534
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1535
|
-
className: "dog-legend-item",
|
|
1536
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1537
|
-
className: "dog-legend-line",
|
|
1538
|
-
"data-kind": "depends"
|
|
1539
|
-
}), "Depends on"]
|
|
1540
|
-
})]
|
|
1541
|
-
}),
|
|
1542
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dog-canvas-spacer" }),
|
|
1543
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1544
|
-
className: "dog-zoom",
|
|
1545
|
-
"aria-label": "Canvas zoom",
|
|
1546
|
-
children: [
|
|
1547
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1548
|
-
className: "dog-zoom-button",
|
|
1549
|
-
type: "button",
|
|
1550
|
-
"aria-label": "Zoom out",
|
|
1551
|
-
onClick: () => adjust(-.1),
|
|
1552
|
-
children: "−"
|
|
1553
|
-
}),
|
|
1554
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1555
|
-
className: "dog-zoom-value",
|
|
1556
|
-
children: [Math.round(zoom * 100), "%"]
|
|
1557
|
-
}),
|
|
1558
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1559
|
-
className: "dog-zoom-button",
|
|
1560
|
-
type: "button",
|
|
1561
|
-
"aria-label": "Zoom in",
|
|
1562
|
-
onClick: () => adjust(.1),
|
|
1563
|
-
children: "+"
|
|
1564
|
-
})
|
|
1565
|
-
]
|
|
1566
|
-
})
|
|
1567
|
-
]
|
|
1568
|
-
});
|
|
1569
|
-
}
|
|
1570
|
-
function GraphCanvas({ graph, run, sessions, selectedNodeId, zoom, onSelectNode, openSession }) {
|
|
1571
|
-
const layout = (0, react.useMemo)(() => layoutDag(graph.input), [graph]);
|
|
1572
|
-
const [expandedAgentNodeId, setExpandedAgentNodeId] = (0, react.useState)();
|
|
1573
|
-
const scaledWidth = layout.width * zoom;
|
|
1574
|
-
const scaledHeight = layout.height * zoom;
|
|
1575
|
-
const stageStyle = {
|
|
1576
|
-
width: layout.width,
|
|
1577
|
-
height: layout.height,
|
|
1578
|
-
transform: `scale(${zoom})`
|
|
1579
|
-
};
|
|
1580
|
-
const wrapStyle = {
|
|
1581
|
-
width: scaledWidth,
|
|
1582
|
-
height: scaledHeight,
|
|
1583
|
-
minWidth: "100%"
|
|
1584
|
-
};
|
|
1585
|
-
(0, react.useEffect)(() => setExpandedAgentNodeId(void 0), [graph.graphDigest, run?.runId]);
|
|
1586
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1587
|
-
className: "dog-canvas-scroll",
|
|
1588
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1589
|
-
className: "dog-canvas-stage-wrap",
|
|
1590
|
-
style: wrapStyle,
|
|
1591
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1592
|
-
className: "dog-canvas-stage",
|
|
1593
|
-
style: stageStyle,
|
|
1594
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
1595
|
-
className: "dog-edges",
|
|
1596
|
-
width: layout.width,
|
|
1597
|
-
height: layout.height,
|
|
1598
|
-
"aria-hidden": "true",
|
|
1599
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("marker", {
|
|
1600
|
-
id: "dog-dependency-arrow",
|
|
1601
|
-
markerWidth: "8",
|
|
1602
|
-
markerHeight: "8",
|
|
1603
|
-
refX: "7",
|
|
1604
|
-
refY: "4",
|
|
1605
|
-
orient: "auto",
|
|
1606
|
-
markerUnits: "strokeWidth",
|
|
1607
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1608
|
-
d: "M 0 0 L 8 4 L 0 8 z",
|
|
1609
|
-
fill: "#c07a39"
|
|
1610
|
-
})
|
|
1611
|
-
}) }), layout.edges.map((edge) => {
|
|
1612
|
-
const connected = selectedNodeId === void 0 || edge.source === selectedNodeId || edge.target === selectedNodeId;
|
|
1613
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1614
|
-
className: "dog-edge",
|
|
1615
|
-
"data-kind": edge.kind,
|
|
1616
|
-
"data-muted": !connected,
|
|
1617
|
-
"data-highlighted": connected && selectedNodeId !== void 0,
|
|
1618
|
-
d: edge.path,
|
|
1619
|
-
markerEnd: edge.kind === "dependsOn" ? "url(#dog-dependency-arrow)" : void 0
|
|
1620
|
-
}, edge.id);
|
|
1621
|
-
})]
|
|
1622
|
-
}), layout.nodes.map((position) => {
|
|
1623
|
-
const node = graph.input.nodes[position.id];
|
|
1624
|
-
if (node === void 0) return null;
|
|
1625
|
-
const result = run?.goals[position.id] ?? { state: "pending" };
|
|
1626
|
-
const agents = goalAgentRefs(run, position.id);
|
|
1627
|
-
const expanded = expandedAgentNodeId === position.id;
|
|
1628
|
-
const style = {
|
|
1629
|
-
left: position.x,
|
|
1630
|
-
top: position.y,
|
|
1631
|
-
width: position.width,
|
|
1632
|
-
height: position.height
|
|
1633
|
-
};
|
|
1634
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1635
|
-
className: "dog-node",
|
|
1636
|
-
type: "button",
|
|
1637
|
-
style,
|
|
1638
|
-
"data-selected": position.id === selectedNodeId,
|
|
1639
|
-
"data-root": position.id === graph.input.root,
|
|
1640
|
-
"data-agents-expanded": expanded || void 0,
|
|
1641
|
-
"aria-expanded": expanded,
|
|
1642
|
-
"aria-label": `${node.title}: ${humanizeState(result.state)}. Click to ${expanded ? "hide" : "show"} ${agents.length} related Agents.`,
|
|
1643
|
-
onClick: () => {
|
|
1644
|
-
onSelectNode(position.id);
|
|
1645
|
-
setExpandedAgentNodeId((current) => current === position.id ? void 0 : position.id);
|
|
1646
|
-
},
|
|
1647
|
-
children: [
|
|
1648
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1649
|
-
className: "dog-node-top",
|
|
1650
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1651
|
-
className: position.id === graph.input.root ? "dog-node-kind dog-node-root" : "dog-node-kind",
|
|
1652
|
-
children: position.id === graph.input.root ? "Root goal" : `${node.constraint} · ${node.kind}`
|
|
1653
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusChip, { state: result.state })]
|
|
1654
|
-
}),
|
|
1655
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1656
|
-
className: "dog-node-title",
|
|
1657
|
-
children: node.title
|
|
1658
|
-
}),
|
|
1659
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1660
|
-
className: "dog-node-foot",
|
|
1661
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1662
|
-
className: "dog-node-id",
|
|
1663
|
-
children: position.id
|
|
1664
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1665
|
-
className: "dog-node-agents",
|
|
1666
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentIcon, {}), agents.length]
|
|
1667
|
-
})]
|
|
1668
|
-
})
|
|
1669
|
-
]
|
|
1670
|
-
}), expanded ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentFlyout, {
|
|
1671
|
-
goalTitle: node.title,
|
|
1672
|
-
refs: agents,
|
|
1673
|
-
sessions,
|
|
1674
|
-
style: agentFlyoutStyle(position, layout.width, layout.height),
|
|
1675
|
-
onClose: () => setExpandedAgentNodeId(void 0),
|
|
1676
|
-
openSession
|
|
1677
|
-
}) : null] }, position.id);
|
|
1678
|
-
})]
|
|
1679
|
-
})
|
|
1680
|
-
})
|
|
1681
|
-
});
|
|
1682
|
-
}
|
|
1683
|
-
function AgentFlyout({ goalTitle, refs, sessions, style, onClose, openSession }) {
|
|
1684
|
-
const [openingSession, setOpeningSession] = (0, react.useState)();
|
|
1685
|
-
const [error, setError] = (0, react.useState)();
|
|
1686
|
-
const agents = refs.map((ref) => goalAgentTelemetry(ref, sessions));
|
|
1687
|
-
const open = async (ref) => {
|
|
1688
|
-
setOpeningSession(ref.sessionId);
|
|
1689
|
-
setError(void 0);
|
|
1690
|
-
try {
|
|
1691
|
-
if (!await openSession(ref.sessionId, ref.parentSessionId)) setError("This Agent session is no longer addressable.");
|
|
1692
|
-
} catch (cause) {
|
|
1693
|
-
setError(cause instanceof Error ? cause.message : String(cause));
|
|
1694
|
-
} finally {
|
|
1695
|
-
setOpeningSession(void 0);
|
|
1696
|
-
}
|
|
1697
|
-
};
|
|
1698
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1699
|
-
className: "dog-agent-flyout",
|
|
1700
|
-
style,
|
|
1701
|
-
"aria-label": `Agents related to ${goalTitle}`,
|
|
1702
|
-
children: [
|
|
1703
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
1704
|
-
className: "dog-agent-flyout-head",
|
|
1705
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentIcon, {}), " Related Agents"] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1706
|
-
type: "button",
|
|
1707
|
-
onClick: onClose,
|
|
1708
|
-
"aria-label": "Close related Agents",
|
|
1709
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CloseIcon, {})
|
|
1710
|
-
})]
|
|
1711
|
-
}),
|
|
1712
|
-
agents.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1713
|
-
className: "dog-agent-empty",
|
|
1714
|
-
children: "No Agent has bound itself to this node."
|
|
1715
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1716
|
-
className: "dog-agent-list",
|
|
1717
|
-
children: agents.map((agent) => {
|
|
1718
|
-
const activity = agent.needsInput ? "Needs input" : agent.running ? "Running" : agent.available ? "Finished" : "Unavailable";
|
|
1719
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1720
|
-
className: "dog-agent-row",
|
|
1721
|
-
type: "button",
|
|
1722
|
-
disabled: openingSession !== void 0,
|
|
1723
|
-
onClick: () => void open(agent.ref),
|
|
1724
|
-
"aria-label": `Open ${agent.label}, ${activity}`,
|
|
1725
|
-
children: [
|
|
1726
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `dog-agent-state ${agent.running ? "dog-state-running" : agent.available ? "dog-state-success" : "dog-state-blocked"}` }),
|
|
1727
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1728
|
-
className: "dog-agent-copy",
|
|
1729
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1730
|
-
className: "dog-agent-name",
|
|
1731
|
-
children: agent.label
|
|
1732
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1733
|
-
className: "dog-agent-meta",
|
|
1734
|
-
children: [
|
|
1735
|
-
humanizeState(agent.ref.role),
|
|
1736
|
-
" · ",
|
|
1737
|
-
activity
|
|
1738
|
-
]
|
|
1739
|
-
})]
|
|
1740
|
-
}),
|
|
1741
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1742
|
-
className: "dog-agent-metrics",
|
|
1743
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: agent.tokens === void 0 ? "— tok" : `${formatCompactNumber(agent.tokens)} tok` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: agent.durationMs === void 0 ? "—" : formatAgentDuration(agent.durationMs) })]
|
|
1744
|
-
})
|
|
1745
|
-
]
|
|
1746
|
-
}) }, agent.ref.sessionId);
|
|
1747
|
-
})
|
|
1748
|
-
}),
|
|
1749
|
-
error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1750
|
-
className: "dog-agent-error",
|
|
1751
|
-
role: "status",
|
|
1752
|
-
children: error
|
|
1753
|
-
}),
|
|
1754
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1755
|
-
className: "dog-agent-hint",
|
|
1756
|
-
children: "Click an Agent to open its native DSH conversation."
|
|
1757
|
-
})
|
|
1758
|
-
]
|
|
1759
|
-
});
|
|
1760
|
-
}
|
|
1761
|
-
function Inspector({ graph, run, nodeId, readGoalRuntime, openSession }) {
|
|
1762
|
-
const node = nodeId === void 0 ? void 0 : graph.input.nodes[nodeId];
|
|
1763
|
-
if (node === void 0 || nodeId === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
|
|
1764
|
-
className: "dog-inspector",
|
|
1765
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1766
|
-
className: "dog-empty-small",
|
|
1767
|
-
children: "Select a goal to inspect its contract and evidence."
|
|
1768
|
-
})
|
|
1769
|
-
});
|
|
1770
|
-
const result = run?.goals[nodeId] ?? { state: "pending" };
|
|
1771
|
-
const plan = graph.acceptancePlans[nodeId];
|
|
1772
|
-
const parents = graph.input.contains.filter((edge) => edge.child === nodeId);
|
|
1773
|
-
const children = graph.input.contains.filter((edge) => edge.parent === nodeId);
|
|
1774
|
-
const dependencies = graph.input.dependsOn.filter((edge) => edge.source === nodeId || edge.target === nodeId);
|
|
1775
|
-
const reason = result.reason ?? (result.verification?.passed === false ? "Trusted verifier returned false for this sandboxed input." : void 0);
|
|
1776
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
1777
|
-
className: "dog-inspector",
|
|
1778
|
-
"aria-label": "Selected goal details",
|
|
1779
|
-
children: [
|
|
1780
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1781
|
-
className: "dog-inspector-head",
|
|
1782
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1783
|
-
className: "dog-inspector-title-wrap",
|
|
1784
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1785
|
-
className: "dog-inspector-eyebrow",
|
|
1786
|
-
children: nodeId === graph.input.root ? "Root goal" : "Goal contract"
|
|
1787
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
1788
|
-
className: "dog-inspector-title",
|
|
1789
|
-
children: node.title
|
|
1790
|
-
})]
|
|
1791
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusChip, { state: result.state })]
|
|
1792
|
-
}),
|
|
1793
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1794
|
-
className: "dog-inspector-chips",
|
|
1795
|
-
children: [
|
|
1796
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1797
|
-
className: "dog-mini-chip",
|
|
1798
|
-
children: node.constraint
|
|
1799
|
-
}),
|
|
1800
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1801
|
-
className: "dog-mini-chip",
|
|
1802
|
-
children: node.kind
|
|
1803
|
-
}),
|
|
1804
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1805
|
-
className: "dog-mini-chip dog-mono",
|
|
1806
|
-
children: nodeId
|
|
1807
|
-
})
|
|
1808
|
-
]
|
|
1809
|
-
}),
|
|
1810
|
-
reason === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1811
|
-
className: `dog-inspector-section ${stateClass(result.state)}`,
|
|
1812
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1813
|
-
className: "dog-inspector-section-title",
|
|
1814
|
-
children: "Why this state"
|
|
1815
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1816
|
-
className: "dog-reason",
|
|
1817
|
-
children: reason
|
|
1818
|
-
})]
|
|
1819
|
-
}),
|
|
1820
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1821
|
-
className: "dog-inspector-section",
|
|
1822
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1823
|
-
className: "dog-inspector-section-title",
|
|
1824
|
-
children: "Contract"
|
|
1825
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
1826
|
-
className: "dog-definition",
|
|
1827
|
-
children: [
|
|
1828
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Constraint" }),
|
|
1829
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: node.constraint }),
|
|
1830
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Completion" }),
|
|
1831
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
1832
|
-
className: "dog-mono",
|
|
1833
|
-
children: node.completion === void 0 ? "atomic verifier" : formatExpression(node.completion)
|
|
1834
|
-
}),
|
|
1835
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Updated" }),
|
|
1836
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: run === void 0 ? "No run yet" : formatTimestamp(run.updatedAt) }),
|
|
1837
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Graph digest" }),
|
|
1838
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
1839
|
-
className: "dog-mono",
|
|
1840
|
-
title: graph.graphDigest,
|
|
1841
|
-
children: shortDigest(graph.graphDigest)
|
|
1842
|
-
})
|
|
1843
|
-
]
|
|
1844
|
-
})]
|
|
1845
|
-
}),
|
|
1846
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeContextPanel, {
|
|
1847
|
-
run,
|
|
1848
|
-
goalId: nodeId,
|
|
1849
|
-
readGoalRuntime,
|
|
1850
|
-
openSession
|
|
1851
|
-
}),
|
|
1852
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Evidence, {
|
|
1853
|
-
node,
|
|
1854
|
-
result,
|
|
1855
|
-
plan
|
|
1856
|
-
}),
|
|
1857
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1858
|
-
className: "dog-inspector-section",
|
|
1859
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1860
|
-
className: "dog-inspector-section-title",
|
|
1861
|
-
children: "Relations"
|
|
1862
|
-
}), parents.length + children.length + dependencies.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1863
|
-
className: "dog-empty-small",
|
|
1864
|
-
children: "No graph relations."
|
|
1865
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
|
|
1866
|
-
className: "dog-relation-list",
|
|
1867
|
-
children: [
|
|
1868
|
-
parents.map((edge, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
1869
|
-
className: "dog-relation",
|
|
1870
|
-
children: [
|
|
1871
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: edge.parent }),
|
|
1872
|
-
" contains this goal · ",
|
|
1873
|
-
edge.required ? "required" : "optional",
|
|
1874
|
-
" · ",
|
|
1875
|
-
edge.failure
|
|
1876
|
-
]
|
|
1877
|
-
}, `parent:${index}`)),
|
|
1878
|
-
children.map((edge, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
1879
|
-
className: "dog-relation",
|
|
1880
|
-
children: [
|
|
1881
|
-
"Contains ",
|
|
1882
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: edge.child }),
|
|
1883
|
-
" · ",
|
|
1884
|
-
edge.required ? "required" : "optional",
|
|
1885
|
-
" · ",
|
|
1886
|
-
edge.failure
|
|
1887
|
-
]
|
|
1888
|
-
}, `child:${index}`)),
|
|
1889
|
-
dependencies.map((edge, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
1890
|
-
className: "dog-relation",
|
|
1891
|
-
"data-kind": "dependsOn",
|
|
1892
|
-
children: [
|
|
1893
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: edge.source }),
|
|
1894
|
-
" depends on ",
|
|
1895
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: edge.target }),
|
|
1896
|
-
edge.data === void 0 ? "" : ` · ${edge.data.join(", ")}`
|
|
1897
|
-
]
|
|
1898
|
-
}, `dependency:${index}`))
|
|
1899
|
-
]
|
|
1900
|
-
})]
|
|
1901
|
-
}),
|
|
1902
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
1903
|
-
className: "dog-inspector-section",
|
|
1904
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
1905
|
-
className: "dog-raw",
|
|
1906
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "Raw goal record" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: JSON.stringify({
|
|
1907
|
-
nodeId,
|
|
1908
|
-
node,
|
|
1909
|
-
result,
|
|
1910
|
-
acceptancePlan: plan
|
|
1911
|
-
}, null, 2) })]
|
|
1912
|
-
})
|
|
1913
|
-
})
|
|
1914
|
-
]
|
|
1915
|
-
});
|
|
1916
|
-
}
|
|
1917
|
-
function RuntimeContextPanel({ run, goalId, readGoalRuntime, openSession }) {
|
|
1918
|
-
const [trace, setTrace] = (0, react.useState)();
|
|
1919
|
-
const [loading, setLoading] = (0, react.useState)(false);
|
|
1920
|
-
const [error, setError] = (0, react.useState)();
|
|
1921
|
-
const [sessionError, setSessionError] = (0, react.useState)();
|
|
1922
|
-
const [openingSession, setOpeningSession] = (0, react.useState)(false);
|
|
1923
|
-
const runId = run?.runId;
|
|
1924
|
-
const runState = run?.state;
|
|
1925
|
-
(0, react.useEffect)(() => {
|
|
1926
|
-
setTrace(void 0);
|
|
1927
|
-
setError(void 0);
|
|
1928
|
-
setSessionError(void 0);
|
|
1929
|
-
setOpeningSession(false);
|
|
1930
|
-
if (runId === void 0 || runState === void 0) {
|
|
1931
|
-
setLoading(false);
|
|
1932
|
-
return;
|
|
1933
|
-
}
|
|
1934
|
-
let disposed = false;
|
|
1935
|
-
let inFlight = false;
|
|
1936
|
-
const controller = new AbortController();
|
|
1937
|
-
const refresh = async () => {
|
|
1938
|
-
if (inFlight) return;
|
|
1939
|
-
inFlight = true;
|
|
1940
|
-
setLoading(true);
|
|
1941
|
-
try {
|
|
1942
|
-
const next = parseGoalRuntimeTrace(await readGoalRuntime(runId, goalId, controller.signal));
|
|
1943
|
-
if (next.runId !== runId || next.goalId !== goalId) throw new Error("runtime trace identity mismatch");
|
|
1944
|
-
if (!disposed) {
|
|
1945
|
-
setTrace(next);
|
|
1946
|
-
setError(void 0);
|
|
1947
|
-
}
|
|
1948
|
-
} catch (cause) {
|
|
1949
|
-
if (!disposed && !controller.signal.aborted) setError(cause instanceof Error ? cause.message : String(cause));
|
|
1950
|
-
} finally {
|
|
1951
|
-
inFlight = false;
|
|
1952
|
-
if (!disposed) setLoading(false);
|
|
1953
|
-
}
|
|
1954
|
-
};
|
|
1955
|
-
refresh();
|
|
1956
|
-
const timer = runState === "running" ? window.setInterval(() => void refresh(), 1500) : void 0;
|
|
1957
|
-
return () => {
|
|
1958
|
-
disposed = true;
|
|
1959
|
-
controller.abort();
|
|
1960
|
-
if (timer !== void 0) window.clearInterval(timer);
|
|
1961
|
-
};
|
|
1962
|
-
}, [
|
|
1963
|
-
goalId,
|
|
1964
|
-
readGoalRuntime,
|
|
1965
|
-
runId,
|
|
1966
|
-
runState
|
|
1967
|
-
]);
|
|
1968
|
-
if (run === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1969
|
-
className: "dog-inspector-section",
|
|
1970
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
1971
|
-
className: "dog-inspector-section-title",
|
|
1972
|
-
children: "Runtime context"
|
|
1973
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1974
|
-
className: "dog-empty-small dog-runtime-empty",
|
|
1975
|
-
children: "Run this graph to capture node activity and failure context."
|
|
1976
|
-
})]
|
|
1977
|
-
});
|
|
1978
|
-
const events = trace?.events ?? [];
|
|
1979
|
-
const latestEvent = events[events.length - 1];
|
|
1980
|
-
const errorEvent = [...events].reverse().find((event) => event.phase === "structured_error");
|
|
1981
|
-
const attempts = new Set(events.map((event) => event.attempt ?? 1)).size;
|
|
1982
|
-
const invocation = trace?.invocation;
|
|
1983
|
-
const goalState = trace?.result.state ?? run.goals[goalId]?.state ?? "pending";
|
|
1984
|
-
const activity = runtimeActivity(goalState, latestEvent, loading);
|
|
1985
|
-
const openInvoker = async () => {
|
|
1986
|
-
setSessionError(void 0);
|
|
1987
|
-
const sessionId = invocation?.agentSessionId;
|
|
1988
|
-
const parentSessionId = invocation?.parentSessionId;
|
|
1989
|
-
if (sessionId === void 0) return;
|
|
1990
|
-
setOpeningSession(true);
|
|
1991
|
-
try {
|
|
1992
|
-
if (!await openSession(sessionId, parentSessionId)) setSessionError("The invoking session is no longer available in this client.");
|
|
1993
|
-
} catch (cause) {
|
|
1994
|
-
setSessionError(cause instanceof Error ? cause.message : String(cause));
|
|
1995
|
-
} finally {
|
|
1996
|
-
setOpeningSession(false);
|
|
1997
|
-
}
|
|
1998
|
-
};
|
|
1999
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2000
|
-
className: "dog-inspector-section",
|
|
2001
|
-
"aria-label": "Goal runtime context",
|
|
2002
|
-
children: [
|
|
2003
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2004
|
-
className: "dog-runtime-heading",
|
|
2005
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
2006
|
-
className: "dog-inspector-section-title",
|
|
2007
|
-
children: "Runtime context"
|
|
2008
|
-
}), loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2009
|
-
className: "dog-runtime-live",
|
|
2010
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dog-runtime-pulse" }), "refreshing"]
|
|
2011
|
-
}) : null]
|
|
2012
|
-
}),
|
|
2013
|
-
error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2014
|
-
className: "dog-runtime-warning",
|
|
2015
|
-
children: ["Context unavailable: ", error]
|
|
2016
|
-
}),
|
|
2017
|
-
trace?.runtimeWarning === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2018
|
-
className: "dog-runtime-warning",
|
|
2019
|
-
children: trace.runtimeWarning
|
|
2020
|
-
}),
|
|
2021
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2022
|
-
className: `dog-runtime-card ${stateClass(goalState)}`,
|
|
2023
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dog-runtime-orb" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2024
|
-
className: "dog-runtime-card-copy",
|
|
2025
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2026
|
-
className: "dog-runtime-activity",
|
|
2027
|
-
children: activity
|
|
2028
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2029
|
-
className: "dog-runtime-meta",
|
|
2030
|
-
children: [events.length === 0 ? "No events yet" : `${events.length} events · ${attempts} attempt${attempts === 1 ? "" : "s"}`, latestEvent?.durationMs === void 0 ? "" : ` · ${formatDuration(latestEvent.durationMs)}`]
|
|
2031
|
-
})]
|
|
2032
|
-
})]
|
|
2033
|
-
}),
|
|
2034
|
-
errorEvent === void 0 || errorEvent.reason === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2035
|
-
className: `dog-runtime-error ${stateClass(errorEvent.state ?? "needs_human")}`,
|
|
2036
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Verification error" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: errorEvent.reason })]
|
|
2037
|
-
}),
|
|
2038
|
-
invocation === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2039
|
-
className: "dog-runtime-session",
|
|
2040
|
-
children: [
|
|
2041
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2042
|
-
className: "dog-runtime-session-head",
|
|
2043
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Invoking DSH session" }), invocation.agentSessionId === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2044
|
-
className: "dog-runtime-session-button",
|
|
2045
|
-
type: "button",
|
|
2046
|
-
disabled: openingSession,
|
|
2047
|
-
onClick: () => void openInvoker(),
|
|
2048
|
-
children: openingSession ? "Opening…" : "Open session"
|
|
2049
|
-
})]
|
|
2050
|
-
}),
|
|
2051
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
2052
|
-
className: "dog-definition",
|
|
2053
|
-
children: [
|
|
2054
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Session" }),
|
|
2055
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
2056
|
-
className: "dog-mono",
|
|
2057
|
-
children: invocation.agentSessionId === void 0 ? "headless / unavailable" : shortId(invocation.agentSessionId)
|
|
2058
|
-
}),
|
|
2059
|
-
invocation.parentSessionId === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Parent" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
2060
|
-
className: "dog-mono",
|
|
2061
|
-
children: shortId(invocation.parentSessionId)
|
|
2062
|
-
})] }),
|
|
2063
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Tool call" }),
|
|
2064
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
2065
|
-
className: "dog-mono",
|
|
2066
|
-
title: invocation.callId,
|
|
2067
|
-
children: shortId(invocation.callId)
|
|
2068
|
-
}),
|
|
2069
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Invoked" }),
|
|
2070
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: formatTimestamp(invocation.invokedAt) })
|
|
2071
|
-
]
|
|
2072
|
-
}),
|
|
2073
|
-
sessionError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2074
|
-
className: "dog-runtime-session-error",
|
|
2075
|
-
children: sessionError
|
|
2076
|
-
})
|
|
2077
|
-
]
|
|
2078
|
-
}),
|
|
2079
|
-
events.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2080
|
-
className: "dog-empty-small dog-runtime-empty",
|
|
2081
|
-
children: loading ? "Loading node activity…" : "No runtime events were recorded for this node."
|
|
2082
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", {
|
|
2083
|
-
className: "dog-runtime-timeline",
|
|
2084
|
-
"aria-label": "Runtime event timeline",
|
|
2085
|
-
children: events.map((event, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
2086
|
-
className: `dog-runtime-event ${stateClass(event.state ?? "running")}`,
|
|
2087
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dog-runtime-marker" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2088
|
-
className: "dog-runtime-event-copy",
|
|
2089
|
-
children: [
|
|
2090
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2091
|
-
className: "dog-runtime-event-head",
|
|
2092
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: runtimeEventLabel(event.phase) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
|
|
2093
|
-
dateTime: event.at,
|
|
2094
|
-
children: formatTime(event.at)
|
|
2095
|
-
})]
|
|
2096
|
-
}),
|
|
2097
|
-
event.attempt === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2098
|
-
className: "dog-runtime-event-meta",
|
|
2099
|
-
children: ["Attempt ", event.attempt]
|
|
2100
|
-
}),
|
|
2101
|
-
runtimeEventDetail(event) === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2102
|
-
className: "dog-runtime-event-detail",
|
|
2103
|
-
children: runtimeEventDetail(event)
|
|
2104
|
-
})
|
|
2105
|
-
]
|
|
2106
|
-
})]
|
|
2107
|
-
}, index))
|
|
2108
|
-
}),
|
|
2109
|
-
trace?.truncated === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2110
|
-
className: "dog-runtime-warning",
|
|
2111
|
-
children: "Showing the latest 64 events for this goal."
|
|
2112
|
-
}) : null,
|
|
2113
|
-
trace === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
2114
|
-
className: "dog-raw dog-runtime-raw",
|
|
2115
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "Raw runtime trace" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: JSON.stringify(trace, null, 2) })]
|
|
2116
|
-
})
|
|
2117
|
-
]
|
|
2118
|
-
});
|
|
2119
|
-
}
|
|
2120
|
-
function runtimeActivity(state, event, loading) {
|
|
2121
|
-
if (event === void 0) return loading ? "Loading runtime context" : state === "pending" ? "Waiting for scheduler" : humanizeState(state);
|
|
2122
|
-
if (event.phase === "verifier_started" && event.verifier !== void 0) return `Running ${event.verifier.mode} kernel`;
|
|
2123
|
-
if (event.phase === "dependency_blocked") return "Blocked by an upstream dependency";
|
|
2124
|
-
if (event.phase === "structured_error") return "Execution needs human review";
|
|
2125
|
-
if (event.phase === "goal_settled") return `Settled as ${humanizeState(event.state ?? state)}`;
|
|
2126
|
-
return runtimeEventLabel(event.phase);
|
|
2127
|
-
}
|
|
2128
|
-
function runtimeEventLabel(phase) {
|
|
2129
|
-
switch (phase) {
|
|
2130
|
-
case "goal_started": return "Goal started";
|
|
2131
|
-
case "dependency_blocked": return "Dependency blocked";
|
|
2132
|
-
case "grounding_extracted": return "Grounding material extracted";
|
|
2133
|
-
case "workspace_allocated": return "Isolated workspace allocated";
|
|
2134
|
-
case "verifier_started": return "Verifier started";
|
|
2135
|
-
case "verifier_passed": return "Verifier passed";
|
|
2136
|
-
case "verifier_failed": return "Verifier failed";
|
|
2137
|
-
case "verifier_inconclusive": return "Verifier inconclusive";
|
|
2138
|
-
case "composite_evaluated": return "Completion rule evaluated";
|
|
2139
|
-
case "result_inherited": return "Verification reused: material unchanged";
|
|
2140
|
-
case "verifier_released": return "Verifier worker released";
|
|
2141
|
-
case "verifier_bind_failed": return "Verifier worker binding failed";
|
|
2142
|
-
case "structured_error": return "Runtime error";
|
|
2143
|
-
case "goal_settled": return "Goal settled";
|
|
2144
|
-
case "run_warning": return "Run warning";
|
|
2145
|
-
}
|
|
2146
|
-
}
|
|
2147
|
-
function runtimeEventDetail(event) {
|
|
2148
|
-
if (event.reason !== void 0) return event.reason;
|
|
2149
|
-
if (event.verifier !== void 0) return `${event.verifier.mode} kernel`;
|
|
2150
|
-
}
|
|
2151
|
-
function formatDuration(value) {
|
|
2152
|
-
return value < 1e3 ? `${value} ms` : `${(value / 1e3).toFixed(value < 1e4 ? 1 : 0)} s`;
|
|
2153
|
-
}
|
|
2154
|
-
function Evidence({ node, result, plan }) {
|
|
2155
|
-
if (node.kind !== "leaf") return null;
|
|
2156
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2157
|
-
className: "dog-inspector-section",
|
|
2158
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
2159
|
-
className: "dog-inspector-section-title",
|
|
2160
|
-
children: "Trusted evidence"
|
|
2161
|
-
}), plan === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2162
|
-
className: "dog-reason dog-state-needs_human",
|
|
2163
|
-
children: "No compiled acceptance plan is available."
|
|
2164
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2165
|
-
className: "dog-evidence",
|
|
2166
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2167
|
-
className: "dog-evidence-head",
|
|
2168
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2169
|
-
className: "dog-evidence-name",
|
|
2170
|
-
children: plan.verifier.mode === "programmatic" ? `script:${plan.verifier.script}` : "agentic"
|
|
2171
|
-
}), result.verification === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2172
|
-
className: "dog-mini-chip",
|
|
2173
|
-
children: "not run"
|
|
2174
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusChip, { state: result.verification.passed ? "success" : "failure" })]
|
|
2175
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2176
|
-
className: "dog-evidence-body",
|
|
2177
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
2178
|
-
className: "dog-definition",
|
|
2179
|
-
children: [
|
|
2180
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Sandbox file" }),
|
|
2181
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
2182
|
-
className: "dog-mono",
|
|
2183
|
-
children: typeof plan.input?.path === "string" && plan.input.path.length > 0 ? plan.input.path : "(run workspace)"
|
|
2184
|
-
}),
|
|
2185
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Digest" }),
|
|
2186
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
2187
|
-
className: "dog-mono",
|
|
2188
|
-
title: plan.input?.digest,
|
|
2189
|
-
children: plan.input === void 0 ? "—" : shortId(plan.input.digest)
|
|
2190
|
-
}),
|
|
2191
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Bytes" }),
|
|
2192
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: plan.input === void 0 ? "—" : plan.input.byteLength.toLocaleString() }),
|
|
2193
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: "Target" }),
|
|
2194
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
2195
|
-
className: "dog-mono",
|
|
2196
|
-
children: plan.target
|
|
2197
|
-
})
|
|
2198
|
-
]
|
|
2199
|
-
}), result.verification === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2200
|
-
className: "dog-inspector-section",
|
|
2201
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h5", {
|
|
2202
|
-
className: "dog-inspector-section-title",
|
|
2203
|
-
children: "Evidence"
|
|
2204
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2205
|
-
className: "dog-observation",
|
|
2206
|
-
children: Object.entries(result.verification.evidence ?? {}).map(([key, value]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2207
|
-
className: "dog-observation-row",
|
|
2208
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2209
|
-
className: "dog-observation-key",
|
|
2210
|
-
children: key
|
|
2211
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2212
|
-
className: "dog-observation-value",
|
|
2213
|
-
children: formatJson(value)
|
|
2214
|
-
})]
|
|
2215
|
-
}, key))
|
|
2216
|
-
})]
|
|
2217
|
-
})]
|
|
2218
|
-
})]
|
|
2219
|
-
})]
|
|
2220
|
-
});
|
|
2221
|
-
}
|
|
2222
|
-
function EmptyWorkspace({ loading, error }) {
|
|
2223
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2224
|
-
className: "dog-workspace",
|
|
2225
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2226
|
-
className: "dog-empty",
|
|
2227
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2228
|
-
className: "dog-empty-card",
|
|
2229
|
-
children: [
|
|
2230
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2231
|
-
className: "dog-empty-icon",
|
|
2232
|
-
children: loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RefreshIcon, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NetworkIcon, { size: 22 })
|
|
2233
|
-
}),
|
|
2234
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
2235
|
-
className: "dog-empty-title",
|
|
2236
|
-
children: loading ? "Loading DoG revisions…" : error === void 0 ? "No persisted graphs yet" : "Debugger data unavailable"
|
|
2237
|
-
}),
|
|
2238
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2239
|
-
className: "dog-empty-copy",
|
|
2240
|
-
children: error ?? "Create a graph with dog_create, then run it. The immutable revision and verifier evidence will appear here automatically."
|
|
2241
|
-
})
|
|
2242
|
-
]
|
|
2243
|
-
})
|
|
2244
|
-
})
|
|
2245
|
-
});
|
|
2246
|
-
}
|
|
2247
|
-
function StatusChip({ state }) {
|
|
2248
|
-
const title = state === "inherited" ? "Reused the prior run verification record: same material digest (GM) and same verifier contract. Not re-run." : void 0;
|
|
2249
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2250
|
-
className: `dog-status-chip ${stateClass(state)}`,
|
|
2251
|
-
title,
|
|
2252
|
-
children: humanizeState(state)
|
|
2253
|
-
});
|
|
2254
|
-
}
|
|
2255
|
-
function IconButton({ label, busy, onClick, children }) {
|
|
2256
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2257
|
-
className: "dog-icon-button",
|
|
2258
|
-
type: "button",
|
|
2259
|
-
"aria-label": label,
|
|
2260
|
-
title: label,
|
|
2261
|
-
"aria-busy": busy,
|
|
2262
|
-
onClick,
|
|
2263
|
-
children
|
|
2264
|
-
});
|
|
2265
|
-
}
|
|
2266
|
-
function readDogDockCollapsed() {
|
|
2267
|
-
try {
|
|
2268
|
-
if (typeof window === "undefined") return true;
|
|
2269
|
-
const stored = window.localStorage.getItem(DOG_DOCK_COLLAPSED_KEY);
|
|
2270
|
-
return stored === null ? true : stored === "true";
|
|
2271
|
-
} catch {
|
|
2272
|
-
return true;
|
|
2273
|
-
}
|
|
2274
|
-
}
|
|
2275
|
-
function writeDogDockCollapsed(collapsed) {
|
|
2276
|
-
try {
|
|
2277
|
-
window.localStorage.setItem(DOG_DOCK_COLLAPSED_KEY, String(collapsed));
|
|
2278
|
-
} catch {}
|
|
2279
|
-
}
|
|
2280
|
-
function latestRun(revision) {
|
|
2281
|
-
return revision.runs[0];
|
|
2282
|
-
}
|
|
2283
|
-
function isAttentionGoal(state) {
|
|
2284
|
-
return state === "failure" || state === "needs_human" || state === "blocked" || state === "partial";
|
|
2285
|
-
}
|
|
2286
|
-
function stateClass(state) {
|
|
2287
|
-
return `dog-state-${state}`;
|
|
2288
|
-
}
|
|
2289
|
-
function humanizeState(state) {
|
|
2290
|
-
return state.replaceAll("_", " ").replace(/\b\w/gu, (letter) => letter.toUpperCase());
|
|
2291
|
-
}
|
|
2292
|
-
function formatExpression(expression) {
|
|
2293
|
-
switch (expression.op) {
|
|
2294
|
-
case "ref": return expression.id;
|
|
2295
|
-
case "not": return `NOT(${formatExpression(expression.item)})`;
|
|
2296
|
-
case "all": return `ALL(${expression.items.map(formatExpression).join(", ")})`;
|
|
2297
|
-
case "any": return `ANY(${expression.items.map(formatExpression).join(", ")})`;
|
|
2298
|
-
case "atLeast": return `AT_LEAST ${expression.count}(${expression.items.map(formatExpression).join(", ")})`;
|
|
2299
|
-
}
|
|
2300
|
-
}
|
|
2301
|
-
function formatJson(value) {
|
|
2302
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
2303
|
-
}
|
|
2304
|
-
function formatTime(value) {
|
|
2305
|
-
const date = new Date(value);
|
|
2306
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
2307
|
-
return new Intl.DateTimeFormat(void 0, {
|
|
2308
|
-
hour: "2-digit",
|
|
2309
|
-
minute: "2-digit",
|
|
2310
|
-
month: "short",
|
|
2311
|
-
day: "numeric"
|
|
2312
|
-
}).format(date);
|
|
2313
|
-
}
|
|
2314
|
-
function formatTimestamp(value) {
|
|
2315
|
-
const date = new Date(value);
|
|
2316
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
2317
|
-
return new Intl.DateTimeFormat(void 0, {
|
|
2318
|
-
dateStyle: "medium",
|
|
2319
|
-
timeStyle: "short"
|
|
2320
|
-
}).format(date);
|
|
2321
|
-
}
|
|
2322
|
-
function shortDigest(value) {
|
|
2323
|
-
return `${value.slice(0, 8)}…${value.slice(-5)}`;
|
|
2324
|
-
}
|
|
2325
|
-
function shortId(value) {
|
|
2326
|
-
return value.length <= 17 ? value : `${value.slice(0, 9)}…${value.slice(-6)}`;
|
|
2327
|
-
}
|
|
2328
|
-
function formatCompactNumber(value) {
|
|
2329
|
-
return new Intl.NumberFormat("en-US", {
|
|
2330
|
-
notation: "compact",
|
|
2331
|
-
maximumFractionDigits: 1
|
|
2332
|
-
}).format(value);
|
|
2333
|
-
}
|
|
2334
|
-
function formatTokenMetric(tokens, partial) {
|
|
2335
|
-
if (tokens === void 0) return "—";
|
|
2336
|
-
const formatted = formatCompactNumber(tokens);
|
|
2337
|
-
return partial ? `≥${formatted}` : formatted;
|
|
2338
|
-
}
|
|
2339
|
-
function formatAgentDuration(value) {
|
|
2340
|
-
if (value < 6e4) return `${Math.max(1, Math.round(value / 1e3))}s`;
|
|
2341
|
-
if (value < 36e5) return `${Math.round(value / 6e4)}m`;
|
|
2342
|
-
return `${(value / 36e5).toFixed(value < 36e6 ? 1 : 0)}h`;
|
|
2343
|
-
}
|
|
2344
|
-
function agentFlyoutStyle(position, canvasWidth, canvasHeight) {
|
|
2345
|
-
const width = 228;
|
|
2346
|
-
const gap = 10;
|
|
2347
|
-
const right = position.x + position.width + gap;
|
|
2348
|
-
const left = right + width <= canvasWidth ? right : Math.max(gap, position.x - width - gap);
|
|
2349
|
-
const maxHeight = Math.max(150, canvasHeight - 20);
|
|
2350
|
-
return {
|
|
2351
|
-
left,
|
|
2352
|
-
top: Math.min(Math.max(gap, position.y - 4), Math.max(gap, canvasHeight - Math.min(250, maxHeight) - gap)),
|
|
2353
|
-
width,
|
|
2354
|
-
maxHeight
|
|
2355
|
-
};
|
|
2356
|
-
}
|
|
2357
|
-
function clampZoom(value) {
|
|
2358
|
-
return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, Math.round(value * 10) / 10));
|
|
2359
|
-
}
|
|
2360
|
-
function NetworkIcon({ size = 16 }) {
|
|
2361
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
2362
|
-
width: size,
|
|
2363
|
-
height: size,
|
|
2364
|
-
viewBox: "0 0 24 24",
|
|
2365
|
-
fill: "none",
|
|
2366
|
-
"aria-hidden": "true",
|
|
2367
|
-
children: [
|
|
2368
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
2369
|
-
cx: "12",
|
|
2370
|
-
cy: "5",
|
|
2371
|
-
r: "2.5",
|
|
2372
|
-
fill: "currentColor"
|
|
2373
|
-
}),
|
|
2374
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
2375
|
-
cx: "5",
|
|
2376
|
-
cy: "18",
|
|
2377
|
-
r: "2.5",
|
|
2378
|
-
fill: "currentColor"
|
|
2379
|
-
}),
|
|
2380
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
2381
|
-
cx: "19",
|
|
2382
|
-
cy: "18",
|
|
2383
|
-
r: "2.5",
|
|
2384
|
-
fill: "currentColor"
|
|
2385
|
-
}),
|
|
2386
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2387
|
-
d: "M10.6 7.1 6.4 15.6M13.4 7.1l4.2 8.5M7.5 18h9",
|
|
2388
|
-
stroke: "currentColor",
|
|
2389
|
-
strokeWidth: "1.6",
|
|
2390
|
-
strokeLinecap: "round"
|
|
2391
|
-
})
|
|
2392
|
-
]
|
|
2393
|
-
});
|
|
2394
|
-
}
|
|
2395
|
-
function AgentIcon() {
|
|
2396
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
2397
|
-
width: "13",
|
|
2398
|
-
height: "13",
|
|
2399
|
-
viewBox: "0 0 24 24",
|
|
2400
|
-
fill: "none",
|
|
2401
|
-
"aria-hidden": "true",
|
|
2402
|
-
children: [
|
|
2403
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
2404
|
-
cx: "12",
|
|
2405
|
-
cy: "8",
|
|
2406
|
-
r: "3.2",
|
|
2407
|
-
stroke: "currentColor",
|
|
2408
|
-
strokeWidth: "1.7"
|
|
2409
|
-
}),
|
|
2410
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2411
|
-
d: "M5.5 19c.5-3.4 2.7-5.3 6.5-5.3s6 1.9 6.5 5.3",
|
|
2412
|
-
stroke: "currentColor",
|
|
2413
|
-
strokeWidth: "1.7",
|
|
2414
|
-
strokeLinecap: "round"
|
|
2415
|
-
}),
|
|
2416
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2417
|
-
d: "M18.3 7.2h2.2M19.4 6.1v2.2",
|
|
2418
|
-
stroke: "currentColor",
|
|
2419
|
-
strokeWidth: "1.5",
|
|
2420
|
-
strokeLinecap: "round"
|
|
2421
|
-
})
|
|
2422
|
-
]
|
|
2423
|
-
});
|
|
2424
|
-
}
|
|
2425
|
-
function RefreshIcon() {
|
|
2426
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2427
|
-
width: "16",
|
|
2428
|
-
height: "16",
|
|
2429
|
-
viewBox: "0 0 24 24",
|
|
2430
|
-
fill: "none",
|
|
2431
|
-
"aria-hidden": "true",
|
|
2432
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2433
|
-
d: "M19 8a8 8 0 1 0 1 7M19 4v4h-4",
|
|
2434
|
-
stroke: "currentColor",
|
|
2435
|
-
strokeWidth: "1.8",
|
|
2436
|
-
strokeLinecap: "round",
|
|
2437
|
-
strokeLinejoin: "round"
|
|
2438
|
-
})
|
|
2439
|
-
});
|
|
2440
|
-
}
|
|
2441
|
-
function CloseIcon() {
|
|
2442
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2443
|
-
width: "17",
|
|
2444
|
-
height: "17",
|
|
2445
|
-
viewBox: "0 0 24 24",
|
|
2446
|
-
fill: "none",
|
|
2447
|
-
"aria-hidden": "true",
|
|
2448
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2449
|
-
d: "m6 6 12 12M18 6 6 18",
|
|
2450
|
-
stroke: "currentColor",
|
|
2451
|
-
strokeWidth: "1.8",
|
|
2452
|
-
strokeLinecap: "round"
|
|
2453
|
-
})
|
|
2454
|
-
});
|
|
2455
|
-
}
|
|
2456
|
-
function DockCollapseIcon() {
|
|
2457
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2458
|
-
width: "16",
|
|
2459
|
-
height: "16",
|
|
2460
|
-
viewBox: "0 0 24 24",
|
|
2461
|
-
fill: "none",
|
|
2462
|
-
"aria-hidden": "true",
|
|
2463
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2464
|
-
d: "m14.5 6-6 6 6 6",
|
|
2465
|
-
stroke: "currentColor",
|
|
2466
|
-
strokeWidth: "1.8",
|
|
2467
|
-
strokeLinecap: "round",
|
|
2468
|
-
strokeLinejoin: "round"
|
|
2469
|
-
})
|
|
2470
|
-
});
|
|
2471
|
-
}
|
|
2472
|
-
function DockExpandIcon() {
|
|
2473
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2474
|
-
width: "14",
|
|
2475
|
-
height: "14",
|
|
2476
|
-
viewBox: "0 0 24 24",
|
|
2477
|
-
fill: "none",
|
|
2478
|
-
"aria-hidden": "true",
|
|
2479
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2480
|
-
d: "m9.5 6 6 6-6 6",
|
|
2481
|
-
stroke: "currentColor",
|
|
2482
|
-
strokeWidth: "1.8",
|
|
2483
|
-
strokeLinecap: "round",
|
|
2484
|
-
strokeLinejoin: "round"
|
|
2485
|
-
})
|
|
2486
|
-
});
|
|
2487
|
-
}
|
|
2488
|
-
function RootIcon() {
|
|
2489
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
2490
|
-
width: "16",
|
|
2491
|
-
height: "16",
|
|
2492
|
-
viewBox: "0 0 24 24",
|
|
2493
|
-
fill: "none",
|
|
2494
|
-
"aria-hidden": "true",
|
|
2495
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2496
|
-
d: "M12 3 4.5 7.2v9.6L12 21l7.5-4.2V7.2L12 3Z",
|
|
2497
|
-
stroke: "currentColor",
|
|
2498
|
-
strokeWidth: "1.7"
|
|
2499
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
2500
|
-
cx: "12",
|
|
2501
|
-
cy: "12",
|
|
2502
|
-
r: "2.3",
|
|
2503
|
-
fill: "currentColor"
|
|
2504
|
-
})]
|
|
2505
|
-
});
|
|
2506
|
-
}
|
|
2507
|
-
//#endregion
|
|
2508
|
-
//#region src/client/sessionNavigation.ts
|
|
2509
|
-
const DEFAULT_SELECTION_TIMEOUT_MS = 2e3;
|
|
2510
|
-
function selected(sessions, id) {
|
|
2511
|
-
const snapshot = sessions.list.getSnapshot();
|
|
2512
|
-
if ("current" in snapshot) return snapshot.current === id;
|
|
2513
|
-
return ((snapshot.byId?.[id])?.retainedBy?.mainView ?? 0) > 0;
|
|
2514
|
-
}
|
|
2515
|
-
async function refreshInvocationCatalog(sessions, parent) {
|
|
2516
|
-
if (typeof sessions.refreshSubagents === "function") await sessions.refreshSubagents(parent);
|
|
2517
|
-
}
|
|
2518
|
-
/**
|
|
2519
|
-
* Select a persisted invocation session and confirm that DSH actually staged it.
|
|
2520
|
-
* Returns false only when neither the ordinary session list nor a refreshed
|
|
2521
|
-
* direct-parent catalog can address the target.
|
|
2522
|
-
*/
|
|
2523
|
-
async function openInvocationSession(sessions, rawSessionId, rawParentSessionId, timeoutMs = DEFAULT_SELECTION_TIMEOUT_MS, uiWorkspace) {
|
|
2524
|
-
const sessionId = rawSessionId;
|
|
2525
|
-
if (selected(sessions, sessionId)) return true;
|
|
2526
|
-
if (sessions.list.getSnapshot().ids.includes(sessionId)) {
|
|
2527
|
-
await selectAndConfirm(sessions, sessionId, () => {
|
|
2528
|
-
if (uiWorkspace) uiWorkspace.openSession(sessionId);
|
|
2529
|
-
else if (sessions.open) sessions.open(sessionId);
|
|
2530
|
-
else throw new Error("DSH exposes no session navigation API");
|
|
2531
|
-
}, timeoutMs);
|
|
2532
|
-
return true;
|
|
2533
|
-
}
|
|
2534
|
-
let address = sessions.subagentAddress?.(sessionId);
|
|
2535
|
-
if (address === void 0 && rawParentSessionId !== void 0) {
|
|
2536
|
-
await refreshInvocationCatalog(sessions, rawParentSessionId);
|
|
2537
|
-
address = sessions.subagentAddress?.(sessionId);
|
|
2538
|
-
if (!address && uiWorkspace) address = {
|
|
2539
|
-
parentSessionId: rawParentSessionId,
|
|
2540
|
-
childSessionId: sessionId,
|
|
2541
|
-
mode: "continuable"
|
|
2542
|
-
};
|
|
2543
|
-
}
|
|
2544
|
-
if (address === void 0) return false;
|
|
2545
|
-
const target = address;
|
|
2546
|
-
await selectAndConfirm(sessions, sessionId, () => {
|
|
2547
|
-
if (uiWorkspace) uiWorkspace.openSession(target);
|
|
2548
|
-
else if (sessions.openSubagent) sessions.openSubagent(target);
|
|
2549
|
-
else throw new Error("DSH exposes no subagent navigation API");
|
|
2550
|
-
}, timeoutMs);
|
|
2551
|
-
return true;
|
|
2552
|
-
}
|
|
2553
|
-
async function selectAndConfirm(sessions, sessionId, select, timeoutMs) {
|
|
2554
|
-
await new Promise((resolve, reject) => {
|
|
2555
|
-
let settled = false;
|
|
2556
|
-
let unsubscribe = () => void 0;
|
|
2557
|
-
const finish = (error) => {
|
|
2558
|
-
if (settled) return;
|
|
2559
|
-
settled = true;
|
|
2560
|
-
clearTimeout(timer);
|
|
2561
|
-
unsubscribe();
|
|
2562
|
-
if (error === void 0) resolve();
|
|
2563
|
-
else reject(error);
|
|
2564
|
-
};
|
|
2565
|
-
const confirm = () => {
|
|
2566
|
-
if (selected(sessions, sessionId)) finish();
|
|
2567
|
-
};
|
|
2568
|
-
const timer = setTimeout(() => {
|
|
2569
|
-
finish(/* @__PURE__ */ new Error(`DSH did not select session ${sessionId} within ${timeoutMs} ms`));
|
|
2570
|
-
}, timeoutMs);
|
|
2571
|
-
unsubscribe = sessions.list.subscribe(confirm);
|
|
2572
|
-
try {
|
|
2573
|
-
select();
|
|
2574
|
-
confirm();
|
|
2575
|
-
} catch (cause) {
|
|
2576
|
-
finish(cause instanceof Error ? cause : new Error(String(cause)));
|
|
2577
|
-
}
|
|
2578
|
-
});
|
|
2579
|
-
}
|
|
2580
|
-
//#endregion
|
|
2581
|
-
//#region src/client/styles.ts
|
|
2582
|
-
/** Scoped styles for the frame overlay; installed and removed with the client plugin fiber. */
|
|
2583
|
-
const DOG_DEBUG_STYLE_ID = "@dsh-external/dsh-dog/debugger";
|
|
2584
|
-
const DOG_DEBUG_CSS = String.raw`
|
|
2585
|
-
.dog-overlay-root,
|
|
2586
|
-
.dog-overlay-root * { box-sizing: border-box; }
|
|
2587
|
-
.dog-overlay-root { pointer-events: none; font-family: inherit; }
|
|
2588
|
-
.dog-dock {
|
|
2589
|
-
pointer-events: auto; position: fixed; top: 14px; right: 16px; bottom: 14px; z-index: 380;
|
|
2590
|
-
width: min(354px, calc(100vw - 24px)); display: flex; flex-direction: column;
|
|
2591
|
-
color: var(--dsw-alias-label-primary); background: color-mix(in srgb, var(--dsw-alias-bg-base) 92%, #7065e9 8%);
|
|
2592
|
-
border: 1px solid color-mix(in srgb, #7165e9 35%, var(--dsw-alias-border-l1)); border-radius: 16px;
|
|
2593
|
-
box-shadow: 0 16px 48px rgba(12, 16, 29, .22); backdrop-filter: blur(18px) saturate(1.08); overflow: hidden;
|
|
2594
|
-
}
|
|
2595
|
-
.dog-overlay-root[data-dog-dock-layout=hidden] .dog-dock { display: none; }
|
|
2596
|
-
.dog-overlay-root[data-dog-dock-layout=floating] .dog-dock { top: 70px; bottom: auto; max-height: min(346px, calc(100dvh - 84px)); }
|
|
2597
|
-
.dog-overlay-root[data-dog-dock-layout=collapsed] .dog-dock { top: 50%; right: 10px; bottom: auto; width: 46px; max-height: none; transform: translateY(-50%); border-radius: 14px; }
|
|
2598
|
-
.dog-dock-rail { width: 100%; min-height: 112px; border: 0; padding: 9px 4px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px; color: var(--dsw-alias-label-secondary); background: transparent; cursor: pointer; font: inherit; }
|
|
2599
|
-
.dog-dock-rail:hover { color: var(--dsw-alias-label-primary); background: color-mix(in srgb, #7165e9 9%, transparent); }
|
|
2600
|
-
.dog-dock-rail-mark { width: 28px; height: 28px; border-radius: 9px; display: grid; place-items: center; color: #fff; background: linear-gradient(145deg, #8174ff, #4b41ba); box-shadow: 0 5px 13px rgba(92, 78, 203, .22); }
|
|
2601
|
-
.dog-dock-rail strong { font-size: 10px; line-height: 14px; letter-spacing: .035em; }
|
|
2602
|
-
.dog-dock[data-collapsed=false] { display: grid; grid-template-columns: 32px minmax(0, 1fr); }
|
|
2603
|
-
.dog-dock-collapse-slot { min-height: 0; display: flex; align-items: center; justify-content: center; border-right: 1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 72%, transparent); background: color-mix(in srgb, #7165e9 4%, transparent); }
|
|
2604
|
-
.dog-dock-collapse-handle { width: 24px; height: 64px; border: 1px solid color-mix(in srgb, #7165e9 28%, var(--dsw-alias-border-l2)); border-radius: 8px; display: grid; place-items: center; color: var(--dsw-alias-label-secondary); background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 92%, #7165e9 8%); cursor: pointer; }
|
|
2605
|
-
.dog-dock-collapse-handle:hover { color: var(--dsw-alias-label-primary); border-color: color-mix(in srgb, #7165e9 48%, var(--dsw-alias-border-l2)); background: color-mix(in srgb, #7165e9 13%, var(--dsw-alias-bg-base)); }
|
|
2606
|
-
.dog-dock-content { min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
|
|
2607
|
-
.dog-dock-header { min-height: 50px; padding: 7px 8px 7px 10px; display: flex; align-items: center; gap: 9px; border-bottom: 1px solid var(--dsw-alias-border-l2); }
|
|
2608
|
-
.dog-dock-mark { width: 30px; height: 30px; flex: none; border-radius: 10px; display: grid; place-items: center; color: #fff; background: linear-gradient(145deg, #8174ff, #4b41ba); box-shadow: 0 6px 16px rgba(92, 78, 203, .23); }
|
|
2609
|
-
.dog-dock-heading { min-width: 0; flex: 1; display: flex; flex-direction: column; }
|
|
2610
|
-
.dog-dock-heading h2 { margin: 0; font-size: 12px; line-height: 17px; font-weight: 680; letter-spacing: -.01em; }
|
|
2611
|
-
.dog-dock-heading span { color: var(--dsw-alias-label-tertiary); font-size: 9.5px; line-height: 14px; }
|
|
2612
|
-
.dog-dock-error { padding: 4px 10px; color: #c94a45; background: color-mix(in srgb, #d5534d 7%, transparent); font-size: 8.5px; line-height: 12px; }
|
|
2613
|
-
.dog-dock-list { min-height: 0; flex: 1; margin: 0; padding: 7px; list-style: none; display: flex; flex-direction: column; gap: 5px; overflow: auto; }
|
|
2614
|
-
.dog-dock-list li { min-width: 0; }
|
|
2615
|
-
.dog-dock-card { width: 100%; min-width: 0; border: 1px solid var(--dsw-alias-border-l2); border-radius: 11px; padding: 8px 9px; display: block; color: inherit; background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 92%, #7165e9 3%); cursor: pointer; text-align: left; font: inherit; transition: border-color 120ms ease, background 120ms ease, transform 120ms ease; }
|
|
2616
|
-
.dog-dock-card:hover { transform: translateY(-1px); border-color: color-mix(in srgb, #7165e9 42%, var(--dsw-alias-border-l2)); background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 88%, #7165e9 7%); }
|
|
2617
|
-
.dog-dock-card:has(.dog-state-failure), .dog-dock-card:has(.dog-state-needs_replan), .dog-dock-card:has(.dog-state-needs_human) { border-color: color-mix(in srgb, #d18135 34%, var(--dsw-alias-border-l2)); }
|
|
2618
|
-
.dog-dock-card-head { min-width: 0; display: flex; align-items: flex-start; gap: 7px; }
|
|
2619
|
-
.dog-dock-title-wrap { min-width: 0; flex: 1; display: flex; flex-direction: column; }
|
|
2620
|
-
.dog-dock-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 11px; line-height: 16px; font-weight: 630; }
|
|
2621
|
-
.dog-dock-id { margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--dsw-alias-label-tertiary); font: 8px/12px ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
2622
|
-
.dog-dock-progress { height: 3px; margin-top: 7px; display: block; border-radius: 999px; background: color-mix(in srgb, var(--dsw-alias-label-tertiary) 16%, transparent); overflow: hidden; }
|
|
2623
|
-
.dog-dock-progress > span { display: block; height: 100%; border-radius: inherit; background: #7165e9; transition: width 180ms ease; }
|
|
2624
|
-
.dog-dock-metrics { min-width: 0; margin-top: 5px; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; color: var(--dsw-alias-label-tertiary); font-size: 8px; line-height: 12px; }
|
|
2625
|
-
.dog-dock-metrics > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
2626
|
-
.dog-dock-metrics strong { color: var(--dsw-alias-label-secondary); font-weight: 650; }
|
|
2627
|
-
.dog-dock-empty { padding: 17px 14px; display: flex; flex-direction: column; align-items: center; gap: 3px; color: var(--dsw-alias-label-tertiary); text-align: center; font-size: 9px; line-height: 14px; }
|
|
2628
|
-
.dog-dock-empty strong { margin-top: 3px; color: var(--dsw-alias-label-secondary); font-size: 10px; }
|
|
2629
|
-
.dog-dock-empty-icon { width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; color: #7165e9; background: color-mix(in srgb, #7165e9 11%, transparent); }
|
|
2630
|
-
.dog-dock-footer { padding: 6px 10px 7px; border-top: 1px solid var(--dsw-alias-border-l2); color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary)); font-size: 8.5px; line-height: 12px; text-align: center; }
|
|
2631
|
-
.dog-dock-card:focus-visible, .dog-dock-rail:focus-visible, .dog-dock-collapse-handle:focus-visible, .dog-icon-button:focus-visible, .dog-list-button:focus-visible, .dog-node:focus-visible, .dog-agent-row:focus-visible,
|
|
2632
|
-
.dog-segment-button:focus-visible, .dog-zoom-button:focus-visible, .dog-runtime-session-button:focus-visible { outline: 2px solid #776cf1; outline-offset: 2px; }
|
|
2633
|
-
.dog-backdrop { pointer-events: auto; position: fixed; inset: 0; z-index: 400; display: block; background: var(--dsw-alias-bg-base); animation: dog-fade-in 120ms ease-out; }
|
|
2634
|
-
.dog-dialog {
|
|
2635
|
-
width: 100vw; height: 100dvh; min-height: 0; display: grid; grid-template-rows: 68px minmax(0, 1fr);
|
|
2636
|
-
color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-base); overflow: hidden; animation: dog-dialog-in 160ms cubic-bezier(.2,.8,.2,1);
|
|
2637
|
-
}
|
|
2638
|
-
.dog-header { min-width: 0; padding: 0 18px 0 20px; display: flex; align-items: center; gap: 14px; border-bottom: 1px solid var(--dsw-alias-border-l2); background: color-mix(in srgb, var(--dsw-alias-bg-base) 94%, #7065e9 6%); }
|
|
2639
|
-
.dog-brand { min-width: 0; display: flex; align-items: center; gap: 11px; }
|
|
2640
|
-
.dog-brand-mark { width: 34px; height: 34px; border-radius: 11px; display: grid; place-items: center; color: #fff; background: linear-gradient(145deg, #8174ff, #4b41ba); box-shadow: 0 7px 18px rgba(92, 78, 203, .24); }
|
|
2641
|
-
.dog-brand-copy { min-width: 0; }
|
|
2642
|
-
.dog-brand-title { margin: 0; font-size: 15px; line-height: 21px; font-weight: 680; letter-spacing: -.01em; }
|
|
2643
|
-
.dog-brand-subtitle { margin: 1px 0 0; color: var(--dsw-alias-label-tertiary); font-size: 11px; line-height: 16px; }
|
|
2644
|
-
.dog-header-divider { width: 1px; height: 28px; margin: 0 2px; background: var(--dsw-alias-border-l2); }
|
|
2645
|
-
.dog-context { min-width: 0; display: flex; flex: 1; align-items: center; gap: 9px; }
|
|
2646
|
-
.dog-context-title { min-width: 0; max-width: 420px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 13px; font-weight: 560; }
|
|
2647
|
-
.dog-revision-chip, .dog-status-chip, .dog-mini-chip { border-radius: 999px; white-space: nowrap; display: inline-flex; align-items: center; gap: 5px; }
|
|
2648
|
-
.dog-revision-chip { height: 24px; padding: 0 8px; color: #655acb; background: color-mix(in srgb, #7165e9 13%, transparent); font-size: 10px; font-weight: 650; letter-spacing: .045em; text-transform: uppercase; }
|
|
2649
|
-
.dog-header-actions { flex: none; display: flex; align-items: center; gap: 7px; }
|
|
2650
|
-
.dog-sync-copy { margin-right: 3px; color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary)); font-size: 10px; white-space: nowrap; }
|
|
2651
|
-
.dog-icon-button, .dog-zoom-button { border: 0; color: var(--dsw-alias-label-secondary); background: transparent; cursor: pointer; font: inherit; display: inline-grid; place-items: center; }
|
|
2652
|
-
.dog-icon-button { width: 34px; height: 34px; border-radius: 10px; }
|
|
2653
|
-
.dog-icon-button:hover, .dog-zoom-button:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-interactive-bg-hover); }
|
|
2654
|
-
.dog-icon-button[aria-busy=true] svg { animation: dog-spin .8s linear infinite; }
|
|
2655
|
-
.dog-workspace { position: relative; min-width: 0; min-height: 0; display: grid; grid-template-columns: 246px minmax(0, 1fr) 324px; }
|
|
2656
|
-
.dog-sidebar, .dog-inspector { min-width: 0; min-height: 0; background: color-mix(in srgb, var(--dsw-specific-sidebar-fill, var(--dsw-alias-bg-base)) 82%, var(--dsw-alias-bg-base) 18%); overflow: auto; }
|
|
2657
|
-
.dog-sidebar { border-right: 1px solid var(--dsw-alias-border-l2); padding: 17px 12px 18px; }
|
|
2658
|
-
.dog-inspector { border-left: 1px solid var(--dsw-alias-border-l2); padding: 18px 16px 28px; }
|
|
2659
|
-
.dog-section-label { margin: 0 7px 9px; color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary)); font-size: 10px; line-height: 16px; font-weight: 700; letter-spacing: .095em; text-transform: uppercase; }
|
|
2660
|
-
.dog-graph-list, .dog-run-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
|
|
2661
|
-
.dog-sidebar-divider { height: 1px; margin: 17px 7px; background: var(--dsw-alias-border-l2); }
|
|
2662
|
-
.dog-list-button { width: 100%; border: 1px solid transparent; border-radius: 11px; padding: 9px 9px 8px; color: inherit; background: transparent; cursor: pointer; text-align: left; font: inherit; transition: background 120ms ease, border-color 120ms ease; }
|
|
2663
|
-
.dog-list-button:hover { background: var(--dsw-alias-interactive-bg-hover); }
|
|
2664
|
-
.dog-list-button[data-selected=true] { border-color: color-mix(in srgb, #7165e9 30%, var(--dsw-alias-border-l2)); background: color-mix(in srgb, #7165e9 10%, var(--dsw-alias-bg-base)); }
|
|
2665
|
-
.dog-list-row { min-width: 0; display: flex; align-items: center; gap: 8px; }
|
|
2666
|
-
.dog-list-title { min-width: 0; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 12px; line-height: 18px; font-weight: 590; }
|
|
2667
|
-
.dog-list-meta { min-width: 0; margin-top: 4px; padding-left: 16px; display: flex; align-items: center; gap: 6px; overflow: hidden; white-space: nowrap; color: var(--dsw-alias-label-tertiary); font-size: 10px; line-height: 15px; }
|
|
2668
|
-
.dog-list-meta > :last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
2669
|
-
.dog-list-current { color: #6e63dd; font-weight: 650; }
|
|
2670
|
-
.dog-state-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: #8a929c; box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 12%, transparent); }
|
|
2671
|
-
.dog-empty-small { margin: 0 7px; color: var(--dsw-alias-label-tertiary); font-size: 11px; line-height: 18px; }
|
|
2672
|
-
.dog-main { min-width: 0; min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); background: var(--dsw-alias-bg-base); }
|
|
2673
|
-
.dog-summary { min-width: 0; padding: 14px 18px 13px; display: grid; grid-template-columns: minmax(190px, 1fr) repeat(4, minmax(82px, 116px)); gap: 10px; border-bottom: 1px solid var(--dsw-alias-border-l2); }
|
|
2674
|
-
.dog-summary-primary, .dog-metric { min-width: 0; min-height: 55px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 88%, #7065e9 3%); }
|
|
2675
|
-
.dog-summary-primary { padding: 9px 11px; display: flex; align-items: center; gap: 11px; }
|
|
2676
|
-
.dog-root-orb { width: 34px; height: 34px; flex: none; border-radius: 50%; display: grid; place-items: center; color: white; }
|
|
2677
|
-
.dog-summary-copy { min-width: 0; }
|
|
2678
|
-
.dog-summary-kicker, .dog-metric-label { color: var(--dsw-alias-label-tertiary); font-size: 9px; line-height: 14px; font-weight: 680; letter-spacing: .08em; text-transform: uppercase; }
|
|
2679
|
-
.dog-summary-value { margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 12px; line-height: 18px; font-weight: 610; }
|
|
2680
|
-
.dog-metric { padding: 8px 10px; }
|
|
2681
|
-
.dog-metric-value { margin-top: 1px; font-size: 17px; line-height: 23px; font-weight: 680; letter-spacing: -.025em; }
|
|
2682
|
-
.dog-canvas-shell { min-width: 0; min-height: 0; display: grid; grid-template-rows: 40px minmax(0, 1fr); }
|
|
2683
|
-
.dog-canvas-toolbar { padding: 0 15px 0 18px; display: flex; align-items: center; gap: 14px; border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 70%, transparent); }
|
|
2684
|
-
.dog-legend { display: flex; align-items: center; gap: 12px; color: var(--dsw-alias-label-tertiary); font-size: 10px; }
|
|
2685
|
-
.dog-legend-item { display: inline-flex; align-items: center; gap: 5px; }
|
|
2686
|
-
.dog-legend-line { width: 21px; height: 0; border-top: 1.5px solid #857ce2; }
|
|
2687
|
-
.dog-legend-line[data-kind=depends] { border-top-style: dashed; border-color: #c07a39; }
|
|
2688
|
-
.dog-canvas-spacer { flex: 1; }
|
|
2689
|
-
.dog-zoom { height: 28px; padding: 0 3px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 9px; display: flex; align-items: center; }
|
|
2690
|
-
.dog-zoom-button { width: 24px; height: 22px; border-radius: 6px; font-size: 15px; }
|
|
2691
|
-
.dog-zoom-value { width: 39px; text-align: center; color: var(--dsw-alias-label-tertiary); font-size: 10px; }
|
|
2692
|
-
.dog-canvas-scroll { min-width: 0; min-height: 0; position: relative; overflow: auto; background-color: color-mix(in srgb, var(--dsw-alias-bg-base) 96%, #7065e9 4%); background-image: radial-gradient(color-mix(in srgb, var(--dsw-alias-label-tertiary) 20%, transparent) .7px, transparent .7px); background-size: 20px 20px; }
|
|
2693
|
-
.dog-canvas-stage-wrap { position: relative; margin: 0 auto; }
|
|
2694
|
-
.dog-canvas-stage { position: absolute; top: 0; left: 0; transform-origin: top left; }
|
|
2695
|
-
.dog-edges { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
|
|
2696
|
-
.dog-edge { fill: none; stroke-width: 1.5; }
|
|
2697
|
-
.dog-edge[data-kind=contains] { stroke: #857ce2; }
|
|
2698
|
-
.dog-edge[data-kind=dependsOn] { stroke: #c07a39; stroke-width: 1.35; stroke-dasharray: 6 5; }
|
|
2699
|
-
.dog-edge[data-muted=true] { opacity: .22; }
|
|
2700
|
-
.dog-edge[data-highlighted=true] { stroke-width: 2.4; filter: drop-shadow(0 0 3px color-mix(in srgb, currentColor 45%, transparent)); }
|
|
2701
|
-
.dog-node { position: absolute; border: 1px solid var(--dsw-alias-border-l2); border-radius: 14px; padding: 10px 11px 9px; display: flex; flex-direction: column; color: var(--dsw-alias-label-primary); background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 94%, #7165e9 2%); box-shadow: 0 4px 14px rgba(14, 18, 29, .05); cursor: pointer; text-align: left; font: inherit; transition: border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease; }
|
|
2702
|
-
.dog-node:hover { transform: translateY(-2px); border-color: color-mix(in srgb, #7165e9 45%, var(--dsw-alias-border-l2)); box-shadow: 0 8px 22px rgba(28, 31, 52, .11); }
|
|
2703
|
-
.dog-node[data-selected=true] { border-color: #7165e9; box-shadow: 0 0 0 3px color-mix(in srgb, #7165e9 14%, transparent), 0 9px 24px rgba(28,31,52,.12); }
|
|
2704
|
-
.dog-node[data-root=true] { background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 88%, #7165e9 8%); }
|
|
2705
|
-
.dog-node-top { display: flex; align-items: center; gap: 7px; }
|
|
2706
|
-
.dog-node-kind { flex: 1; color: var(--dsw-alias-label-tertiary); font-size: 9px; line-height: 13px; font-weight: 700; letter-spacing: .085em; text-transform: uppercase; }
|
|
2707
|
-
.dog-node-root { color: #6c61d6; }
|
|
2708
|
-
.dog-node-title { margin-top: 8px; min-height: 34px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font-size: 12px; line-height: 17px; font-weight: 620; }
|
|
2709
|
-
.dog-node-foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 7px; }
|
|
2710
|
-
.dog-node-id { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary)); font: 9px/13px ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
2711
|
-
.dog-status-chip { height: 19px; padding: 0 6px; color: var(--dog-state-color); background: color-mix(in srgb, var(--dog-state-color) 13%, transparent); font-size: 9px; line-height: 14px; font-weight: 700; letter-spacing: .035em; text-transform: uppercase; }
|
|
2712
|
-
.dog-status-chip:before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--dog-state-color); }
|
|
2713
|
-
.dog-node[data-agents-expanded=true] { border-color: color-mix(in srgb, #7165e9 62%, var(--dsw-alias-border-l2)); }
|
|
2714
|
-
.dog-node-agents { flex: none; display: inline-flex; align-items: center; gap: 3px; color: #6b60d4; font-size: 9px; line-height: 13px; font-weight: 650; }
|
|
2715
|
-
.dog-agent-flyout { position: absolute; z-index: 8; min-height: 116px; display: flex; flex-direction: column; color: var(--dsw-alias-label-primary); background: color-mix(in srgb, var(--dsw-alias-bg-base) 96%, #7165e9 4%); border: 1px solid color-mix(in srgb, #7165e9 35%, var(--dsw-alias-border-l2)); border-radius: 13px; box-shadow: 0 14px 34px rgba(12, 16, 29, .22); overflow: hidden; }
|
|
2716
|
-
.dog-agent-flyout-head { min-height: 35px; padding: 6px 7px 6px 9px; display: flex; align-items: center; gap: 6px; border-bottom: 1px solid var(--dsw-alias-border-l2); }
|
|
2717
|
-
.dog-agent-flyout-head > span { min-width: 0; flex: 1; display: inline-flex; align-items: center; gap: 5px; font-size: 9.5px; line-height: 14px; font-weight: 680; }
|
|
2718
|
-
.dog-agent-flyout-head button { width: 25px; height: 25px; border: 0; border-radius: 7px; display: grid; place-items: center; color: var(--dsw-alias-label-tertiary); background: transparent; cursor: pointer; }
|
|
2719
|
-
.dog-agent-flyout-head button:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-interactive-bg-hover); }
|
|
2720
|
-
.dog-agent-list { min-height: 0; margin: 0; padding: 5px; list-style: none; overflow: auto; }
|
|
2721
|
-
.dog-agent-list li + li { margin-top: 3px; }
|
|
2722
|
-
.dog-agent-row { width: 100%; min-width: 0; border: 0; border-radius: 8px; padding: 7px 6px; display: grid; grid-template-columns: 8px minmax(0, 1fr) auto; align-items: center; gap: 7px; color: inherit; background: transparent; cursor: pointer; text-align: left; font: inherit; }
|
|
2723
|
-
.dog-agent-row:hover { background: var(--dsw-alias-interactive-bg-hover); }
|
|
2724
|
-
.dog-agent-row:disabled { cursor: wait; opacity: .66; }
|
|
2725
|
-
.dog-agent-state { width: 7px; height: 7px; border-radius: 50%; background: var(--dog-state-color); box-shadow: 0 0 0 3px color-mix(in srgb, var(--dog-state-color) 12%, transparent); }
|
|
2726
|
-
.dog-agent-copy, .dog-agent-metrics { min-width: 0; display: flex; flex-direction: column; }
|
|
2727
|
-
.dog-agent-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 9.5px; line-height: 14px; font-weight: 630; }
|
|
2728
|
-
.dog-agent-meta { color: var(--dsw-alias-label-tertiary); font-size: 8px; line-height: 12px; }
|
|
2729
|
-
.dog-agent-metrics { align-items: flex-end; color: var(--dsw-alias-label-tertiary); font: 8px/12px ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
|
|
2730
|
-
.dog-agent-empty { margin: auto 0; padding: 13px 10px; color: var(--dsw-alias-label-tertiary); text-align: center; font-size: 9px; line-height: 14px; }
|
|
2731
|
-
.dog-agent-hint { padding: 5px 8px 6px; border-top: 1px solid var(--dsw-alias-border-l2); color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary)); text-align: center; font-size: 7.5px; line-height: 11px; }
|
|
2732
|
-
.dog-agent-error { padding: 5px 8px; color: #c94a45; background: color-mix(in srgb, #d5534d 7%, transparent); font-size: 8px; line-height: 12px; overflow-wrap: anywhere; }
|
|
2733
|
-
.dog-inspector-head { display: flex; align-items: flex-start; gap: 10px; }
|
|
2734
|
-
.dog-inspector-title-wrap { min-width: 0; flex: 1; }
|
|
2735
|
-
.dog-inspector-eyebrow { color: var(--dsw-alias-label-tertiary); font-size: 9px; line-height: 14px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; }
|
|
2736
|
-
.dog-inspector-title { margin: 3px 0 0; overflow-wrap: anywhere; font-size: 15px; line-height: 21px; font-weight: 660; }
|
|
2737
|
-
.dog-inspector-chips { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
|
|
2738
|
-
.dog-mini-chip { height: 21px; padding: 0 7px; color: var(--dsw-alias-label-secondary); background: var(--dsw-alias-interactive-bg-hover); font-size: 9px; font-weight: 650; text-transform: uppercase; letter-spacing: .045em; }
|
|
2739
|
-
.dog-inspector-section { margin-top: 18px; }
|
|
2740
|
-
.dog-inspector-section-title { margin: 0 0 8px; color: var(--dsw-alias-label-tertiary); font-size: 9px; line-height: 14px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; }
|
|
2741
|
-
.dog-reason { border: 1px solid color-mix(in srgb, var(--dog-state-color) 33%, var(--dsw-alias-border-l2)); border-radius: 10px; padding: 9px 10px; color: var(--dsw-alias-label-secondary); background: color-mix(in srgb, var(--dog-state-color) 7%, transparent); font-size: 11px; line-height: 17px; overflow-wrap: anywhere; }
|
|
2742
|
-
.dog-definition { margin: 0; display: grid; grid-template-columns: minmax(82px, .7fr) minmax(0, 1.3fr); gap: 7px 9px; font-size: 10px; line-height: 16px; }
|
|
2743
|
-
.dog-definition dt { color: var(--dsw-alias-label-tertiary); }
|
|
2744
|
-
.dog-definition dd { min-width: 0; margin: 0; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; }
|
|
2745
|
-
.dog-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 9.5px; }
|
|
2746
|
-
.dog-evidence { border: 1px solid var(--dsw-alias-border-l2); border-radius: 11px; overflow: hidden; }
|
|
2747
|
-
.dog-evidence-head { min-height: 35px; padding: 7px 9px; display: flex; align-items: center; gap: 8px; background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 90%, #7165e9 4%); border-bottom: 1px solid var(--dsw-alias-border-l2); }
|
|
2748
|
-
.dog-evidence-name { min-width: 0; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font: 10px/16px ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
2749
|
-
.dog-evidence-body { padding: 8px 9px 9px; }
|
|
2750
|
-
.dog-observation { margin: 0; display: grid; gap: 5px; }
|
|
2751
|
-
.dog-observation-row { display: grid; grid-template-columns: minmax(76px, .75fr) minmax(0, 1.25fr); gap: 8px; font-size: 10px; line-height: 15px; }
|
|
2752
|
-
.dog-observation-key { color: var(--dsw-alias-label-tertiary); overflow-wrap: anywhere; }
|
|
2753
|
-
.dog-observation-value { color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
2754
|
-
.dog-relation-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
|
|
2755
|
-
.dog-relation { border-left: 2px solid #857ce2; padding-left: 8px; color: var(--dsw-alias-label-secondary); font-size: 10px; line-height: 15px; }
|
|
2756
|
-
.dog-relation[data-kind=dependsOn] { border-color: #c07a39; }
|
|
2757
|
-
.dog-relation strong { color: var(--dsw-alias-label-primary); font-weight: 600; }
|
|
2758
|
-
.dog-raw { border: 1px solid var(--dsw-alias-border-l2); border-radius: 10px; overflow: hidden; }
|
|
2759
|
-
.dog-raw summary { padding: 7px 9px; color: var(--dsw-alias-label-secondary); cursor: pointer; font-size: 10px; }
|
|
2760
|
-
.dog-raw pre { max-height: 240px; margin: 0; padding: 9px; border-top: 1px solid var(--dsw-alias-border-l2); color: var(--dsw-alias-label-tertiary); background: color-mix(in srgb, var(--dsw-alias-bg-base) 94%, #000 6%); white-space: pre-wrap; overflow: auto; font: 9px/15px ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
2761
|
-
.dog-runtime-heading { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
2762
|
-
.dog-runtime-heading .dog-inspector-section-title { margin-bottom: 8px; }
|
|
2763
|
-
.dog-runtime-live { display: inline-flex; align-items: center; gap: 5px; color: #3c7fe1; font-size: 9px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; }
|
|
2764
|
-
.dog-runtime-pulse { width: 6px; height: 6px; border-radius: 50%; background: #3c7fe1; box-shadow: 0 0 0 0 rgba(60,127,225,.35); animation: dog-runtime-pulse 1.5s ease-out infinite; }
|
|
2765
|
-
.dog-runtime-card { min-width: 0; border: 1px solid color-mix(in srgb, var(--dog-state-color) 25%, var(--dsw-alias-border-l2)); border-radius: 11px; padding: 9px 10px; display: flex; align-items: center; gap: 9px; background: color-mix(in srgb, var(--dog-state-color) 6%, var(--dsw-alias-bg-base)); }
|
|
2766
|
-
.dog-runtime-orb { width: 10px; height: 10px; flex: none; border-radius: 50%; background: var(--dog-state-color); box-shadow: 0 0 0 4px color-mix(in srgb, var(--dog-state-color) 13%, transparent); }
|
|
2767
|
-
.dog-runtime-card-copy { min-width: 0; }
|
|
2768
|
-
.dog-runtime-activity { color: var(--dsw-alias-label-primary); overflow-wrap: anywhere; font-size: 11px; line-height: 16px; font-weight: 620; }
|
|
2769
|
-
.dog-runtime-meta { margin-top: 2px; color: var(--dsw-alias-label-tertiary); font-size: 9px; line-height: 14px; }
|
|
2770
|
-
.dog-runtime-warning { margin-top: 7px; border: 1px solid color-mix(in srgb, #d18135 28%, var(--dsw-alias-border-l2)); border-radius: 9px; padding: 7px 8px; color: #b66d28; background: color-mix(in srgb, #d18135 7%, transparent); overflow-wrap: anywhere; font-size: 9.5px; line-height: 15px; }
|
|
2771
|
-
.dog-runtime-error { margin-top: 8px; border-left: 3px solid var(--dog-state-color); border-radius: 8px; padding: 8px 9px; display: flex; flex-direction: column; gap: 3px; color: var(--dsw-alias-label-secondary); background: color-mix(in srgb, var(--dog-state-color) 8%, transparent); font-size: 9.5px; line-height: 15px; overflow-wrap: anywhere; }
|
|
2772
|
-
.dog-runtime-error strong { color: var(--dog-state-color); font-size: 9px; letter-spacing: .035em; text-transform: uppercase; }
|
|
2773
|
-
.dog-runtime-session { margin-top: 8px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 10px; padding: 8px 9px; background: color-mix(in srgb, var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base)) 92%, #7165e9 3%); }
|
|
2774
|
-
.dog-runtime-session-head { margin-bottom: 7px; display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--dsw-alias-label-secondary); font-size: 10px; font-weight: 620; }
|
|
2775
|
-
.dog-runtime-session-button { flex: none; border: 1px solid color-mix(in srgb, #7165e9 32%, var(--dsw-alias-border-l2)); border-radius: 7px; padding: 4px 7px; color: #655acb; background: color-mix(in srgb, #7165e9 8%, var(--dsw-alias-bg-base)); cursor: pointer; font: 600 9px/13px inherit; }
|
|
2776
|
-
.dog-runtime-session-button:hover { background: color-mix(in srgb, #7165e9 15%, var(--dsw-alias-bg-base)); }
|
|
2777
|
-
.dog-runtime-session-button:disabled { cursor: wait; opacity: .62; }
|
|
2778
|
-
.dog-runtime-session-error { margin-top: 7px; color: #c94a45; font-size: 9px; line-height: 14px; overflow-wrap: anywhere; }
|
|
2779
|
-
.dog-runtime-empty { margin: 8px 0 0; }
|
|
2780
|
-
.dog-runtime-timeline { margin: 10px 0 0; padding: 0; list-style: none; }
|
|
2781
|
-
.dog-runtime-event { --dog-runtime-line: color-mix(in srgb, var(--dog-state-color) 32%, var(--dsw-alias-border-l2)); position: relative; min-width: 0; padding: 0 0 12px 19px; }
|
|
2782
|
-
.dog-runtime-event:not(:last-child):before { content: ''; position: absolute; left: 4px; top: 10px; bottom: 0; width: 1px; background: var(--dog-runtime-line); }
|
|
2783
|
-
.dog-runtime-marker { position: absolute; left: 0; top: 4px; width: 9px; height: 9px; border: 2px solid var(--dsw-alias-bg-base); border-radius: 50%; background: var(--dog-state-color); box-shadow: 0 0 0 1px var(--dog-runtime-line); }
|
|
2784
|
-
.dog-runtime-event-copy { min-width: 0; }
|
|
2785
|
-
.dog-runtime-event-head { min-width: 0; display: flex; align-items: baseline; justify-content: space-between; gap: 7px; color: var(--dsw-alias-label-secondary); font-size: 9.5px; line-height: 14px; }
|
|
2786
|
-
.dog-runtime-event-head strong { min-width: 0; overflow-wrap: anywhere; font-weight: 620; }
|
|
2787
|
-
.dog-runtime-event-head time { flex: none; color: var(--dsw-alias-label-tertiary); font-size: 8.5px; }
|
|
2788
|
-
.dog-runtime-event-meta { margin-top: 1px; color: var(--dsw-alias-label-caption, var(--dsw-alias-label-tertiary)); font: 8px/12px ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
2789
|
-
.dog-runtime-event-detail { margin-top: 3px; color: var(--dsw-alias-label-tertiary); overflow-wrap: anywhere; font-size: 9px; line-height: 14px; }
|
|
2790
|
-
.dog-runtime-raw { margin-top: 4px; }
|
|
2791
|
-
.dog-empty { grid-column: 1 / -1; min-height: 320px; display: grid; place-items: center; padding: 40px; text-align: center; }
|
|
2792
|
-
.dog-empty-card { max-width: 380px; }
|
|
2793
|
-
.dog-empty-icon { width: 48px; height: 48px; margin: 0 auto 13px; border-radius: 16px; display: grid; place-items: center; color: #7165e9; background: color-mix(in srgb, #7165e9 12%, transparent); }
|
|
2794
|
-
.dog-empty-title { margin: 0; font-size: 15px; line-height: 22px; font-weight: 650; }
|
|
2795
|
-
.dog-empty-copy { margin: 6px 0 0; color: var(--dsw-alias-label-tertiary); font-size: 11px; line-height: 18px; }
|
|
2796
|
-
.dog-error-banner { margin: 12px 18px 0; border: 1px solid color-mix(in srgb, #d5534d 35%, var(--dsw-alias-border-l2)); border-radius: 10px; padding: 8px 10px; color: #c94a45; background: color-mix(in srgb, #d5534d 8%, transparent); font-size: 11px; line-height: 17px; }
|
|
2797
|
-
.dog-loading { opacity: .65; }
|
|
2798
|
-
.dog-state-success { --dog-state-color: #1c9a69; }
|
|
2799
|
-
.dog-state-failure { --dog-state-color: #d5534d; }
|
|
2800
|
-
.dog-state-needs_human { --dog-state-color: #d18135; }
|
|
2801
|
-
.dog-state-partial { --dog-state-color: #b88a22; }
|
|
2802
|
-
.dog-state-blocked, .dog-state-cancelled, .dog-state-invalidated { --dog-state-color: #828b97; }
|
|
2803
|
-
.dog-state-running { --dog-state-color: #3c7fe1; }
|
|
2804
|
-
.dog-state-pending, .dog-state-created { --dog-state-color: #8c859f; }
|
|
2805
|
-
.dog-state-partial_success { --dog-state-color: #b88a22; }
|
|
2806
|
-
.dog-state-infeasible, .dog-state-needs_replan { --dog-state-color: #d18135; }
|
|
2807
|
-
.dog-root-orb { background: var(--dog-state-color); box-shadow: 0 7px 18px color-mix(in srgb, var(--dog-state-color) 26%, transparent); }
|
|
2808
|
-
@keyframes dog-fade-in { from { opacity: 0; } }
|
|
2809
|
-
@keyframes dog-dialog-in { from { opacity: 0; transform: translateY(8px) scale(.992); } }
|
|
2810
|
-
@keyframes dog-runtime-pulse { 70%, 100% { box-shadow: 0 0 0 6px rgba(60,127,225,0); } }
|
|
2811
|
-
@keyframes dog-spin { to { transform: rotate(360deg); } }
|
|
2812
|
-
@media (max-width: 1180px) {
|
|
2813
|
-
.dog-workspace { grid-template-columns: 220px minmax(0, 1fr) 292px; }
|
|
2814
|
-
.dog-summary { grid-template-columns: minmax(170px, 1fr) repeat(4, minmax(76px, 92px)); gap: 7px; }
|
|
2815
|
-
}
|
|
2816
|
-
@media (min-width: 981px) and (max-width: 1080px) {
|
|
2817
|
-
.dog-workspace { grid-template-columns: 190px minmax(0, 1fr) 270px; }
|
|
2818
|
-
.dog-summary { grid-template-columns: minmax(160px, 1fr) repeat(3, minmax(72px, 84px)); }
|
|
2819
|
-
.dog-metric:last-child { display: none; }
|
|
2820
|
-
}
|
|
2821
|
-
@media (max-width: 980px) {
|
|
2822
|
-
.dog-dialog { width: 100%; height: 100dvh; min-height: 0; }
|
|
2823
|
-
.dog-workspace { grid-template-columns: 210px minmax(0, 1fr); }
|
|
2824
|
-
.dog-inspector { position: absolute; z-index: 3; top: 0; right: 0; bottom: 0; width: min(330px, 84%); box-shadow: -16px 0 36px rgba(7, 10, 18, .16); }
|
|
2825
|
-
.dog-summary { grid-template-columns: minmax(170px, 1fr) repeat(3, minmax(72px, 88px)); }
|
|
2826
|
-
.dog-metric:last-child { display: none; }
|
|
2827
|
-
}
|
|
2828
|
-
@media (max-width: 720px) {
|
|
2829
|
-
.dog-overlay-root[data-dog-dock-layout=floating] .dog-dock { top: 64px; right: 8px; bottom: auto; width: calc(100vw - 16px); max-height: min(286px, calc(100dvh - 72px)); }
|
|
2830
|
-
.dog-workspace { grid-template-columns: 1fr; }
|
|
2831
|
-
.dog-sidebar { display: none; }
|
|
2832
|
-
.dog-header-divider, .dog-brand-subtitle, .dog-sync-copy { display: none; }
|
|
2833
|
-
.dog-summary { grid-template-columns: minmax(145px, 1fr) repeat(2, minmax(66px, 76px)); padding-inline: 10px; }
|
|
2834
|
-
.dog-metric:nth-of-type(n+4) { display: none; }
|
|
2835
|
-
}
|
|
2836
|
-
@media (prefers-reduced-motion: reduce) {
|
|
2837
|
-
.dog-launcher, .dog-node, .dog-backdrop, .dog-dialog, .dog-runtime-pulse { animation: none; transition: none; }
|
|
2838
|
-
}
|
|
2839
|
-
`;
|
|
2840
|
-
//#endregion
|
|
2841
|
-
//#region src/client/sessionState.ts
|
|
2842
|
-
/** DSH 0.2 folds pending interactions into the unified session status source. */
|
|
2843
|
-
function debuggerSessionState(sessions, uiSession) {
|
|
2844
|
-
const status = uiSession.sessionStatus;
|
|
2845
|
-
const source = status ?? uiSession.pendingInteractions;
|
|
2846
|
-
if (!source || typeof source.getSnapshot !== "function" || typeof source.subscribe !== "function") throw new Error("DSH session UI exposes neither sessionStatus nor pendingInteractions");
|
|
2847
|
-
let lastSessions;
|
|
2848
|
-
let lastStatus;
|
|
2849
|
-
let combined;
|
|
2850
|
-
return {
|
|
2851
|
-
getSnapshot() {
|
|
2852
|
-
const next = sessions.getSnapshot();
|
|
2853
|
-
const pending = source.getSnapshot();
|
|
2854
|
-
if (next !== lastSessions || pending !== lastStatus) {
|
|
2855
|
-
lastSessions = next;
|
|
2856
|
-
lastStatus = pending;
|
|
2857
|
-
const interactions = status ? new Map([...status.getSnapshot()].flatMap(([id, value]) => value.pendingInteraction === void 0 ? [] : [[id, value.pendingInteraction]])) : pending;
|
|
2858
|
-
combined = {
|
|
2859
|
-
...next,
|
|
2860
|
-
pendingInteractions: interactions
|
|
2861
|
-
};
|
|
2862
|
-
}
|
|
2863
|
-
return combined;
|
|
2864
|
-
},
|
|
2865
|
-
subscribe(listener) {
|
|
2866
|
-
const stopSessions = sessions.subscribe(listener);
|
|
2867
|
-
try {
|
|
2868
|
-
const stopStatus = source.subscribe(listener);
|
|
2869
|
-
return () => {
|
|
2870
|
-
stopStatus();
|
|
2871
|
-
stopSessions();
|
|
2872
|
-
};
|
|
2873
|
-
} catch (error) {
|
|
2874
|
-
stopSessions();
|
|
2875
|
-
throw error;
|
|
2876
|
-
}
|
|
2877
|
-
}
|
|
2878
|
-
};
|
|
2879
|
-
}
|
|
2880
|
-
//#endregion
|
|
2881
|
-
//#region src/client/index.tsx
|
|
2882
|
-
/** The overlay uses the shared trusted RPC transport and canonical session navigator. */
|
|
2883
|
-
const inject = [
|
|
2884
|
-
"slots",
|
|
2885
|
-
"sessions",
|
|
2886
|
-
"connection",
|
|
2887
|
-
"uiSession",
|
|
2888
|
-
"uiWorkspace"
|
|
2889
|
-
];
|
|
2890
|
-
/** Register the debugger beside other frame-wide overlays without replacing shipped UI. */
|
|
2891
|
-
function apply(ctx) {
|
|
2892
|
-
try {
|
|
2893
|
-
ctx.effect(() => install(ctx), "openwrite-dog: client activation");
|
|
2894
|
-
} catch (error) {
|
|
2895
|
-
console.error("[OpenWrite/DoG] Debugger disabled: client activation failed", error);
|
|
2896
|
-
}
|
|
2897
|
-
}
|
|
2898
|
-
function* install(ctx) {
|
|
2899
|
-
const connection = ctx.get("connection");
|
|
2900
|
-
const sessions = ctx.get("sessions");
|
|
2901
|
-
const call = async (endpoint, payload, signal) => {
|
|
2902
|
-
const result = await connection.rpc.call(DOG_DEBUG_RPC_CHANNEL, endpoint, payload, signal);
|
|
2903
|
-
if (!result.ok) throw new Error(result.error.message);
|
|
2904
|
-
return result.value;
|
|
2905
|
-
};
|
|
2906
|
-
const openSession = (sessionId, parentSessionId) => openInvocationSession(sessions, sessionId, parentSessionId, void 0, typeof ctx.uiWorkspace.openSession === "function" ? ctx.uiWorkspace : void 0);
|
|
2907
|
-
const state = debuggerSessionState(sessions.list, ctx.uiSession);
|
|
2908
|
-
state.getSnapshot();
|
|
2909
|
-
const DogDebuggerHost = () => {
|
|
2910
|
-
const [request, setRequest] = (0, react.useState)(0);
|
|
2911
|
-
(0, react.useEffect)(() => {
|
|
2912
|
-
const show = () => setRequest((value) => value + 1);
|
|
2913
|
-
window.addEventListener("openwrite:dog-open", show);
|
|
2914
|
-
return () => window.removeEventListener("openwrite:dog-open", show);
|
|
2915
|
-
}, []);
|
|
2916
|
-
return request === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DogDebugger, {
|
|
2917
|
-
initialOpen: true,
|
|
2918
|
-
hideDock: true,
|
|
2919
|
-
readSnapshot: (signal) => call(DOG_DEBUG_SNAPSHOT_ENDPOINT, {}, signal),
|
|
2920
|
-
readGoalRuntime: (runId, goalId, signal) => call(DOG_RUNTIME_TRACE_ENDPOINT, {
|
|
2921
|
-
runId,
|
|
2922
|
-
goalId
|
|
2923
|
-
}, signal),
|
|
2924
|
-
openSession,
|
|
2925
|
-
getSessionState: state.getSnapshot,
|
|
2926
|
-
subscribeSessions: state.subscribe,
|
|
2927
|
-
refreshAgentCatalog: (parentSessionId) => refreshInvocationCatalog(sessions, parentSessionId)
|
|
2928
|
-
}, request);
|
|
2929
|
-
};
|
|
2930
|
-
yield ctx.effect(installStyles, "dog-debugger: styles");
|
|
2931
|
-
yield ctx.slots.inject("shell.overlay", () => {
|
|
2932
|
-
try {
|
|
2933
|
-
return ctx.slots.register({
|
|
2934
|
-
name: "shell.overlay",
|
|
2935
|
-
id: "openwrite.dog-debugger",
|
|
2936
|
-
order: 80
|
|
2937
|
-
}, DogDebuggerHost);
|
|
2938
|
-
} catch (error) {
|
|
2939
|
-
console.error("[OpenWrite/DoG] Debugger disabled: overlay registration failed", error);
|
|
2940
|
-
return () => {};
|
|
2941
|
-
}
|
|
2942
|
-
});
|
|
2943
|
-
}
|
|
2944
|
-
function installStyles() {
|
|
2945
|
-
if (document.querySelector(`style[data-plugin-css="@dsh-external/dsh-dog/debugger"]`) !== null) return () => void 0;
|
|
2946
|
-
const style = document.createElement("style");
|
|
2947
|
-
style.dataset.plugin = "@dsh-external/dsh-dog";
|
|
2948
|
-
style.dataset.pluginCss = DOG_DEBUG_STYLE_ID;
|
|
2949
|
-
style.textContent = DOG_DEBUG_CSS;
|
|
2950
|
-
document.head.appendChild(style);
|
|
2951
|
-
return () => style.remove();
|
|
2952
|
-
}
|
|
2953
|
-
//#endregion
|
|
2954
|
-
exports.apply = apply;
|
|
2955
|
-
exports.inject = inject;
|
|
2956
|
-
return module.exports;
|
|
2957
|
-
}
|
|
2958
|
-
});
|
|
2959
|
-
|
|
2960
|
-
//# sourceMappingURL=client.js.map
|