@agentic-surfaces/server 0.1.18 → 0.1.19

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.
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>agentic-surfaces — workflow editor</title>
7
- <script type="module" crossorigin src="/assets/index-CKayDw1h.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-BFmyefsd.css">
7
+ <script type="module" crossorigin src="/assets/index-aoHYCL_u.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-6vZGwRHS.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/dist/http.d.ts CHANGED
@@ -16,11 +16,11 @@ export interface ServerOptions {
16
16
  workflows?: Workflow[];
17
17
  observer: StreamingObserver;
18
18
  /**
19
- * Trigger a workflow run by name (POST /api/run). Wired by the CLI to the
20
- * engine; events stream back via the observer. When absent, /api/run is 405
21
- * (the editor renders read-only).
19
+ * Trigger a workflow run by name + optional trigger payload (POST /api/run). A payload is
20
+ * needed to run a `trigger.command` sub-workflow directly (e.g. `{ key: "PD-109" }`). Events
21
+ * stream back via the observer. When absent, /api/run is 405 (the editor renders read-only).
22
22
  */
23
- onRun?: (name: string) => void | Promise<unknown>;
23
+ onRun?: (name: string, payload?: unknown) => void | Promise<unknown>;
24
24
  /** Project-level config surfaced at GET /api/config (so the UI shows effective agent defaults + version). */
25
25
  config?: {
26
26
  dryRun?: boolean;
@@ -32,6 +32,17 @@ export interface ServerOptions {
32
32
  };
33
33
  /** File-based agent definitions, surfaced at GET /api/agents (for the node detail view). */
34
34
  agents?: AgentDefinition[];
35
+ /** The engine cache, surfaced at GET/DELETE /api/cache so the dashboard can inspect + clear seen-state. */
36
+ cache?: {
37
+ entries(): {
38
+ seen: string[];
39
+ cursors: Array<{
40
+ key: string;
41
+ value: string;
42
+ }>;
43
+ };
44
+ forget(key: string): void;
45
+ };
35
46
  }
36
47
  /** Build an http.Server that serves the workflow-engine API and optional static files. */
37
48
  export declare function createServer(opts: ServerOptions): http.Server;
package/dist/http.js CHANGED
@@ -26,7 +26,7 @@ function writeEvent(res, event) {
26
26
  }
27
27
  /** Build an http.Server that serves the workflow-engine API and optional static files. */
28
28
  export function createServer(opts) {
29
- const { observer, workflows = [], staticDir, onRun, config, agents = [] } = opts;
29
+ const { observer, workflows = [], staticDir, onRun, config, agents = [], cache } = opts;
30
30
  const workflowByName = new Map(workflows.map((w) => [w.name, w]));
31
31
  // In-memory run registry — populated by listening to the observer.
32
32
  const runs = new Map();
@@ -97,15 +97,16 @@ export function createServer(opts) {
97
97
  const triggerType = w.nodes.find((n) => n.type.startsWith("trigger."))?.type ?? null;
98
98
  return {
99
99
  name: w.name,
100
+ title: w.title ?? w.name,
100
101
  nodeCount: w.nodes.length,
101
102
  triggerType,
102
103
  // Full graph so the editor can render each workflow without a second fetch.
103
104
  nodes: w.nodes,
104
105
  edges: w.edges,
105
- // Runnable from the browser only for ENTRY workflows. A `trigger.command` workflow is a
106
- // sub-workflow invoked by foreach/run-workflow with a payload running it standalone
107
- // gives it no trigger payload (empty keys → bad requests), so it isn't directly runnable.
108
- runnable: Boolean(onRun) && triggerType !== "trigger.command",
106
+ // Runnable from the browser when a run-trigger is wired. A `trigger.command` sub-workflow
107
+ // needs a payload (the editor prompts for one); entry workflows run with no payload.
108
+ runnable: Boolean(onRun),
109
+ needsPayload: triggerType === "trigger.command",
109
110
  };
110
111
  }));
111
112
  return;
@@ -119,25 +120,56 @@ export function createServer(opts) {
119
120
  let body = "";
120
121
  req.on("data", (c) => { body += c; });
121
122
  req.on("end", () => {
122
- let name;
123
+ let parsed;
123
124
  try {
124
- name = JSON.parse(body || "{}").workflow;
125
+ parsed = JSON.parse(body || "{}");
125
126
  }
126
127
  catch {
127
128
  json(res, { error: "invalid JSON body" }, 400);
128
129
  return;
129
130
  }
131
+ const name = parsed.workflow;
130
132
  if (!name || !workflowByName.has(name)) {
131
133
  json(res, { error: `unknown workflow: ${name ?? "(none)"}` }, 404);
132
134
  return;
133
135
  }
134
136
  // Don't await — the run streams over SSE; a thrown error is reported
135
137
  // there (and logged by the runner), so the server keeps serving.
136
- Promise.resolve(onRun(name)).catch(() => { });
138
+ Promise.resolve(onRun(name, parsed.payload)).catch(() => { });
137
139
  json(res, { started: name }, 202);
138
140
  });
139
141
  return;
140
142
  }
143
+ // Inspect / clear the engine seen-cache (debugging dedup state).
144
+ if (pathname === "/api/cache" && (req.method === "GET" || req.method === undefined)) {
145
+ json(res, cache ? cache.entries() : { seen: [], cursors: [] });
146
+ return;
147
+ }
148
+ if (pathname === "/api/cache" && req.method === "DELETE") {
149
+ if (!cache) {
150
+ json(res, { error: "cache not available" }, 405);
151
+ return;
152
+ }
153
+ let body = "";
154
+ req.on("data", (c) => { body += c; });
155
+ req.on("end", () => {
156
+ let key;
157
+ try {
158
+ key = JSON.parse(body || "{}").key;
159
+ }
160
+ catch {
161
+ json(res, { error: "invalid JSON body" }, 400);
162
+ return;
163
+ }
164
+ if (!key) {
165
+ json(res, { error: "missing key" }, 400);
166
+ return;
167
+ }
168
+ cache.forget(key);
169
+ json(res, { forgot: key }, 200);
170
+ });
171
+ return;
172
+ }
141
173
  if (pathname === "/api/config") {
142
174
  json(res, config ?? {});
143
175
  return;
package/dist/serve.d.ts CHANGED
@@ -9,8 +9,8 @@ export interface ServeOptions {
9
9
  observer?: StreamingObserver;
10
10
  /** Workflows to expose at /api/workflows (graph + run-eligibility). */
11
11
  workflows?: Workflow[];
12
- /** Trigger a run by name from the UI (POST /api/run). */
13
- onRun?: (name: string) => void | Promise<unknown>;
12
+ /** Trigger a run by name + optional payload from the UI (POST /api/run). */
13
+ onRun?: (name: string, payload?: unknown) => void | Promise<unknown>;
14
14
  /** Project config surfaced at GET /api/config (effective agent defaults, dryRun, version). */
15
15
  config?: {
16
16
  dryRun?: boolean;
@@ -22,6 +22,17 @@ export interface ServeOptions {
22
22
  };
23
23
  /** Agent definitions surfaced at GET /api/agents. */
24
24
  agents?: AgentDefinition[];
25
+ /** Engine cache, surfaced at GET/DELETE /api/cache for inspecting + clearing seen-state. */
26
+ cache?: {
27
+ entries(): {
28
+ seen: string[];
29
+ cursors: Array<{
30
+ key: string;
31
+ value: string;
32
+ }>;
33
+ };
34
+ forget(key: string): void;
35
+ };
25
36
  }
26
37
  /**
27
38
  * Locate the built editor assets to serve. Checks, in order:
package/dist/serve.js CHANGED
@@ -36,6 +36,7 @@ export function serve(opts = {}) {
36
36
  onRun: opts.onRun,
37
37
  config: opts.config,
38
38
  agents: opts.agents,
39
+ cache: opts.cache,
39
40
  });
40
41
  server.listen(port, host, () => {
41
42
  console.log(`[flow-server] listening on http://${host}:${port}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentic-surfaces/server",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -21,7 +21,7 @@
21
21
  "dist"
22
22
  ],
23
23
  "dependencies": {
24
- "@agentic-surfaces/core": "0.1.18"
24
+ "@agentic-surfaces/core": "0.1.19"
25
25
  },
26
26
  "scripts": {
27
27
  "build": "tsc -b",