@sapiom/harness 0.1.6 → 0.2.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.
Files changed (185) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/dist/cli/args.d.ts +16 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +80 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/bin.js +12 -65
  7. package/dist/cli/bin.js.map +1 -1
  8. package/dist/cli/settings.d.ts.map +1 -1
  9. package/dist/cli/settings.js +33 -1
  10. package/dist/cli/settings.js.map +1 -1
  11. package/dist/core/adapters/claude-code.d.ts +60 -2
  12. package/dist/core/adapters/claude-code.d.ts.map +1 -1
  13. package/dist/core/adapters/claude-code.js +119 -32
  14. package/dist/core/adapters/claude-code.js.map +1 -1
  15. package/dist/core/adapters/codex.d.ts +21 -2
  16. package/dist/core/adapters/codex.d.ts.map +1 -1
  17. package/dist/core/adapters/codex.js +53 -2
  18. package/dist/core/adapters/codex.js.map +1 -1
  19. package/dist/core/adapters/detect.d.ts +9 -0
  20. package/dist/core/adapters/detect.d.ts.map +1 -1
  21. package/dist/core/adapters/detect.js +9 -0
  22. package/dist/core/adapters/detect.js.map +1 -1
  23. package/dist/core/canvas-body.d.ts +28 -28
  24. package/dist/core/canvas-body.d.ts.map +1 -1
  25. package/dist/core/canvas-body.js +117 -55
  26. package/dist/core/canvas-body.js.map +1 -1
  27. package/dist/core/canvas-derive.d.ts +43 -0
  28. package/dist/core/canvas-derive.d.ts.map +1 -0
  29. package/dist/core/canvas-derive.js +95 -0
  30. package/dist/core/canvas-derive.js.map +1 -0
  31. package/dist/core/canvas-enrichment.d.ts +52 -127
  32. package/dist/core/canvas-enrichment.d.ts.map +1 -1
  33. package/dist/core/canvas-enrichment.js +17 -178
  34. package/dist/core/canvas-enrichment.js.map +1 -1
  35. package/dist/core/canvas-graph.d.ts +40 -1
  36. package/dist/core/canvas-graph.d.ts.map +1 -1
  37. package/dist/core/canvas-graph.js +71 -9
  38. package/dist/core/canvas-graph.js.map +1 -1
  39. package/dist/core/canvas-interconnections.d.ts +26 -8
  40. package/dist/core/canvas-interconnections.d.ts.map +1 -1
  41. package/dist/core/canvas-interconnections.js +132 -24
  42. package/dist/core/canvas-interconnections.js.map +1 -1
  43. package/dist/core/canvas-manifest-check.d.ts.map +1 -1
  44. package/dist/core/canvas-manifest-check.js +15 -2
  45. package/dist/core/canvas-manifest-check.js.map +1 -1
  46. package/dist/core/canvas-render.d.ts +8 -15
  47. package/dist/core/canvas-render.d.ts.map +1 -1
  48. package/dist/core/canvas-render.js +29 -41
  49. package/dist/core/canvas-render.js.map +1 -1
  50. package/dist/core/canvas-run-state.d.ts +41 -0
  51. package/dist/core/canvas-run-state.d.ts.map +1 -1
  52. package/dist/core/canvas-run-state.js +136 -0
  53. package/dist/core/canvas-run-state.js.map +1 -1
  54. package/dist/core/canvas-svg.d.ts +9 -4
  55. package/dist/core/canvas-svg.d.ts.map +1 -1
  56. package/dist/core/canvas-svg.js +84 -13
  57. package/dist/core/canvas-svg.js.map +1 -1
  58. package/dist/core/canvas-template.d.ts +9 -10
  59. package/dist/core/canvas-template.d.ts.map +1 -1
  60. package/dist/core/canvas-template.js +57 -20
  61. package/dist/core/canvas-template.js.map +1 -1
  62. package/dist/core/canvas-watcher.d.ts +22 -1
  63. package/dist/core/canvas-watcher.d.ts.map +1 -1
  64. package/dist/core/canvas-watcher.js +111 -30
  65. package/dist/core/canvas-watcher.js.map +1 -1
  66. package/dist/core/collector/normalizer.d.ts +8 -0
  67. package/dist/core/collector/normalizer.d.ts.map +1 -1
  68. package/dist/core/collector/normalizer.js +8 -0
  69. package/dist/core/collector/normalizer.js.map +1 -1
  70. package/dist/core/collector/store.d.ts +75 -1
  71. package/dist/core/collector/store.d.ts.map +1 -1
  72. package/dist/core/collector/store.js +334 -2
  73. package/dist/core/collector/store.js.map +1 -1
  74. package/dist/core/errors.d.ts +10 -4
  75. package/dist/core/errors.d.ts.map +1 -1
  76. package/dist/core/errors.js +11 -5
  77. package/dist/core/errors.js.map +1 -1
  78. package/dist/core/example-seed.d.ts +8 -0
  79. package/dist/core/example-seed.d.ts.map +1 -1
  80. package/dist/core/example-seed.js +47 -10
  81. package/dist/core/example-seed.js.map +1 -1
  82. package/dist/core/inject/system-prompt.d.ts +8 -0
  83. package/dist/core/inject/system-prompt.d.ts.map +1 -1
  84. package/dist/core/inject/system-prompt.js +3 -1
  85. package/dist/core/inject/system-prompt.js.map +1 -1
  86. package/dist/core/macros.d.ts.map +1 -1
  87. package/dist/core/macros.js +5 -6
  88. package/dist/core/macros.js.map +1 -1
  89. package/dist/core/paths.d.ts +1 -0
  90. package/dist/core/paths.d.ts.map +1 -1
  91. package/dist/core/paths.js +1 -0
  92. package/dist/core/paths.js.map +1 -1
  93. package/dist/core/record-archive.d.ts +187 -0
  94. package/dist/core/record-archive.d.ts.map +1 -0
  95. package/dist/core/record-archive.js +465 -0
  96. package/dist/core/record-archive.js.map +1 -0
  97. package/dist/core/rehydration.d.ts +72 -0
  98. package/dist/core/rehydration.d.ts.map +1 -0
  99. package/dist/core/rehydration.js +72 -0
  100. package/dist/core/rehydration.js.map +1 -0
  101. package/dist/core/resume-brief.d.ts +130 -0
  102. package/dist/core/resume-brief.d.ts.map +1 -0
  103. package/dist/core/resume-brief.js +404 -0
  104. package/dist/core/resume-brief.js.map +1 -0
  105. package/dist/core/rolling-summary.d.ts +130 -0
  106. package/dist/core/rolling-summary.d.ts.map +1 -0
  107. package/dist/core/rolling-summary.js +227 -0
  108. package/dist/core/rolling-summary.js.map +1 -0
  109. package/dist/core/session-manager.d.ts +11 -3
  110. package/dist/core/session-manager.d.ts.map +1 -1
  111. package/dist/core/session-manager.js +56 -7
  112. package/dist/core/session-manager.js.map +1 -1
  113. package/dist/core/session-record.d.ts +165 -0
  114. package/dist/core/session-record.d.ts.map +1 -0
  115. package/dist/core/session-record.js +470 -0
  116. package/dist/core/session-record.js.map +1 -0
  117. package/dist/core/spawn-target.d.ts +12 -0
  118. package/dist/core/spawn-target.d.ts.map +1 -0
  119. package/dist/core/spawn-target.js +187 -0
  120. package/dist/core/spawn-target.js.map +1 -0
  121. package/dist/core/task-manager.d.ts.map +1 -1
  122. package/dist/core/task-manager.js +9 -1
  123. package/dist/core/task-manager.js.map +1 -1
  124. package/dist/core/template-catalog.d.ts +48 -0
  125. package/dist/core/template-catalog.d.ts.map +1 -0
  126. package/dist/core/template-catalog.js +338 -0
  127. package/dist/core/template-catalog.js.map +1 -0
  128. package/dist/core/workflow-registry.d.ts.map +1 -1
  129. package/dist/core/workflow-registry.js +2 -2
  130. package/dist/core/workflow-registry.js.map +1 -1
  131. package/dist/core/workspace-watcher.d.ts.map +1 -1
  132. package/dist/core/workspace-watcher.js +4 -3
  133. package/dist/core/workspace-watcher.js.map +1 -1
  134. package/dist/index.d.ts +12 -0
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.js +21 -0
  137. package/dist/index.js.map +1 -1
  138. package/dist/profiles/default.d.ts.map +1 -1
  139. package/dist/profiles/default.js +9 -14
  140. package/dist/profiles/default.js.map +1 -1
  141. package/dist/server/canvas.d.ts.map +1 -1
  142. package/dist/server/canvas.js +7 -7
  143. package/dist/server/canvas.js.map +1 -1
  144. package/dist/server/fs.d.ts.map +1 -1
  145. package/dist/server/fs.js +17 -1
  146. package/dist/server/fs.js.map +1 -1
  147. package/dist/server/index.d.ts +12 -3
  148. package/dist/server/index.d.ts.map +1 -1
  149. package/dist/server/index.js +321 -50
  150. package/dist/server/index.js.map +1 -1
  151. package/dist/server/ingest.d.ts +11 -0
  152. package/dist/server/ingest.d.ts.map +1 -1
  153. package/dist/server/ingest.js +1 -0
  154. package/dist/server/ingest.js.map +1 -1
  155. package/dist/server/macros.d.ts +4 -6
  156. package/dist/server/macros.d.ts.map +1 -1
  157. package/dist/server/macros.js.map +1 -1
  158. package/dist/server/rest.d.ts +18 -6
  159. package/dist/server/rest.d.ts.map +1 -1
  160. package/dist/server/rest.js +185 -48
  161. package/dist/server/rest.js.map +1 -1
  162. package/dist/server/templates.d.ts +24 -0
  163. package/dist/server/templates.d.ts.map +1 -0
  164. package/dist/server/templates.js +54 -0
  165. package/dist/server/templates.js.map +1 -0
  166. package/dist/shared/types.d.ts +477 -29
  167. package/dist/shared/types.d.ts.map +1 -1
  168. package/dist/shared/types.js +19 -11
  169. package/dist/shared/types.js.map +1 -1
  170. package/dist/web/assets/index-SYpugKQ1.css +32 -0
  171. package/dist/web/assets/index-vYYd44hZ.js +446 -0
  172. package/dist/web/index.html +2 -2
  173. package/package.json +5 -4
  174. package/dist/core/canvas-enrich.d.ts +0 -115
  175. package/dist/core/canvas-enrich.d.ts.map +0 -1
  176. package/dist/core/canvas-enrich.js +0 -186
  177. package/dist/core/canvas-enrich.js.map +0 -1
  178. package/dist/profiles/canvas-guidelines.d.ts +0 -20
  179. package/dist/profiles/canvas-guidelines.d.ts.map +0 -1
  180. package/dist/profiles/canvas-guidelines.js +0 -48
  181. package/dist/profiles/canvas-guidelines.js.map +0 -1
  182. package/dist/web/assets/index-DCtyI4VW.css +0 -32
  183. package/dist/web/assets/index-WSw5RvYR.js +0 -445
  184. package/dist/web/welcome-hero-dark.png +0 -0
  185. package/dist/web/welcome-hero-light.png +0 -0
@@ -13,8 +13,8 @@
13
13
  document.documentElement.dataset.theme = theme;
14
14
  })();
15
15
  </script>
16
- <script type="module" crossorigin src="/assets/index-WSw5RvYR.js"></script>
17
- <link rel="stylesheet" crossorigin href="/assets/index-DCtyI4VW.css">
16
+ <script type="module" crossorigin src="/assets/index-vYYd44hZ.js"></script>
17
+ <link rel="stylesheet" crossorigin href="/assets/index-SYpugKQ1.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapiom/harness",
3
- "version": "0.1.6",
3
+ "version": "0.2.1",
4
4
  "description": "Sapiom Harness — a CLI-launched local web app that runs your coding agent (Claude Code, Codex) in a Sapiom-configured environment: MCP pre-wired, workflows tracked, one-click deploy/run, and a live canvas for previews.",
5
5
  "keywords": [
6
6
  "sapiom",
@@ -47,8 +47,8 @@
47
47
  "open": "^10.1.0",
48
48
  "ws": "^8.18.0",
49
49
  "zod": "^3.25.0",
50
- "@sapiom/agent": "^0.6.7",
51
- "@sapiom/agent-core": "^0.9.9",
50
+ "@sapiom/agent": "^0.7.0",
51
+ "@sapiom/agent-core": "^0.9.10",
52
52
  "@sapiom/analytics-core": "^0.2.1",
53
53
  "@sapiom/mcp": "^0.11.3"
54
54
  },
@@ -87,7 +87,8 @@
87
87
  "dev": "tsx src/cli/bin.ts --dev",
88
88
  "dev:web": "vite --config web/vite.config.ts",
89
89
  "start": "node dist/cli/bin.js",
90
- "test": "vitest run",
90
+ "test": "vitest run && vitest run --config vitest.perf.config.ts",
91
+ "test:perf": "vitest run --config vitest.perf.config.ts",
91
92
  "test:watch": "vitest",
92
93
  "test:mutation": "stryker run",
93
94
  "test:ui": "playwright test --config web/e2e/playwright.config.ts",
@@ -1,115 +0,0 @@
1
- /**
2
- * The AI enrichment runner: spawns ONE bounded, headless agent task per
3
- * workflow (via TaskManager) that reads the workflow's step bodies and
4
- * returns the JSON `CanvasEnrichment` contract — never HTML, never a file
5
- * write. On success the validated enrichment is persisted to the workflow's
6
- * cache file and the render file is rebuilt with it merged in; on any
7
- * parse/validation failure the enrichment is discarded whole and the base
8
- * render stands (core/canvas-enrichment.ts's contract). Task-process
9
- * failures surface through the task record itself (the pane's error state +
10
- * Retry), never as HTML on disk.
11
- *
12
- * Triggering (see server/index.ts):
13
- * - bind / session create → `ensureFresh`: spawn only when no cache entry
14
- * matches the current source fingerprint; every skip reason is silent.
15
- * - the visualize macro → `forceRefresh`: drop the extraction + enrichment
16
- * caches, re-render the base immediately, re-enrich; refusals propagate
17
- * (an already-running enrichment for this workflow → 409 via the macros
18
- * router, exactly like any other double-fired background macro).
19
- *
20
- * Dedupe is per WORKFLOW, not per session: TaskManager refuses a second
21
- * running task with the same macroId + workflowPath regardless of which
22
- * session asked (see TaskAlreadyRunningError) — two panes bound to the same
23
- * workflow can never race its cache/render files.
24
- */
25
- import type { BackgroundTask, HarnessKind } from "../shared/types.js";
26
- import { type CachedExtraction } from "./canvas-cache.js";
27
- import type { CanvasGraph } from "./canvas-graph.js";
28
- import { type RenderableWorkflow } from "./canvas-render.js";
29
- import type { RunTaskRequest } from "./task-manager.js";
30
- /** The macro identity enrichment tasks run under — the pane's Retry re-fires
31
- * this macro, which routes back through forceRefresh. */
32
- export declare const ENRICHMENT_MACRO_ID = "visualize";
33
- /** Model the enrichment task runs on — overridable per install. */
34
- export declare function enrichmentModel(env?: NodeJS.ProcessEnv): string;
35
- /**
36
- * Builds the one-shot enrichment prompt: the extracted graph inline (the AI
37
- * annotates THIS structure — it never invents nodes), pointed at the step
38
- * sources for semantics, with the JSON contract and its hard limits stated
39
- * verbatim so a well-behaved run needs no retry.
40
- */
41
- export declare function buildEnrichmentPrompt(graph: CanvasGraph, workflowDir: string): string;
42
- /**
43
- * Pulls the JSON object out of a task's final result text — either fenced
44
- * (\`\`\`json ... \`\`\`) or raw, tolerating prose around it by falling back to
45
- * the outermost {...} span. Null when nothing parses.
46
- */
47
- export declare function extractEnrichmentJson(text: string): unknown | null;
48
- /** The slice of TaskManager the runner uses — injectable for tests. */
49
- export interface EnrichmentTaskRunner {
50
- run(req: RunTaskRequest): Promise<BackgroundTask>;
51
- onStatusChange(listener: (task: BackgroundTask) => void): () => void;
52
- /** Returns true when an enrichment task for this workflow is currently
53
- * running — checked before cache destruction in forceRefresh so a
54
- * double-click Visualize is a true no-op, not a half-destroyed cache. */
55
- isRunning(macroId: string, workflowPath: string): boolean;
56
- }
57
- /** The session shape the coordinator needs — satisfied by HarnessSession. */
58
- export interface EnrichmentSession {
59
- id: string;
60
- cwd: string;
61
- harness: HarnessKind;
62
- boundWorkflowPath: string | null;
63
- }
64
- export interface EnrichmentCoordinatorOptions {
65
- tasks: EnrichmentTaskRunner;
66
- /** Rebuilds the workflow's render file (with the just-persisted enrichment
67
- * merged) after a successful run — the write alone hot-reloads any open
68
- * pane via the canvas watcher. */
69
- rerender?: (cwd: string, workflow: RenderableWorkflow) => Promise<void>;
70
- /** Injectable for tests — defaults to the real cached extraction. */
71
- extractCached?: (dir: string) => Promise<CachedExtraction>;
72
- env?: NodeJS.ProcessEnv;
73
- now?: () => string;
74
- onError?: (message: string) => void;
75
- }
76
- export declare class CanvasEnrichmentCoordinator {
77
- private readonly tasks;
78
- private readonly rerender;
79
- private readonly extractCached;
80
- private readonly env;
81
- private readonly now;
82
- private readonly onError;
83
- constructor(options: EnrichmentCoordinatorOptions);
84
- /**
85
- * The bind/create trigger: spawn an enrichment task unless a cached
86
- * enrichment already matches the workflow's current sources. Silent on
87
- * every expected refusal — unbound session, failed extraction, fresh
88
- * cache, an enrichment already in flight for this workflow, a harness
89
- * with no headless mode, even a spawn failure (logged) — because nothing
90
- * here was user-initiated and a bind must never fail on enrichment's
91
- * account.
92
- */
93
- ensureFresh(session: EnrichmentSession, workflows: readonly RenderableWorkflow[]): Promise<void>;
94
- /**
95
- * The visualize macro: invalidate both caches, re-render the base diagram
96
- * immediately (instant feedback, honest content — no leftover enrichment
97
- * from sources that may have changed), then re-enrich. Refusals propagate
98
- * to the macros router (TaskAlreadyRunningError → 409,
99
- * TaskNotSupportedError → 400). Unbound session: just a no-op, matching
100
- * the deterministic render's own unbound contract.
101
- *
102
- * The already-running check happens BEFORE any cache destruction so that a
103
- * double-click Visualize is a true no-op: the second call rejects with
104
- * TaskAlreadyRunningError and the caches and render are left exactly as
105
- * the still-running enrichment will need them.
106
- */
107
- forceRefresh(session: EnrichmentSession, workflows: readonly RenderableWorkflow[]): Promise<void>;
108
- private resolveBound;
109
- private spawn;
110
- /** Completed task → parse → validate → cache file → re-render. Any parse
111
- * or validation failure discards the enrichment whole; the base render
112
- * already on disk stands untouched. */
113
- private persist;
114
- }
115
- //# sourceMappingURL=canvas-enrich.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvas-enrich.d.ts","sourceRoot":"","sources":["../../src/core/canvas-enrich.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAyD,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASrD,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD;0DAC0D;AAC1D,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAO/C,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE5E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAuBrF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAgBlE;AAED,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAClD,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACrE;;8EAE0E;IAC1E,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3D;AAED,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,WAAW,CAAC;IACrB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,oBAAoB,CAAC;IAC5B;;uCAEmC;IACnC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,qEAAqE;IACrE,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+D;IACxF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6C;IAC3E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;gBAExC,OAAO,EAAE,4BAA4B;IASjD;;;;;;;;OAQG;IACG,WAAW,CAAC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,kBAAkB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAetG;;;;;;;;;;;;OAYG;IACG,YAAY,CAAC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,kBAAkB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcvG,OAAO,CAAC,YAAY;YAON,KAAK;IA+BnB;;4CAEwC;YAC1B,OAAO;CAqBtB"}
@@ -1,186 +0,0 @@
1
- import { extractWorkflowGraphCached, invalidateExtractionCache } from "./canvas-cache.js";
2
- import { ENRICHMENT_LIMITS, normalizeCanvasEnrichmentCandidate, parseCanvasEnrichment, readEnrichmentCacheFile, removeEnrichmentCacheFile, writeEnrichmentCacheFile, } from "./canvas-enrichment.js";
3
- import { enrichmentCacheFileFor, renderWorkflowRenderFile, } from "./canvas-render.js";
4
- import { TaskAlreadyRunningError, TaskNotSupportedError } from "./task-manager.js";
5
- /** The macro identity enrichment tasks run under — the pane's Retry re-fires
6
- * this macro, which routes back through forceRefresh. */
7
- export const ENRICHMENT_MACRO_ID = "visualize";
8
- const ENRICHMENT_TASK_LABEL = "Visualize";
9
- /** Hard turn cap: read a few step files, answer. A run that needs more than
10
- * this is off the rails, not thorough. */
11
- const ENRICHMENT_MAX_TURNS = 8;
12
- const DEFAULT_ENRICHMENT_MODEL = "sonnet";
13
- /** Model the enrichment task runs on — overridable per install. */
14
- export function enrichmentModel(env = process.env) {
15
- return env.SAPIOM_HARNESS_VISUALIZE_MODEL || DEFAULT_ENRICHMENT_MODEL;
16
- }
17
- /**
18
- * Builds the one-shot enrichment prompt: the extracted graph inline (the AI
19
- * annotates THIS structure — it never invents nodes), pointed at the step
20
- * sources for semantics, with the JSON contract and its hard limits stated
21
- * verbatim so a well-behaved run needs no retry.
22
- */
23
- export function buildEnrichmentPrompt(graph, workflowDir) {
24
- const L = ENRICHMENT_LIMITS;
25
- return `You are annotating an already-rendered workflow diagram. The diagram's structure below is fixed — you only supply short text annotations, as one JSON object.
26
-
27
- Extracted workflow graph:
28
- ${JSON.stringify(graph, null, 2)}
29
-
30
- Read the step run() bodies in ${workflowDir} to understand what each step actually does (what it calls, what it decides, why it branches), then RETURN ONLY a JSON object matching this schema — no prose before or after, no markdown required, and DO NOT write or modify any files:
31
-
32
- {
33
- "summary": "what this workflow does, one line (max ${L.summary} chars)",
34
- "nodeDetails": { "<nodeId>": { "sublabel": "short annotation shown in the node (max ${L.sublabel} chars)", "description": "one sentence, shown on hover (max ${L.description} chars)" } },
35
- "edgeLabels": { "<fromNodeId>-><toNodeId>": "intent/condition name (max ${L.edgeLabel} chars)" },
36
- "notes": ["up to ${L.noteCount} facts worth knowing, each max ${L.note} chars"],
37
- "layoutHints": { "groups": [{ "label": "group name (max ${L.groupLabel} chars)", "nodeIds": ["..."] }], "laneOrder": { "<layerIndex>": ["nodeId", "..."] } },
38
- "crossWorkflow": "how this workflow ties into the project's other workflows, if it does (max ${L.crossWorkflow} chars)"
39
- }
40
-
41
- Rules:
42
- - Every field is optional — omit what you have nothing useful for (omit, don't write null). Empty strings are worse than omissions.
43
- - Use ONLY node ids that appear in the graph above.
44
- - Length limits are hard caps and oversize strings get truncated mid-sentence — aim comfortably under each limit.
45
- - Your final message must be exactly the JSON object.`;
46
- }
47
- /**
48
- * Pulls the JSON object out of a task's final result text — either fenced
49
- * (\`\`\`json ... \`\`\`) or raw, tolerating prose around it by falling back to
50
- * the outermost {...} span. Null when nothing parses.
51
- */
52
- export function extractEnrichmentJson(text) {
53
- const fenced = /```(?:json)?\s*([\s\S]*?)```/.exec(text);
54
- const candidates = [fenced?.[1], text];
55
- const first = text.indexOf("{");
56
- const last = text.lastIndexOf("}");
57
- if (first !== -1 && last > first)
58
- candidates.push(text.slice(first, last + 1));
59
- for (const candidate of candidates) {
60
- if (!candidate)
61
- continue;
62
- try {
63
- const parsed = JSON.parse(candidate.trim());
64
- if (typeof parsed === "object" && parsed !== null)
65
- return parsed;
66
- }
67
- catch {
68
- // Try the next candidate shape.
69
- }
70
- }
71
- return null;
72
- }
73
- export class CanvasEnrichmentCoordinator {
74
- constructor(options) {
75
- this.tasks = options.tasks;
76
- this.rerender = options.rerender ?? (async (cwd, workflow) => void (await renderWorkflowRenderFile(cwd, workflow)));
77
- this.extractCached = options.extractCached ?? extractWorkflowGraphCached;
78
- this.env = options.env ?? process.env;
79
- this.now = options.now ?? (() => new Date().toISOString());
80
- this.onError = options.onError ?? ((message) => console.error(`[harness] ${message}`));
81
- }
82
- /**
83
- * The bind/create trigger: spawn an enrichment task unless a cached
84
- * enrichment already matches the workflow's current sources. Silent on
85
- * every expected refusal — unbound session, failed extraction, fresh
86
- * cache, an enrichment already in flight for this workflow, a harness
87
- * with no headless mode, even a spawn failure (logged) — because nothing
88
- * here was user-initiated and a bind must never fail on enrichment's
89
- * account.
90
- */
91
- async ensureFresh(session, workflows) {
92
- const bound = this.resolveBound(session, workflows);
93
- if (!bound)
94
- return;
95
- try {
96
- const { result, fingerprint } = await this.extractCached(bound.path);
97
- if (!result.ok)
98
- return;
99
- const entry = await readEnrichmentCacheFile(enrichmentCacheFileFor(session.cwd, bound.path));
100
- if (entry && entry.sourceFingerprint === fingerprint)
101
- return;
102
- await this.spawn(session, bound, result.graph, fingerprint);
103
- }
104
- catch (err) {
105
- if (err instanceof TaskAlreadyRunningError || err instanceof TaskNotSupportedError)
106
- return;
107
- this.onError(`canvas enrichment (auto) failed to start: ${err.message}`);
108
- }
109
- }
110
- /**
111
- * The visualize macro: invalidate both caches, re-render the base diagram
112
- * immediately (instant feedback, honest content — no leftover enrichment
113
- * from sources that may have changed), then re-enrich. Refusals propagate
114
- * to the macros router (TaskAlreadyRunningError → 409,
115
- * TaskNotSupportedError → 400). Unbound session: just a no-op, matching
116
- * the deterministic render's own unbound contract.
117
- *
118
- * The already-running check happens BEFORE any cache destruction so that a
119
- * double-click Visualize is a true no-op: the second call rejects with
120
- * TaskAlreadyRunningError and the caches and render are left exactly as
121
- * the still-running enrichment will need them.
122
- */
123
- async forceRefresh(session, workflows) {
124
- const bound = this.resolveBound(session, workflows);
125
- if (!bound)
126
- return;
127
- if (this.tasks.isRunning(ENRICHMENT_MACRO_ID, bound.path)) {
128
- throw new TaskAlreadyRunningError(ENRICHMENT_TASK_LABEL);
129
- }
130
- invalidateExtractionCache(bound.path);
131
- await removeEnrichmentCacheFile(enrichmentCacheFileFor(session.cwd, bound.path));
132
- await this.rerender(session.cwd, bound);
133
- const { result, fingerprint } = await this.extractCached(bound.path);
134
- if (!result.ok)
135
- return;
136
- await this.spawn(session, bound, result.graph, fingerprint);
137
- }
138
- resolveBound(session, workflows) {
139
- return session.boundWorkflowPath ? workflows.find((w) => w.path === session.boundWorkflowPath) : undefined;
140
- }
141
- async spawn(session, workflow, graph, fingerprint) {
142
- const task = await this.tasks.run({
143
- macroId: ENRICHMENT_MACRO_ID,
144
- label: ENRICHMENT_TASK_LABEL,
145
- harnessSessionId: session.id,
146
- harness: session.harness,
147
- cwd: session.cwd,
148
- prompt: buildEnrichmentPrompt(graph, workflow.path),
149
- workflowPath: workflow.path,
150
- model: enrichmentModel(this.env),
151
- maxTurns: ENRICHMENT_MAX_TURNS,
152
- });
153
- // Subscribed synchronously right after run() resolves — the process's
154
- // exit can only arrive via a later event-loop turn, so the terminal
155
- // status can't be missed.
156
- const unsubscribe = this.tasks.onStatusChange((update) => {
157
- if (update.id !== task.id || update.status === "running")
158
- return;
159
- unsubscribe();
160
- if (update.status !== "completed")
161
- return; // pane shows the failure; nothing to persist
162
- void this.persist(session.cwd, workflow, graph, fingerprint, update.resultText).catch((err) => {
163
- this.onError(`canvas enrichment persist failed: ${err.message}`);
164
- });
165
- });
166
- }
167
- /** Completed task → parse → validate → cache file → re-render. Any parse
168
- * or validation failure discards the enrichment whole; the base render
169
- * already on disk stands untouched. */
170
- async persist(cwd, workflow, graph, fingerprint, resultText) {
171
- const candidate = resultText ? extractEnrichmentJson(resultText) : null;
172
- const enrichment = candidate ? parseCanvasEnrichment(normalizeCanvasEnrichmentCandidate(candidate)) : null;
173
- if (!enrichment) {
174
- this.onError(`canvas enrichment for ${workflow.path} returned invalid output — discarded, base render stands`);
175
- return;
176
- }
177
- await writeEnrichmentCacheFile(enrichmentCacheFileFor(cwd, workflow.path), {
178
- graph,
179
- enrichment,
180
- sourceFingerprint: fingerprint,
181
- enrichedAt: this.now(),
182
- });
183
- await this.rerender(cwd, workflow);
184
- }
185
- }
186
- //# sourceMappingURL=canvas-enrich.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvas-enrich.js","sourceRoot":"","sources":["../../src/core/canvas-enrich.ts"],"names":[],"mappings":"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"}
@@ -1,20 +0,0 @@
1
- /**
2
- * Canvas style contract: injected everywhere an agent is asked to write to
3
- * `.sapiom/canvas/index.html` (the Visualize macro's inject text, and the
4
- * system prompt's canvas paragraph for freeform "show me X" asks), so every
5
- * generated canvas looks Sapiom-native regardless of which prompt triggered
6
- * it. Kept prompt-sized on purpose — this rides in prompts, not docs.
7
- *
8
- * Colors are the harness's own dark-theme tokens (web/src/styles.css,
9
- * `[data-theme="dark"]`) — dark is the canonical canvas look. Structural
10
- * conventions (rounded nodes with a uniform glow, straight-then-curved
11
- * arrowed edges, stats header, legend footer) mirror what
12
- * scripts/seed-example.mjs's reference canvas already renders; this doesn't
13
- * change that seed, just documents its pattern for agents generating new
14
- * ones. Edge/glow/legend wording tightened after a live Visualize proof
15
- * (see PR history) surfaced ambiguities two different agent runs resolved
16
- * inconsistently — see git blame for the before/after if the wording here
17
- * ever seems oddly specific.
18
- */
19
- export declare const CANVAS_STYLE_GUIDELINES: string;
20
- //# sourceMappingURL=canvas-guidelines.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvas-guidelines.d.ts","sourceRoot":"","sources":["../../src/profiles/canvas-guidelines.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,uBAAuB,QA4B5B,CAAC"}
@@ -1,48 +0,0 @@
1
- /**
2
- * Canvas style contract: injected everywhere an agent is asked to write to
3
- * `.sapiom/canvas/index.html` (the Visualize macro's inject text, and the
4
- * system prompt's canvas paragraph for freeform "show me X" asks), so every
5
- * generated canvas looks Sapiom-native regardless of which prompt triggered
6
- * it. Kept prompt-sized on purpose — this rides in prompts, not docs.
7
- *
8
- * Colors are the harness's own dark-theme tokens (web/src/styles.css,
9
- * `[data-theme="dark"]`) — dark is the canonical canvas look. Structural
10
- * conventions (rounded nodes with a uniform glow, straight-then-curved
11
- * arrowed edges, stats header, legend footer) mirror what
12
- * scripts/seed-example.mjs's reference canvas already renders; this doesn't
13
- * change that seed, just documents its pattern for agents generating new
14
- * ones. Edge/glow/legend wording tightened after a live Visualize proof
15
- * (see PR history) surfaced ambiguities two different agent runs resolved
16
- * inconsistently — see git blame for the before/after if the wording here
17
- * ever seems oddly specific.
18
- */
19
- export const CANVAS_STYLE_GUIDELINES = `
20
- Canvas style contract (.sapiom/canvas/index.html):
21
- - One self-contained HTML file: inline all CSS/JS, no external stylesheets/
22
- scripts or CDN fonts (the CSP blocks them) — no build step, no dependencies.
23
- - Dark theme, Sapiom palette: background #0f0f0f, panel #1a1a1a, border
24
- #2e2e2e, text #fafafa, dim text #a1a1aa, accent/success #6be195, escalation
25
- #f59e0b, failure #f87171.
26
- - Monospace throughout: ui-monospace, "SF Mono", Menlo, Consolas, monospace.
27
- - Header: title + short status badge, one-line subtitle, and a stats row
28
- (e.g. step count, terminal-outcome count, branch count) as label/value pairs.
29
- - Render the workflow as an inline SVG graph, top-to-bottom: rounded-rect
30
- nodes (12-16px radius). Every node gets the same subtle glow on its
31
- border — never reserve the glow for entry/terminal nodes only; role and
32
- outcome are conveyed by border/stroke color, not by which nodes glow.
33
- - Edges: straight lines with arrowhead markers for a single-successor step,
34
- curved paths with arrowhead markers only where a step branches into
35
- multiple successors — don't curve every edge, that reads as noise on a
36
- simple linear chain.
37
- - Color-code terminal outcomes by meaning: accent/green = success, amber =
38
- escalation/needs-attention, red = failure. Reserve those colors for actual
39
- terminal branches, not regular steps.
40
- - Footer legend: one visually distinct marker per node kind used (shape
41
- and/or fill vs. outline — never reuse the identical marker for two
42
- different kinds just because they happen to share a color) + label, plus
43
- a short note that this is a static preview to regenerate after the
44
- workflow changes.
45
- - Prefer clarity over decoration: no motion, gradients, or ornamentation that
46
- doesn't help someone understand the graph's structure in a few seconds.
47
- `.trim();
48
- //# sourceMappingURL=canvas-guidelines.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"canvas-guidelines.js","sourceRoot":"","sources":["../../src/profiles/canvas-guidelines.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BtC,CAAC,IAAI,EAAE,CAAC"}