@boardwalk-labs/workflow 0.1.2 → 0.1.3

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/dist/extract.js CHANGED
@@ -37,6 +37,13 @@ const DEFAULT_FILE_NAME = "index.ts";
37
37
  export function extractMetaLiteral(source, options = {}) {
38
38
  const fileName = options.fileName ?? DEFAULT_FILE_NAME;
39
39
  const sf = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, /*setParentNodes*/ true);
40
+ // A syntax error otherwise falls through to "No `meta` declaration found" (the parser produced no
41
+ // usable `meta` node) — misleading. Report the real syntax error, with position, first.
42
+ const syntaxError = firstSyntaxError(sf);
43
+ if (syntaxError !== undefined) {
44
+ const text = ts.flattenDiagnosticMessageText(syntaxError.messageText, "\n");
45
+ throw failAt(`syntax error: ${text}`, sf, syntaxError.start);
46
+ }
40
47
  const initializer = findMetaInitializer(sf);
41
48
  if (initializer === null) {
42
49
  throw fail("No `meta` declaration found — a workflow program must export a pure-literal " +
@@ -191,3 +198,32 @@ function fail(message, node, sf) {
191
198
  }
192
199
  return new MetaExtractionError(message);
193
200
  }
201
+ /** Like {@link fail}, but positioned at a raw source offset (a diagnostic's `start`). */
202
+ function failAt(message, sf, start) {
203
+ if (start === undefined)
204
+ return new MetaExtractionError(message);
205
+ const { line, character } = sf.getLineAndCharacterOfPosition(start);
206
+ return new MetaExtractionError(`${sf.fileName}:${String(line + 1)}:${String(character + 1)} — ${message}`);
207
+ }
208
+ /**
209
+ * The first syntax error TS recorded while parsing, or undefined. The parser stores these on the
210
+ * source file's `parseDiagnostics` (an internal field), so read it through `Reflect` + a runtime
211
+ * guard rather than a cast — a future TS that drops/renames it simply yields "no error".
212
+ */
213
+ function firstSyntaxError(sf) {
214
+ const raw = Reflect.get(sf, "parseDiagnostics");
215
+ if (!Array.isArray(raw))
216
+ return undefined;
217
+ for (const d of raw) {
218
+ if (isErrorDiagnostic(d))
219
+ return d;
220
+ }
221
+ return undefined;
222
+ }
223
+ function isErrorDiagnostic(d) {
224
+ return (typeof d === "object" &&
225
+ d !== null &&
226
+ "messageText" in d &&
227
+ "category" in d &&
228
+ d.category === ts.DiagnosticCategory.Error);
229
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AgentOptions, ArtifactBody, ArtifactRef, CallOptions, JsonValue, PhaseOptions, SleepArg } from "./types.js";
1
+ import type { AgentOptions, ArtifactBody, ArtifactRef, CallOptions, JsonSchema, JsonValue, PhaseOptions, SleepArg } from "./types.js";
2
2
  /**
3
3
  * Mark the current run phase for live-tail and run-log grouping. Everything after this call
4
4
  * belongs to the named phase until the next `phase(...)` marker or the run ends. This is
@@ -6,14 +6,21 @@ import type { AgentOptions, ArtifactBody, ArtifactRef, CallOptions, JsonValue, P
6
6
  */
7
7
  export declare function phase(name: string, opts?: PhaseOptions): void;
8
8
  /**
9
- * Run an agent leaf to completion. Without `opts.schema`, resolves to the leaf's final text
10
- * (`T` defaults to `string`); with a schema, resolves to the validated object pass the
11
- * expected type, e.g. `await agent<Groups>(prompt, { schema })`. Omit `opts.model` to let the
12
- * provider route automatically (the default `boardwalk` provider on every engine; your own
13
- * keys only via an explicit provider). Capabilities (`tools`, `mcp`, `skills`, `memory`) are
14
- * PER-AGENT each call brings its own; the manifest declares none of them.
9
+ * Run an agent leaf to completion. Two typed forms, by whether you pass a `schema`:
10
+ * - `agent(prompt, opts?)` (no `schema`) the leaf's final text (`Promise<string>`).
11
+ * - `agent<Shape>(prompt, { schema })` the schema-validated object (`Promise<Shape>`); name the
12
+ * expected type. The run fails if the model's output doesn't validate.
13
+ *
14
+ * Asking for a typed result WITHOUT a schema (`agent<Shape>(prompt)`) is a type error: there would
15
+ * be nothing to validate against, so the value would really be a string. Omit `opts.model` to let
16
+ * the provider route automatically (the default `boardwalk` provider on every engine; your own keys
17
+ * only via an explicit provider). Capabilities (`tools`, `mcp`, `skills`, `memory`) are PER-AGENT —
18
+ * each call brings its own; the manifest declares none of them.
15
19
  */
16
- export declare function agent<T = string>(prompt: string, opts?: AgentOptions): Promise<T>;
20
+ export declare function agent<T>(prompt: string, opts: AgentOptions & {
21
+ schema: JsonSchema;
22
+ }): Promise<T>;
23
+ export declare function agent(prompt: string, opts?: AgentOptions): Promise<string>;
17
24
  /** Cross-workflow composition: `call` (await the result) and `run` (fire-and-forget). */
18
25
  export declare const workflows: {
19
26
  /**
package/dist/index.js CHANGED
@@ -24,15 +24,10 @@ export function phase(name, opts) {
24
24
  }
25
25
  host.setPhase(name, opts);
26
26
  }
27
- /**
28
- * Run an agent leaf to completion. Without `opts.schema`, resolves to the leaf's final text
29
- * (`T` defaults to `string`); with a schema, resolves to the validated object — pass the
30
- * expected type, e.g. `await agent<Groups>(prompt, { schema })`. Omit `opts.model` to let the
31
- * provider route automatically (the default `boardwalk` provider on every engine; your own
32
- * keys only via an explicit provider). Capabilities (`tools`, `mcp`, `skills`, `memory`) are
33
- * PER-AGENT — each call brings its own; the manifest declares none of them.
34
- */
35
27
  export async function agent(prompt, opts) {
28
+ // The host returns `unknown`; the overloads above are the public contract. With a `schema` the
29
+ // host validated the value (best-effort; the run fails on mismatch) → `T`; without one it is the
30
+ // leaf's final text → `string` (the `T = string` default). The cast is confined to this boundary.
36
31
  return (await requireHost().agent(prompt, opts));
37
32
  }
38
33
  /** Cross-workflow composition: `call` (await the result) and `run` (fire-and-forget). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boardwalk-labs/workflow",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Author Boardwalk workflows in TypeScript: agent(), sleep(), workflows.call(), secrets, the manifest schema, and the run-event wire format.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,7 +37,7 @@
37
37
  "lint": "eslint . --max-warnings 0",
38
38
  "format": "prettier --write .",
39
39
  "format:check": "prettier --check .",
40
- "test": "vitest run",
40
+ "test": "vitest run --coverage",
41
41
  "test:watch": "vitest"
42
42
  },
43
43
  "dependencies": {
@@ -47,6 +47,7 @@
47
47
  "devDependencies": {
48
48
  "@eslint/js": "^9.18.0",
49
49
  "@types/node": "^24.0.0",
50
+ "@vitest/coverage-v8": "^3.2.6",
50
51
  "eslint": "^9.18.0",
51
52
  "prettier": "^3.4.0",
52
53
  "typescript-eslint": "^8.20.0",