@nodetool-ai/execution 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/app-debug/app-spec.d.ts +94 -0
- package/dist/app-debug/app-spec.d.ts.map +1 -0
- package/dist/app-debug/app-spec.js +710 -0
- package/dist/app-debug/app-spec.js.map +1 -0
- package/dist/app-debug/application-target.d.ts +53 -0
- package/dist/app-debug/application-target.d.ts.map +1 -0
- package/dist/app-debug/application-target.js +126 -0
- package/dist/app-debug/application-target.js.map +1 -0
- package/dist/app-debug/bundle-target.d.ts +21 -0
- package/dist/app-debug/bundle-target.d.ts.map +1 -0
- package/dist/app-debug/bundle-target.js +51 -0
- package/dist/app-debug/bundle-target.js.map +1 -0
- package/dist/app-debug/graph-shape.d.ts +14 -0
- package/dist/app-debug/graph-shape.d.ts.map +1 -0
- package/dist/app-debug/graph-shape.js +23 -0
- package/dist/app-debug/graph-shape.js.map +1 -0
- package/dist/app-debug/index.d.ts +26 -0
- package/dist/app-debug/index.d.ts.map +1 -0
- package/dist/app-debug/index.js +19 -0
- package/dist/app-debug/index.js.map +1 -0
- package/dist/app-debug/markdown.d.ts +6 -0
- package/dist/app-debug/markdown.d.ts.map +1 -0
- package/dist/app-debug/markdown.js +133 -0
- package/dist/app-debug/markdown.js.map +1 -0
- package/dist/app-debug/runtime.d.ts +267 -0
- package/dist/app-debug/runtime.d.ts.map +1 -0
- package/dist/app-debug/runtime.js +633 -0
- package/dist/app-debug/runtime.js.map +1 -0
- package/dist/app-debug/script-operation.d.ts +58 -0
- package/dist/app-debug/script-operation.d.ts.map +1 -0
- package/dist/app-debug/script-operation.js +44 -0
- package/dist/app-debug/script-operation.js.map +1 -0
- package/dist/app-debug/simulate.d.ts +85 -0
- package/dist/app-debug/simulate.d.ts.map +1 -0
- package/dist/app-debug/simulate.js +991 -0
- package/dist/app-debug/simulate.js.map +1 -0
- package/dist/app-debug/summarize.d.ts +64 -0
- package/dist/app-debug/summarize.d.ts.map +1 -0
- package/dist/app-debug/summarize.js +65 -0
- package/dist/app-debug/summarize.js.map +1 -0
- package/dist/app-debug/types.d.ts +343 -0
- package/dist/app-debug/types.d.ts.map +1 -0
- package/dist/app-debug/types.js +2 -0
- package/dist/app-debug/types.js.map +1 -0
- package/dist/cost-ledger.d.ts +147 -0
- package/dist/cost-ledger.d.ts.map +1 -0
- package/dist/cost-ledger.js +288 -0
- package/dist/cost-ledger.js.map +1 -0
- package/dist/debug/collector.d.ts +28 -0
- package/dist/debug/collector.d.ts.map +1 -0
- package/dist/debug/collector.js +284 -0
- package/dist/debug/collector.js.map +1 -0
- package/dist/debug/index.d.ts +15 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js +16 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/debug/types.d.ts +179 -0
- package/dist/debug/types.d.ts.map +1 -0
- package/dist/debug/types.js +11 -0
- package/dist/debug/types.js.map +1 -0
- package/dist/debug/verdict.d.ts +27 -0
- package/dist/debug/verdict.d.ts.map +1 -0
- package/dist/debug/verdict.js +51 -0
- package/dist/debug/verdict.js.map +1 -0
- package/dist/executor-resolver.d.ts +13 -0
- package/dist/executor-resolver.d.ts.map +1 -0
- package/dist/executor-resolver.js +13 -0
- package/dist/executor-resolver.js.map +1 -0
- package/dist/fal-output-decoder.d.ts +36 -0
- package/dist/fal-output-decoder.d.ts.map +1 -0
- package/dist/fal-output-decoder.js +129 -0
- package/dist/fal-output-decoder.js.map +1 -0
- package/dist/generation-lifecycle.d.ts +54 -0
- package/dist/generation-lifecycle.d.ts.map +1 -0
- package/dist/generation-lifecycle.js +431 -0
- package/dist/generation-lifecycle.js.map +1 -0
- package/dist/generation-recovery-worker.d.ts +100 -0
- package/dist/generation-recovery-worker.d.ts.map +1 -0
- package/dist/generation-recovery-worker.js +995 -0
- package/dist/generation-recovery-worker.js.map +1 -0
- package/dist/generation-tracker.d.ts +83 -0
- package/dist/generation-tracker.d.ts.map +1 -0
- package/dist/generation-tracker.js +436 -0
- package/dist/generation-tracker.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/js-script-debug/index.d.ts +13 -0
- package/dist/js-script-debug/index.d.ts.map +1 -0
- package/dist/js-script-debug/index.js +12 -0
- package/dist/js-script-debug/index.js.map +1 -0
- package/dist/js-script-debug/markdown.d.ts +6 -0
- package/dist/js-script-debug/markdown.d.ts.map +1 -0
- package/dist/js-script-debug/markdown.js +62 -0
- package/dist/js-script-debug/markdown.js.map +1 -0
- package/dist/js-script-debug/outputs.d.ts +20 -0
- package/dist/js-script-debug/outputs.d.ts.map +1 -0
- package/dist/js-script-debug/outputs.js +30 -0
- package/dist/js-script-debug/outputs.js.map +1 -0
- package/dist/js-script-debug/report.d.ts +15 -0
- package/dist/js-script-debug/report.d.ts.map +1 -0
- package/dist/js-script-debug/report.js +90 -0
- package/dist/js-script-debug/report.js.map +1 -0
- package/dist/js-script-debug/types.d.ts +63 -0
- package/dist/js-script-debug/types.d.ts.map +1 -0
- package/dist/js-script-debug/types.js +10 -0
- package/dist/js-script-debug/types.js.map +1 -0
- package/dist/js-script-debug/validate.d.ts +38 -0
- package/dist/js-script-debug/validate.d.ts.map +1 -0
- package/dist/js-script-debug/validate.js +137 -0
- package/dist/js-script-debug/validate.js.map +1 -0
- package/dist/message-stream.d.ts +33 -0
- package/dist/message-stream.d.ts.map +1 -0
- package/dist/message-stream.js +58 -0
- package/dist/message-stream.js.map +1 -0
- package/dist/normalize-graph.d.ts +13 -0
- package/dist/normalize-graph.d.ts.map +1 -0
- package/dist/normalize-graph.js +63 -0
- package/dist/normalize-graph.js.map +1 -0
- package/dist/output-names.d.ts +13 -0
- package/dist/output-names.d.ts.map +1 -0
- package/dist/output-names.js +13 -0
- package/dist/output-names.js.map +1 -0
- package/dist/predicates.d.ts +6 -0
- package/dist/predicates.d.ts.map +1 -0
- package/dist/predicates.js +6 -0
- package/dist/predicates.js.map +1 -0
- package/dist/preflight.d.ts +87 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +139 -0
- package/dist/preflight.js.map +1 -0
- package/dist/provider-secret-key.d.ts +3 -0
- package/dist/provider-secret-key.d.ts.map +1 -0
- package/dist/provider-secret-key.js +7 -0
- package/dist/provider-secret-key.js.map +1 -0
- package/dist/service/app-debug-service.d.ts +78 -0
- package/dist/service/app-debug-service.d.ts.map +1 -0
- package/dist/service/app-debug-service.js +201 -0
- package/dist/service/app-debug-service.js.map +1 -0
- package/dist/service/app-run-server.d.ts +28 -0
- package/dist/service/app-run-server.d.ts.map +1 -0
- package/dist/service/app-run-server.js +104 -0
- package/dist/service/app-run-server.js.map +1 -0
- package/dist/service/debug-sessions.d.ts +158 -0
- package/dist/service/debug-sessions.d.ts.map +1 -0
- package/dist/service/debug-sessions.js +358 -0
- package/dist/service/debug-sessions.js.map +1 -0
- package/dist/service/index.d.ts +22 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +17 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/job-progress.d.ts +40 -0
- package/dist/service/job-progress.d.ts.map +1 -0
- package/dist/service/job-progress.js +53 -0
- package/dist/service/job-progress.js.map +1 -0
- package/dist/service/workflow-run.d.ts +279 -0
- package/dist/service/workflow-run.d.ts.map +1 -0
- package/dist/service/workflow-run.js +598 -0
- package/dist/service/workflow-run.js.map +1 -0
- package/dist/service/workflow-workspace.d.ts +89 -0
- package/dist/service/workflow-workspace.d.ts.map +1 -0
- package/dist/service/workflow-workspace.js +160 -0
- package/dist/service/workflow-workspace.js.map +1 -0
- package/dist/session.d.ts +62 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +353 -0
- package/dist/session.js.map +1 -0
- package/dist/sketch-debug/index.d.ts +11 -0
- package/dist/sketch-debug/index.d.ts.map +1 -0
- package/dist/sketch-debug/index.js +10 -0
- package/dist/sketch-debug/index.js.map +1 -0
- package/dist/sketch-debug/markdown.d.ts +6 -0
- package/dist/sketch-debug/markdown.d.ts.map +1 -0
- package/dist/sketch-debug/markdown.js +93 -0
- package/dist/sketch-debug/markdown.js.map +1 -0
- package/dist/sketch-debug/report.d.ts +15 -0
- package/dist/sketch-debug/report.d.ts.map +1 -0
- package/dist/sketch-debug/report.js +98 -0
- package/dist/sketch-debug/report.js.map +1 -0
- package/dist/sketch-debug/types.d.ts +62 -0
- package/dist/sketch-debug/types.d.ts.map +1 -0
- package/dist/sketch-debug/types.js +10 -0
- package/dist/sketch-debug/types.js.map +1 -0
- package/dist/sketch-debug/validate.d.ts +14 -0
- package/dist/sketch-debug/validate.d.ts.map +1 -0
- package/dist/sketch-debug/validate.js +478 -0
- package/dist/sketch-debug/validate.js.map +1 -0
- package/dist/supervisor.d.ts +45 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +97 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/timeline-debug/index.d.ts +11 -0
- package/dist/timeline-debug/index.d.ts.map +1 -0
- package/dist/timeline-debug/index.js +10 -0
- package/dist/timeline-debug/index.js.map +1 -0
- package/dist/timeline-debug/legibility.d.ts +23 -0
- package/dist/timeline-debug/legibility.d.ts.map +1 -0
- package/dist/timeline-debug/legibility.js +240 -0
- package/dist/timeline-debug/legibility.js.map +1 -0
- package/dist/timeline-debug/markdown.d.ts +6 -0
- package/dist/timeline-debug/markdown.d.ts.map +1 -0
- package/dist/timeline-debug/markdown.js +103 -0
- package/dist/timeline-debug/markdown.js.map +1 -0
- package/dist/timeline-debug/motion.d.ts +20 -0
- package/dist/timeline-debug/motion.d.ts.map +1 -0
- package/dist/timeline-debug/motion.js +362 -0
- package/dist/timeline-debug/motion.js.map +1 -0
- package/dist/timeline-debug/report.d.ts +16 -0
- package/dist/timeline-debug/report.d.ts.map +1 -0
- package/dist/timeline-debug/report.js +100 -0
- package/dist/timeline-debug/report.js.map +1 -0
- package/dist/timeline-debug/showcase.d.ts +7 -0
- package/dist/timeline-debug/showcase.d.ts.map +1 -0
- package/dist/timeline-debug/showcase.js +347 -0
- package/dist/timeline-debug/showcase.js.map +1 -0
- package/dist/timeline-debug/types.d.ts +64 -0
- package/dist/timeline-debug/types.d.ts.map +1 -0
- package/dist/timeline-debug/types.js +10 -0
- package/dist/timeline-debug/types.js.map +1 -0
- package/dist/timeline-debug/validate.d.ts +24 -0
- package/dist/timeline-debug/validate.d.ts.map +1 -0
- package/dist/timeline-debug/validate.js +1432 -0
- package/dist/timeline-debug/validate.js.map +1 -0
- package/dist/types.d.ts +211 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +103 -0
package/dist/session.js
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ExecutionSession` — the one place that constructs `WorkflowRunner`.
|
|
3
|
+
*
|
|
4
|
+
* See the package README for the wiring-inventory table this facade is
|
|
5
|
+
* derived from (Track A / task A1 of docs/RELIABILITY_TASKS.md) and
|
|
6
|
+
* docs/RELIABILITY_ARCHITECTURE.md §7 for the target API shape.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
import { createLogger } from "@nodetool-ai/config";
|
|
10
|
+
import { hydrateGraphNodeFlags } from "@nodetool-ai/node-sdk";
|
|
11
|
+
import { Graph, WorkflowRunner, withExplicitNodeFlags } from "@nodetool-ai/kernel";
|
|
12
|
+
import { PERMISSION_GATE_CONTEXT_KEY, connectPythonBridgeForGraph, headlessGate } from "@nodetool-ai/runtime";
|
|
13
|
+
import { createExecutorResolver } from "./executor-resolver.js";
|
|
14
|
+
import { WORKFLOW_RUN_HOST, buildWorkspaceExecutionContext } from "./service/workflow-workspace.js";
|
|
15
|
+
import { normalizeGraph } from "./normalize-graph.js";
|
|
16
|
+
import { assertPreflight } from "./preflight.js";
|
|
17
|
+
import { rewriteOutputNames } from "./output-names.js";
|
|
18
|
+
import { MessageStream } from "./message-stream.js";
|
|
19
|
+
import { attachRunCostLedger, nodeTypeLookup } from "./cost-ledger.js";
|
|
20
|
+
const log = createLogger("nodetool.execution.session");
|
|
21
|
+
export class ExecutionSession {
|
|
22
|
+
jobId;
|
|
23
|
+
workflowId;
|
|
24
|
+
graph;
|
|
25
|
+
runner;
|
|
26
|
+
/** Null unless the caller opted into `captureMessages` (see options). */
|
|
27
|
+
stream;
|
|
28
|
+
persistence;
|
|
29
|
+
bridge;
|
|
30
|
+
resultPromise;
|
|
31
|
+
runTimeoutHandle = null;
|
|
32
|
+
_cancelReason = null;
|
|
33
|
+
constructor(init) {
|
|
34
|
+
this.jobId = init.jobId;
|
|
35
|
+
this.workflowId = init.workflowId;
|
|
36
|
+
this.graph = init.graph;
|
|
37
|
+
this.runner = init.runner;
|
|
38
|
+
this.persistence = init.persistence;
|
|
39
|
+
this.bridge = init.bridge;
|
|
40
|
+
this.stream = init.captureMessages
|
|
41
|
+
? new MessageStream(init.context, init.messageBufferLimit)
|
|
42
|
+
: null;
|
|
43
|
+
// Every generation this run pays for lands in the ledger `nodetool costs`
|
|
44
|
+
// reads. Attached here, at the one seam all surfaces share, so image and
|
|
45
|
+
// video spend is recorded whether the run came from the CLI, the debug
|
|
46
|
+
// harness, an app, or the websocket server.
|
|
47
|
+
// No `projectId`/`documentId`: a session is constructed from a graph and a
|
|
48
|
+
// job id, and no host passes project attribution down to it. The rows carry
|
|
49
|
+
// a null rather than being attributed to the loose bucket.
|
|
50
|
+
const detachLedger = init.recordCosts
|
|
51
|
+
? attachRunCostLedger(init.context, {
|
|
52
|
+
userId: init.userId,
|
|
53
|
+
workflowId: init.workflowId,
|
|
54
|
+
projectId: init.projectId ?? null,
|
|
55
|
+
documentId: init.documentId ?? null,
|
|
56
|
+
nodeType: nodeTypeLookup(init.graph.nodes),
|
|
57
|
+
resolveSecret: (key) => init.context.getSecret(key)
|
|
58
|
+
})
|
|
59
|
+
: null;
|
|
60
|
+
if (init.runTimeoutMs && init.runTimeoutMs > 0) {
|
|
61
|
+
this.runTimeoutHandle = setTimeout(() => {
|
|
62
|
+
this.cancel("timeout");
|
|
63
|
+
}, init.runTimeoutMs);
|
|
64
|
+
}
|
|
65
|
+
// Open the run boundary on the Python worker before the kernel starts, so
|
|
66
|
+
// an execute frame can never arrive ahead of the job it belongs to. Fire
|
|
67
|
+
// and forget: `jobStart` is a no-op on a pre-v4 worker and swallows its own
|
|
68
|
+
// failures, and blocking the kernel on worker bookkeeping would make an
|
|
69
|
+
// unreachable worker a run failure.
|
|
70
|
+
const boundary = {
|
|
71
|
+
jobId: init.jobId,
|
|
72
|
+
workflowId: init.workflowId,
|
|
73
|
+
userId: init.userId
|
|
74
|
+
};
|
|
75
|
+
void init.lifecycle?.jobStart(boundary);
|
|
76
|
+
const runRequest = {
|
|
77
|
+
job_id: init.jobId,
|
|
78
|
+
workflow_id: init.workflowId ?? undefined,
|
|
79
|
+
params: init.params
|
|
80
|
+
};
|
|
81
|
+
if (init.triggerEvent) {
|
|
82
|
+
runRequest.trigger_event = init.triggerEvent;
|
|
83
|
+
}
|
|
84
|
+
this.resultPromise = init.runner
|
|
85
|
+
.run(runRequest, init.graph)
|
|
86
|
+
.then((result) => {
|
|
87
|
+
void init.lifecycle?.jobEnd({
|
|
88
|
+
...boundary,
|
|
89
|
+
reason: this.endReason(result.status)
|
|
90
|
+
});
|
|
91
|
+
return result;
|
|
92
|
+
}, (err) => {
|
|
93
|
+
// `run()` documents that it never rejects, but the boundary must
|
|
94
|
+
// close even if that ever stops being true — an abandoned run is
|
|
95
|
+
// exactly the leak `job.end` exists to prevent.
|
|
96
|
+
void init.lifecycle?.jobEnd({ ...boundary, reason: "abandoned" });
|
|
97
|
+
throw err;
|
|
98
|
+
})
|
|
99
|
+
.finally(async () => {
|
|
100
|
+
if (this.runTimeoutHandle) {
|
|
101
|
+
clearTimeout(this.runTimeoutHandle);
|
|
102
|
+
this.runTimeoutHandle = null;
|
|
103
|
+
}
|
|
104
|
+
init.closeBridge();
|
|
105
|
+
// The terminal message was emitted synchronously before run()
|
|
106
|
+
// resolved (ProcessingContext.emit() calls listeners inline), so the
|
|
107
|
+
// stream can close now without dropping it. The same holds for the
|
|
108
|
+
// ledger: every prediction/node_update it prices was already delivered.
|
|
109
|
+
detachLedger?.();
|
|
110
|
+
this.stream?.close();
|
|
111
|
+
try {
|
|
112
|
+
await init.context.workspace?.cleanupScratch?.();
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
log.warn("Workspace scratch cleanup failed", {
|
|
116
|
+
jobId: this.jobId,
|
|
117
|
+
error: err instanceof Error ? err.message : String(err)
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
this.resultPromise
|
|
122
|
+
.then((result) => this.persistence?.onTerminal?.(result))
|
|
123
|
+
.catch((err) => {
|
|
124
|
+
log.warn("persistence.onTerminal threw", {
|
|
125
|
+
jobId: this.jobId,
|
|
126
|
+
error: err instanceof Error ? err.message : String(err)
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/** Map a kernel run status onto the `job.end` reason. */
|
|
131
|
+
endReason(status) {
|
|
132
|
+
if (status === "failed")
|
|
133
|
+
return "failed";
|
|
134
|
+
if (status === "cancelled")
|
|
135
|
+
return "cancelled";
|
|
136
|
+
return "completed";
|
|
137
|
+
}
|
|
138
|
+
static async create(options) {
|
|
139
|
+
if (options.limits?.nodeTimeoutMs) {
|
|
140
|
+
throw new Error("ExecutionSession: nodeTimeoutMs is not yet supported — the kernel " +
|
|
141
|
+
"has no per-node timeout hook (only run-level cancel()). Omit it " +
|
|
142
|
+
"or use limits.runTimeoutMs.");
|
|
143
|
+
}
|
|
144
|
+
if (!options.registry && !options.resolveExecutor) {
|
|
145
|
+
throw new Error("ExecutionSession: either registry or resolveExecutor must be provided " +
|
|
146
|
+
"(registry builds the default registry+bridge resolver; resolveExecutor " +
|
|
147
|
+
"bypasses it for a host with its own resolution, e.g. the WS runner).");
|
|
148
|
+
}
|
|
149
|
+
const jobId = options.jobId ?? randomUUID();
|
|
150
|
+
const workflowId = options.workflowId ?? null;
|
|
151
|
+
const registry = options.registry;
|
|
152
|
+
const normalized = normalizeGraph(options.graph);
|
|
153
|
+
// A caller that brings no context still gets one that can reach the
|
|
154
|
+
// secret store. The bare `new ProcessingContext(...)` this replaced
|
|
155
|
+
// resolved no secret at all, so a graph with a provider node failed on
|
|
156
|
+
// credentials the install had — the same defect the service-layer run
|
|
157
|
+
// path shipped with. Selected here, ahead of the bridge, because the
|
|
158
|
+
// preflight below resolves credentials through it.
|
|
159
|
+
const context = options.context ??
|
|
160
|
+
buildWorkspaceExecutionContext({
|
|
161
|
+
jobId,
|
|
162
|
+
workflowId,
|
|
163
|
+
userId: "1",
|
|
164
|
+
workspace: null,
|
|
165
|
+
durableFalGenerations: true
|
|
166
|
+
});
|
|
167
|
+
// This facade is the workflow host for every caller that builds its own
|
|
168
|
+
// context (`nodetool run`, the WebSocket job runner, the app simulator):
|
|
169
|
+
// a run is consent, so a context that arrived with no gate gets the
|
|
170
|
+
// headless one here. A caller that already has a user to ask — a chat
|
|
171
|
+
// turn's `run_node` — set its gate before handing the context in, and
|
|
172
|
+
// keeps it.
|
|
173
|
+
if (context.get(PERMISSION_GATE_CONTEXT_KEY) === undefined) {
|
|
174
|
+
context.set(PERMISSION_GATE_CONTEXT_KEY, headlessGate(WORKFLOW_RUN_HOST));
|
|
175
|
+
}
|
|
176
|
+
// Refuse a graph this runtime cannot honour before anything is paid for:
|
|
177
|
+
// ahead of the Python bridge (a worker spawn), ahead of
|
|
178
|
+
// `persistence.onAccepted` (a job row), and ahead of the kernel. Without
|
|
179
|
+
// this, a bad model id or a missing key failed at the node that needed it
|
|
180
|
+
// — after the upstream half of the graph had already run and billed.
|
|
181
|
+
// A context serving providers from its own resolver (a fake, a cassette,
|
|
182
|
+
// the e2e server's scripted provider) never reaches the registry and never
|
|
183
|
+
// reads a credential, so the registry's "is this key set" question does not
|
|
184
|
+
// apply to it — asking anyway refuses the run for a secret it would not
|
|
185
|
+
// have used. An explicit checker still wins: a host that knows its own
|
|
186
|
+
// registry says so itself.
|
|
187
|
+
const providerConfiguration = options.providerConfiguration ??
|
|
188
|
+
(context.hasProviderResolver ? () => [] : undefined);
|
|
189
|
+
await assertPreflight(normalized, {
|
|
190
|
+
catalogs: options.catalogs,
|
|
191
|
+
providerConfiguration,
|
|
192
|
+
resolveSecret: (key) => context.getSecret(key)
|
|
193
|
+
});
|
|
194
|
+
// A caller injecting its own `resolveExecutor` (see the option doc)
|
|
195
|
+
// typically also owns its own Python bridge — never connect a second one
|
|
196
|
+
// behind its back. `bridgeFactory` remains available for that caller to
|
|
197
|
+
// opt back in explicitly (e.g. handing this facade an already-connected
|
|
198
|
+
// bridge instance to close on its behalf).
|
|
199
|
+
const bridgeFactory = options.bridgeFactory ??
|
|
200
|
+
(options.resolveExecutor
|
|
201
|
+
? async () => null
|
|
202
|
+
: connectPythonBridgeForGraph);
|
|
203
|
+
const bridge = await bridgeFactory(normalized.nodes, (t) => registry ? registry.has(t) : false);
|
|
204
|
+
let bridgeClosed = false;
|
|
205
|
+
const closeBridge = () => {
|
|
206
|
+
if (bridgeClosed)
|
|
207
|
+
return;
|
|
208
|
+
bridgeClosed = true;
|
|
209
|
+
bridge?.close();
|
|
210
|
+
};
|
|
211
|
+
let hydrated;
|
|
212
|
+
try {
|
|
213
|
+
if (options.resolveNodeType) {
|
|
214
|
+
// Richer path: resolves `propertyTypes`/`outputs` from registry
|
|
215
|
+
// metadata too (async — the resolver may lazy-load a namespace),
|
|
216
|
+
// matching `websocket-client-session.ts`'s `Graph.loadFromDict`
|
|
217
|
+
// hydration. Without this, multi-edge fan-in into a non-list
|
|
218
|
+
// property is misclassified as list aggregation (the kernel only
|
|
219
|
+
// gates on a populated `propertyTypes` map).
|
|
220
|
+
const loaded = await Graph.loadFromDict(normalized, {
|
|
221
|
+
resolver: options.resolveNodeType
|
|
222
|
+
});
|
|
223
|
+
hydrated = { nodes: [...loaded.nodes], edges: [...loaded.edges] };
|
|
224
|
+
}
|
|
225
|
+
else if (registry) {
|
|
226
|
+
hydrated = hydrateGraphNodeFlags(normalized, registry);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// No registry and no resolveNodeType: the caller hydrates its own
|
|
230
|
+
// graph before handing it to this facade (see the `registry` option
|
|
231
|
+
// doc) — default absent flags to `false` rather than guessing.
|
|
232
|
+
// `...node` on every field `withExplicitNodeFlags` doesn't touch
|
|
233
|
+
// means an already-resolved `propertyTypes`/`outputs` passes through
|
|
234
|
+
// unchanged.
|
|
235
|
+
hydrated = withExplicitNodeFlags(normalized);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
closeBridge();
|
|
240
|
+
throw err;
|
|
241
|
+
}
|
|
242
|
+
if (options.requireTerminalResult) {
|
|
243
|
+
rewriteOutputNames(hydrated);
|
|
244
|
+
}
|
|
245
|
+
const resolveExecutor = options.resolveExecutor ?? createExecutorResolver(registry, bridge);
|
|
246
|
+
const runnerOptions = {
|
|
247
|
+
resolveExecutor,
|
|
248
|
+
executionContext: context,
|
|
249
|
+
validateNode: options.validateNode,
|
|
250
|
+
bufferLimit: options.limits?.bufferLimit ?? null,
|
|
251
|
+
strict: options.strict
|
|
252
|
+
};
|
|
253
|
+
if (options.supervisor) {
|
|
254
|
+
runnerOptions.supervisor = options.supervisor;
|
|
255
|
+
}
|
|
256
|
+
const runner = new WorkflowRunner(jobId, runnerOptions);
|
|
257
|
+
try {
|
|
258
|
+
await options.persistence?.onAccepted?.(jobId);
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
log.warn("persistence.onAccepted threw", {
|
|
262
|
+
jobId,
|
|
263
|
+
error: err instanceof Error ? err.message : String(err)
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return new ExecutionSession({
|
|
267
|
+
jobId,
|
|
268
|
+
workflowId,
|
|
269
|
+
graph: hydrated,
|
|
270
|
+
runner,
|
|
271
|
+
context,
|
|
272
|
+
persistence: options.persistence ?? null,
|
|
273
|
+
params: options.params ?? {},
|
|
274
|
+
triggerEvent: options.triggerEvent ?? null,
|
|
275
|
+
bridge,
|
|
276
|
+
lifecycle: options.jobLifecycleBridge ?? bridge,
|
|
277
|
+
userId: context.userId,
|
|
278
|
+
closeBridge,
|
|
279
|
+
runTimeoutMs: options.limits?.runTimeoutMs,
|
|
280
|
+
captureMessages: options.captureMessages === true,
|
|
281
|
+
messageBufferLimit: options.limits?.messageBufferLimit,
|
|
282
|
+
recordCosts: options.recordCosts !== false,
|
|
283
|
+
projectId: options.projectId,
|
|
284
|
+
documentId: options.documentId
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Live message stream — closes once the run reaches a terminal state.
|
|
289
|
+
* Requires `captureMessages: true` at `create()`; without it nothing is
|
|
290
|
+
* queued (see that option) and reading this throws rather than handing back
|
|
291
|
+
* a stream that would silently yield nothing.
|
|
292
|
+
*/
|
|
293
|
+
get messages() {
|
|
294
|
+
if (!this.stream) {
|
|
295
|
+
throw new Error("ExecutionSession: `messages` requires `captureMessages: true` at " +
|
|
296
|
+
"create() — message capture is opt-in so a host that only awaits " +
|
|
297
|
+
"`result` never queues a run's messages unread.");
|
|
298
|
+
}
|
|
299
|
+
return this.stream;
|
|
300
|
+
}
|
|
301
|
+
/** The run's terminal result. Never rejects — kernel failures resolve as `status: "failed"`. */
|
|
302
|
+
get result() {
|
|
303
|
+
return this.resultPromise;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Live resource counts, for leak accounting: after a terminal result every
|
|
307
|
+
* one of these must be back to zero. Measured, not inferred — the
|
|
308
|
+
* reliability harness's `cleanup-leaks` invariant asserts against these
|
|
309
|
+
* numbers and reports a violation when a driver can't produce them.
|
|
310
|
+
*/
|
|
311
|
+
resourceCounters() {
|
|
312
|
+
return {
|
|
313
|
+
liveActors: this.runner.liveActorCount,
|
|
314
|
+
pendingControlResponses: this.runner.pendingControlResponseCount,
|
|
315
|
+
// The session's own run-timeout timer is the only timer it owns; it is
|
|
316
|
+
// cleared when the run settles.
|
|
317
|
+
pendingTimers: this.runTimeoutHandle === null ? 0 : 1,
|
|
318
|
+
pythonBridgePendingRequests: this.bridge?.pendingRequestCount ?? 0
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
/** The reason passed to the most recent `cancel()` call, if any. */
|
|
322
|
+
get cancelReason() {
|
|
323
|
+
return this._cancelReason;
|
|
324
|
+
}
|
|
325
|
+
/** Stream one more value into a live input node (mirrors the WS `stream_input` command). */
|
|
326
|
+
pushInput(inputName, value, sourceHandle) {
|
|
327
|
+
return this.runner.pushInputValue(inputName, value, sourceHandle);
|
|
328
|
+
}
|
|
329
|
+
/** Signal end-of-stream for a live input node (mirrors `end_input_stream`). */
|
|
330
|
+
finishInputStream(inputName, sourceHandle) {
|
|
331
|
+
this.runner.finishInputStream(inputName, sourceHandle);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Push property updates into a running node's executor instance (live
|
|
335
|
+
* parameter changes, e.g. a synth knob while a patch plays — mirrors the
|
|
336
|
+
* WS runner's `update_node_properties` command). Returns `true` when the
|
|
337
|
+
* node's executor exists and supports live updates; `false` is not an
|
|
338
|
+
* error — the caller's own state already holds the new value for the next
|
|
339
|
+
* run.
|
|
340
|
+
*/
|
|
341
|
+
updateNodeProperties(nodeId, properties) {
|
|
342
|
+
return this.runner.updateNodeProperties(nodeId, properties);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* The only cancel path. `runTimeoutMs` is implemented as
|
|
346
|
+
* `cancel("timeout")` — there is no separate timeout code path.
|
|
347
|
+
*/
|
|
348
|
+
cancel(reason) {
|
|
349
|
+
this._cancelReason = reason ?? this._cancelReason ?? "cancelled";
|
|
350
|
+
this.runner.cancel();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nodetool-ai/execution/sketch-debug` — sketch validation + debug report.
|
|
3
|
+
*
|
|
4
|
+
* Pure, dependency-injected core: no DB, no canvas, no browser. Hosts (the CLI
|
|
5
|
+
* `sketch` command today) resolve the target and write the bundle.
|
|
6
|
+
*/
|
|
7
|
+
export type { SketchDebugIssue, SketchValidation, SketchInteractionRecord, SketchDebugTarget, SketchDocumentMeta, SketchDebugReport } from "./types.js";
|
|
8
|
+
export { validateSketchDocument, type SketchValidationMeta } from "./validate.js";
|
|
9
|
+
export { buildSketchDebugReport, type SketchDebugReportInput } from "./report.js";
|
|
10
|
+
export { renderSketchReportMarkdown } from "./markdown.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sketch-debug/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,sBAAsB,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EACL,sBAAsB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nodetool-ai/execution/sketch-debug` — sketch validation + debug report.
|
|
3
|
+
*
|
|
4
|
+
* Pure, dependency-injected core: no DB, no canvas, no browser. Hosts (the CLI
|
|
5
|
+
* `sketch` command today) resolve the target and write the bundle.
|
|
6
|
+
*/
|
|
7
|
+
export { validateSketchDocument } from "./validate.js";
|
|
8
|
+
export { buildSketchDebugReport } from "./report.js";
|
|
9
|
+
export { renderSketchReportMarkdown } from "./markdown.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sketch-debug/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAAE,sBAAsB,EAA6B,MAAM,eAAe,CAAC;AAClF,OAAO,EACL,sBAAsB,EAEvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a `SketchDebugReport` as human-readable Markdown for the bundle.
|
|
3
|
+
*/
|
|
4
|
+
import type { SketchDebugReport } from "./types.js";
|
|
5
|
+
export declare function renderSketchReportMarkdown(report: SketchDebugReport): string;
|
|
6
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/sketch-debug/markdown.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA+EtE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAyD5E"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { isObjectLike, isString } from "../predicates.js";
|
|
2
|
+
const short = (value, max = 120) => {
|
|
3
|
+
if (value === undefined)
|
|
4
|
+
return "—";
|
|
5
|
+
let s;
|
|
6
|
+
try {
|
|
7
|
+
s = isString(value) ? value : JSON.stringify(value);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
s = String(value);
|
|
11
|
+
}
|
|
12
|
+
s = (s ?? "null").replace(/\s+/g, " ");
|
|
13
|
+
return s.length > max ? `${s.slice(0, max)}…` : s;
|
|
14
|
+
};
|
|
15
|
+
const where = (issue) => {
|
|
16
|
+
const parts = [
|
|
17
|
+
issue.layerId ? `layer \`${issue.layerId}\`` : null,
|
|
18
|
+
issue.path ? `\`${issue.path}\`` : null
|
|
19
|
+
].filter((part) => part !== null);
|
|
20
|
+
return parts.length > 0 ? parts.join(" · ") : "—";
|
|
21
|
+
};
|
|
22
|
+
function issueTable(title, issues, lines) {
|
|
23
|
+
if (issues.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
lines.push("", `## ${title}`, "");
|
|
26
|
+
lines.push("| Severity | Code | Where | Message |");
|
|
27
|
+
lines.push("| --- | --- | --- | --- |");
|
|
28
|
+
for (const issue of issues) {
|
|
29
|
+
lines.push(`| ${issue.severity} | \`${issue.code}\` | ${where(issue)} | ${short(issue.message, 300)} |`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const asRecord = (value) => isObjectLike(value) ? value : null;
|
|
33
|
+
/**
|
|
34
|
+
* The snapshot carries the whole layer stack; the markdown wants one line per
|
|
35
|
+
* layer, top of the stack first, rather than a JSON dump.
|
|
36
|
+
*/
|
|
37
|
+
function finalStateLines(state) {
|
|
38
|
+
const record = asRecord(state);
|
|
39
|
+
const layers = Array.isArray(record?.layers)
|
|
40
|
+
? record.layers
|
|
41
|
+
: null;
|
|
42
|
+
if (!layers)
|
|
43
|
+
return [`- ${short(state, 600)}`];
|
|
44
|
+
const lines = [];
|
|
45
|
+
const canvas = `${String(record?.width ?? "?")}×${String(record?.height ?? "?")}`;
|
|
46
|
+
lines.push(`- canvas ${canvas}, active layer \`${String(record?.activeLayerId ?? "none")}\``);
|
|
47
|
+
for (const layer of [...layers].reverse()) {
|
|
48
|
+
lines.push(`- \`${layer.id ?? "?"}\`${layer.name ? ` "${layer.name}"` : ""} ` +
|
|
49
|
+
`${layer.type ?? "?"} · opacity ${layer.opacity ?? 1} · ${layer.blendMode ?? "normal"}` +
|
|
50
|
+
`${layer.visible === false ? " · hidden" : ""}${layer.hasBinding ? " · bound" : ""}`);
|
|
51
|
+
}
|
|
52
|
+
return lines;
|
|
53
|
+
}
|
|
54
|
+
export function renderSketchReportMarkdown(report) {
|
|
55
|
+
const lines = [];
|
|
56
|
+
const title = report.target.name ?? report.target.ref;
|
|
57
|
+
lines.push(`# Sketch debug: ${title}`);
|
|
58
|
+
lines.push("");
|
|
59
|
+
lines.push(`${report.verdict.ok ? "✅" : "❌"} ${report.verdict.headline}`);
|
|
60
|
+
lines.push("");
|
|
61
|
+
lines.push(`Target: \`${report.target.ref}\` (${report.target.kind})`);
|
|
62
|
+
lines.push(`Document: ${report.meta.width}×${report.meta.height} on ${report.meta.backgroundColor} · ` +
|
|
63
|
+
`${report.meta.layerCount} layer(s), ${report.meta.bindingCount} binding(s)`);
|
|
64
|
+
if (report.verdict.issues.length > 0) {
|
|
65
|
+
lines.push("", "## Issues", "");
|
|
66
|
+
for (const issue of report.verdict.issues)
|
|
67
|
+
lines.push(`- ${issue}`);
|
|
68
|
+
}
|
|
69
|
+
issueTable("Validation", [...report.validation.errors, ...report.validation.warnings], lines);
|
|
70
|
+
if (report.interactions.length > 0) {
|
|
71
|
+
lines.push("", "## Interactions", "");
|
|
72
|
+
lines.push("| Tool | OK | Input | Error |");
|
|
73
|
+
lines.push("| --- | --- | --- | --- |");
|
|
74
|
+
for (const step of report.interactions) {
|
|
75
|
+
lines.push(`| \`${step.tool}\` | ${step.ok ? "✅" : "❌"} | ${short(step.input)} | ${step.error ? short(step.error, 200) : "—"} |`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (report.finalValidation) {
|
|
79
|
+
issueTable("Validation after edits", [...report.finalValidation.errors, ...report.finalValidation.warnings], lines);
|
|
80
|
+
}
|
|
81
|
+
if (report.finalState !== undefined) {
|
|
82
|
+
lines.push("", "## Final state", "");
|
|
83
|
+
lines.push(...finalStateLines(report.finalState));
|
|
84
|
+
}
|
|
85
|
+
if (report.notSimulated.length > 0) {
|
|
86
|
+
lines.push("", "## Not simulated", "");
|
|
87
|
+
for (const entry of report.notSimulated)
|
|
88
|
+
lines.push(`- ${entry}`);
|
|
89
|
+
}
|
|
90
|
+
lines.push("");
|
|
91
|
+
return lines.join("\n");
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/sketch-debug/markdown.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,YAAY,EACZ,QAAQ,EACT,MAAM,kBAAkB,CAAC;AAE1B,MAAM,KAAK,GAAG,CAAC,KAAc,EAAE,GAAG,GAAG,GAAG,EAAU,EAAE;IAClD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACpC,IAAI,CAAS,CAAC;IACd,IAAI,CAAC;QACH,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,KAAuB,EAAU,EAAE;IAChD,MAAM,KAAK,GAAG;QACZ,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI;QACnD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;KACxC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACpD,CAAC,CAAC;AAEF,SAAS,UAAU,CACjB,KAAa,EACb,MAAuC,EACvC,KAAe;IAEf,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAChC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAClC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CACR,KAAK,KAAK,CAAC,QAAQ,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAC7F,CAAC;IACJ,CAAC;AACH,CAAC;AAYD,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAkC,EAAE,CAClE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAErC;;;GAGG;AACH,SAAS,eAAe,CAAC,KAAc;IACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC;QAC1C,CAAC,CAAE,MAAM,CAAC,MAA0B;QACpC,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,KAAK,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAE/C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC;IAClF,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,oBAAoB,MAAM,CAAC,MAAM,EAAE,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9F,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CACR,OAAO,KAAK,CAAC,EAAE,IAAI,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG;YAChE,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,cAAc,KAAK,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,SAAS,IAAI,QAAQ,EAAE;YACvF,GAAG,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CACvF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAAyB;IAClE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;IACtD,KAAK,CAAC,IAAI,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAC;IACvC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IACvE,KAAK,CAAC,IAAI,CACR,aAAa,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC,IAAI,CAAC,eAAe,KAAK;QACzF,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,cAAc,MAAM,CAAC,IAAI,CAAC,YAAY,aAAa,CAC/E,CAAC;IAEF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,UAAU,CACR,YAAY,EACZ,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAC5D,KAAK,CACN,CAAC;IAEF,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CACR,OAAO,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAChE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GACxC,IAAI,CACL,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,UAAU,CACR,wBAAwB,EACxB,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EACtE,KAAK,CACN,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;QACvC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SketchDebugReport, SketchDebugTarget, SketchInteractionRecord } from "./types.js";
|
|
2
|
+
import { type SketchValidationMeta } from "./validate.js";
|
|
3
|
+
export interface SketchDebugReportInput {
|
|
4
|
+
target: SketchDebugTarget;
|
|
5
|
+
/** The document as loaded — untrusted, validated here. */
|
|
6
|
+
document: unknown;
|
|
7
|
+
meta?: SketchValidationMeta;
|
|
8
|
+
interactions?: SketchInteractionRecord[];
|
|
9
|
+
/** Bridge snapshot after the scripted session (`SketchBridgeFinalState`). */
|
|
10
|
+
finalState?: unknown;
|
|
11
|
+
/** Document reconstructed from the final state, validated as a second pass. */
|
|
12
|
+
finalDocument?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export declare function buildSketchDebugReport(input: SketchDebugReportInput): SketchDebugReport;
|
|
15
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/sketch-debug/report.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,iBAAiB,EACjB,iBAAiB,EAEjB,uBAAuB,EAExB,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAyGvB,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,YAAY,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACzC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,sBAAsB,GAC5B,iBAAiB,CAiCnB"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { validateSketchDocument } from "./validate.js";
|
|
2
|
+
import { isPositiveFiniteNumber, isString } from "../predicates.js";
|
|
3
|
+
const DEFAULTS = {
|
|
4
|
+
width: 1024,
|
|
5
|
+
height: 1024,
|
|
6
|
+
backgroundColor: "#ffffff"
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* What a headless sketch run cannot answer. Fixed, because the boundary is a
|
|
10
|
+
* property of the harness, not of the document it was pointed at.
|
|
11
|
+
*/
|
|
12
|
+
const NOT_SIMULATED = [
|
|
13
|
+
"Pixels — layer bitmaps are never decoded, composited, or diffed.",
|
|
14
|
+
"Rendering and flattening — no canvas exists, so blend modes and effects produce nothing to look at.",
|
|
15
|
+
"Painting tools — brush, eraser, fill, gradient and transform strokes leave no marks headlessly.",
|
|
16
|
+
"Generation providers — no imagery is produced; bindings are checked structurally only.",
|
|
17
|
+
"Asset I/O — asset ids are never resolved, fetched, or uploaded.",
|
|
18
|
+
"Generation bindings after edits — the headless bridge tracks a layer's prompt/provider/model but not the persisted binding record, so a post-edit document is validated with no bindings."
|
|
19
|
+
];
|
|
20
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21
|
+
const count = (value) => Array.isArray(value) ? value.length : 0;
|
|
22
|
+
function describeDocument(document, meta) {
|
|
23
|
+
const record = isRecord(document) ? document : {};
|
|
24
|
+
const sketch = isRecord(record.sketch) ? record.sketch : {};
|
|
25
|
+
const canvas = isRecord(sketch.canvas) ? sketch.canvas : {};
|
|
26
|
+
const pick = (value, fallback) => isPositiveFiniteNumber(value) ? value : fallback;
|
|
27
|
+
const background = isString(canvas.backgroundColor)
|
|
28
|
+
? canvas.backgroundColor
|
|
29
|
+
: (meta?.backgroundColor ?? DEFAULTS.backgroundColor);
|
|
30
|
+
return {
|
|
31
|
+
width: pick(canvas.width, pick(meta?.width, DEFAULTS.width)),
|
|
32
|
+
height: pick(canvas.height, pick(meta?.height, DEFAULTS.height)),
|
|
33
|
+
backgroundColor: background,
|
|
34
|
+
layerCount: count(sketch.layers),
|
|
35
|
+
bindingCount: count(record.layerBindings)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const describe = (issue) => {
|
|
39
|
+
const where = issue.layerId ?? issue.path;
|
|
40
|
+
return where
|
|
41
|
+
? `[${issue.code}] ${where}: ${issue.message}`
|
|
42
|
+
: `[${issue.code}] ${issue.message}`;
|
|
43
|
+
};
|
|
44
|
+
function buildSketchVerdict(validation, interactions, finalValidation) {
|
|
45
|
+
const failedSteps = interactions.filter((step) => !step.ok);
|
|
46
|
+
const issues = [
|
|
47
|
+
...validation.errors.map(describe),
|
|
48
|
+
...failedSteps.map((step) => `Interaction \`${step.tool}\` failed${step.error ? `: ${step.error}` : ""}`),
|
|
49
|
+
...(finalValidation?.errors ?? []).map((issue) => `After edits — ${describe(issue)}`)
|
|
50
|
+
];
|
|
51
|
+
const warnings = [
|
|
52
|
+
...validation.warnings.map(describe),
|
|
53
|
+
...(finalValidation?.warnings ?? []).map((issue) => `After edits — ${describe(issue)}`)
|
|
54
|
+
];
|
|
55
|
+
const ok = issues.length === 0;
|
|
56
|
+
const warningCount = warnings.length;
|
|
57
|
+
const headline = ok
|
|
58
|
+
? `Sketch is sound — ${interactions.length} interaction(s) ran clean` +
|
|
59
|
+
(warningCount > 0 ? `, ${warningCount} warning(s)` : "") +
|
|
60
|
+
"."
|
|
61
|
+
: `Sketch has ${issues.length} problem(s)` +
|
|
62
|
+
(failedSteps.length > 0
|
|
63
|
+
? `, ${failedSteps.length} failed interaction(s)`
|
|
64
|
+
: "") +
|
|
65
|
+
(warningCount > 0 ? `, ${warningCount} warning(s)` : "") +
|
|
66
|
+
` — ${issues[0]}`;
|
|
67
|
+
return warningCount > 0
|
|
68
|
+
? { ok, headline, issues, warnings }
|
|
69
|
+
: { ok, headline, issues };
|
|
70
|
+
}
|
|
71
|
+
export function buildSketchDebugReport(input) {
|
|
72
|
+
const validation = validateSketchDocument(input.document, input.meta);
|
|
73
|
+
// The post-edit pass runs without `meta`: a session may have resized the
|
|
74
|
+
// canvas, and the stored row's size is then the stale number, not the bug.
|
|
75
|
+
const finalValidation = input.finalDocument === undefined
|
|
76
|
+
? undefined
|
|
77
|
+
: validateSketchDocument(input.finalDocument);
|
|
78
|
+
const interactions = input.interactions ?? [];
|
|
79
|
+
// The final document is what the session left behind, so it — not the input
|
|
80
|
+
// — describes the sketch the report is about.
|
|
81
|
+
const meta = describeDocument(input.finalDocument ?? input.document, input.meta);
|
|
82
|
+
const report = {
|
|
83
|
+
target: input.target,
|
|
84
|
+
meta,
|
|
85
|
+
validation,
|
|
86
|
+
interactions,
|
|
87
|
+
notSimulated: [...NOT_SIMULATED],
|
|
88
|
+
verdict: buildSketchVerdict(validation, interactions, finalValidation)
|
|
89
|
+
};
|
|
90
|
+
if (input.finalState !== undefined) {
|
|
91
|
+
report.finalState = input.finalState;
|
|
92
|
+
}
|
|
93
|
+
if (finalValidation) {
|
|
94
|
+
report.finalValidation = finalValidation;
|
|
95
|
+
}
|
|
96
|
+
return report;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/sketch-debug/report.ts"],"names":[],"mappings":"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"}
|