@signalridge/pi-workflows 1.2.1 → 1.3.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/CHANGELOG.md +36 -0
- package/README.md +142 -17
- package/package.json +14 -8
- package/skills/workflow-authoring/SKILL.md +30 -0
- package/skills/workflow-authoring/examples/adversarial-verification.js +63 -0
- package/skills/workflow-authoring/examples/bounded-semantic-retry.js +56 -0
- package/skills/workflow-authoring/examples/classify-and-act.js +67 -0
- package/skills/workflow-authoring/examples/defensive-json-parsing.js +63 -0
- package/skills/workflow-authoring/examples/fan-out-and-synthesize.js +47 -0
- package/skills/workflow-authoring/examples/generate-and-filter.js +68 -0
- package/skills/workflow-authoring/examples/loop-until-done.js +68 -0
- package/skills/workflow-authoring/examples/phased-budgets.js +75 -0
- package/skills/workflow-authoring/examples/saved-nested-workflows.js +44 -0
- package/skills/workflow-authoring/examples/structured-output.js +37 -0
- package/skills/workflow-authoring/examples/tournament.js +81 -0
- package/skills/workflow-authoring/examples/validated-gate.js +63 -0
- package/skills/workflow-authoring/references/capabilities.md +44 -0
- package/skills/workflow-authoring/references/capability-details.md +294 -0
- package/skills/workflow-authoring/references/common-helpers.md +4 -0
- package/skills/workflow-authoring/references/debugging.md +29 -0
- package/skills/workflow-authoring/references/focused-recipes.md +12 -0
- package/skills/workflow-authoring/references/helpers.md +9 -0
- package/skills/workflow-authoring/references/lifecycle.md +37 -0
- package/skills/workflow-authoring/references/pattern-selection.md +15 -0
- package/skills/workflow-authoring/references/quality-helpers.md +8 -0
- package/skills/workflow-authoring/references/registry-ownership.md +17 -0
- package/skills/workflow-authoring/references/retry-helper.md +5 -0
- package/skills/workflow-authoring/references/review.md +43 -0
- package/skills/workflow-authoring/references/runtime.md +29 -0
- package/skills/workflow-authoring/references/specialized-helpers.md +19 -0
- package/skills/workflow-authoring/references/versions.md +13 -0
- package/skills/workflow-patterns/SKILL.md +51 -0
- package/src/arming.ts +69 -0
- package/src/builtins.ts +331 -0
- package/src/capabilities.ts +318 -0
- package/src/code-review-scope.ts +144 -0
- package/src/engine.ts +1158 -2561
- package/src/errors.ts +136 -0
- package/src/index.ts +750 -103
- package/src/journal.ts +594 -1001
- package/src/rpc-client.ts +95 -24
- package/src/runtime.ts +1708 -0
- package/src/saved-workflows.ts +121 -0
- package/src/shared-store.ts +132 -0
- package/src/ui.ts +77 -40
- package/src/workflow-settings.ts +100 -0
- package/src/schema.ts +0 -215
- package/src/state-machine.ts +0 -79
- package/src/synthesis.ts +0 -140
package/src/errors.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* errors.ts — classified workflow failures.
|
|
3
|
+
*
|
|
4
|
+
* Every failure a workflow run can produce is narrowed here, so the engine,
|
|
5
|
+
* journal, UI, and the capability contract can react to the same stable codes
|
|
6
|
+
* instead of string-matching error text. `recoverable` is the single bit the
|
|
7
|
+
* runtime and the engine key their retry/terminal decisions on.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Stable runtime and persistence failure codes exposed to callers and UI surfaces. */
|
|
11
|
+
export enum WorkflowErrorCode {
|
|
12
|
+
/** Agent exceeded timeout. */
|
|
13
|
+
AGENT_TIMEOUT = "AGENT_TIMEOUT",
|
|
14
|
+
/** Workflow was aborted by user. */
|
|
15
|
+
WORKFLOW_ABORTED = "WORKFLOW_ABORTED",
|
|
16
|
+
/** Agent limit exceeded. */
|
|
17
|
+
AGENT_LIMIT_EXCEEDED = "AGENT_LIMIT_EXCEEDED",
|
|
18
|
+
/** Token budget exhausted. */
|
|
19
|
+
TOKEN_BUDGET_EXHAUSTED = "TOKEN_BUDGET_EXHAUSTED",
|
|
20
|
+
/**
|
|
21
|
+
* The provider's subscription/usage/quota/rate limit was hit. Distinct from the
|
|
22
|
+
* user's self-imposed TOKEN_BUDGET_EXHAUSTED: a provider limit refills on its own,
|
|
23
|
+
* so the run is checkpointed (paused) and replayed by resume() rather than failed.
|
|
24
|
+
*/
|
|
25
|
+
PROVIDER_USAGE_LIMIT = "PROVIDER_USAGE_LIMIT",
|
|
26
|
+
/** Script validation failed. */
|
|
27
|
+
SCRIPT_VALIDATION_ERROR = "SCRIPT_VALIDATION_ERROR",
|
|
28
|
+
/** A schema agent never produced a valid structured result (after bounded repair). */
|
|
29
|
+
SCHEMA_NONCOMPLIANCE = "SCHEMA_NONCOMPLIANCE",
|
|
30
|
+
/** A non-schema agent completed without any assistant text output. */
|
|
31
|
+
AGENT_EMPTY_OUTPUT = "AGENT_EMPTY_OUTPUT",
|
|
32
|
+
/**
|
|
33
|
+
* An agent()'s explicit selector (model/tier/agentType) did not resolve. Never
|
|
34
|
+
* silently substituted — resolution is deterministic, so retrying the same spec
|
|
35
|
+
* would fail identically every time.
|
|
36
|
+
*/
|
|
37
|
+
MODEL_NOT_FOUND = "MODEL_NOT_FOUND",
|
|
38
|
+
/** Agent execution failed. */
|
|
39
|
+
AGENT_EXECUTION_ERROR = "AGENT_EXECUTION_ERROR",
|
|
40
|
+
/** Run state persistence failed. */
|
|
41
|
+
PERSISTENCE_ERROR = "PERSISTENCE_ERROR",
|
|
42
|
+
/** Unknown error. */
|
|
43
|
+
UNKNOWN = "UNKNOWN",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Classified workflow failure with recoverability and optional agent/provider context. */
|
|
47
|
+
export class WorkflowError extends Error {
|
|
48
|
+
readonly code: WorkflowErrorCode;
|
|
49
|
+
readonly recoverable: boolean;
|
|
50
|
+
readonly agentLabel?: string;
|
|
51
|
+
readonly details?: unknown;
|
|
52
|
+
/** For PROVIDER_USAGE_LIMIT: the provider's human reset hint, e.g. "Resets in ~3h" (verbatim). */
|
|
53
|
+
readonly resetHint?: string;
|
|
54
|
+
|
|
55
|
+
constructor(
|
|
56
|
+
message: string,
|
|
57
|
+
code: WorkflowErrorCode,
|
|
58
|
+
options: { recoverable?: boolean; agentLabel?: string; details?: unknown; resetHint?: string } = {},
|
|
59
|
+
) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = "WorkflowError";
|
|
62
|
+
this.code = code;
|
|
63
|
+
this.recoverable = options.recoverable ?? false;
|
|
64
|
+
this.agentLabel = options.agentLabel;
|
|
65
|
+
this.details = options.details;
|
|
66
|
+
this.resetHint = options.resetHint;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Narrow an unknown failure to WorkflowError. */
|
|
71
|
+
export function isWorkflowError(error: unknown): error is WorkflowError {
|
|
72
|
+
return error instanceof WorkflowError;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Recognize abort-like Error messages without assuming a provider-specific class. */
|
|
76
|
+
export function isAbortError(error: unknown): boolean {
|
|
77
|
+
if (!(error instanceof Error)) return false;
|
|
78
|
+
return /\babort(?:ed)?\b/i.test(error.message);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Recognize timeout-like errors by name or message. */
|
|
82
|
+
export function isTimeoutError(error: unknown): boolean {
|
|
83
|
+
if (!(error instanceof Error)) return false;
|
|
84
|
+
return /\btimeout\b/i.test(error.message) || error.name === "TimeoutError";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Recognize provider subscription/rate/quota exhaustion separately from run-local limits. */
|
|
88
|
+
export function isProviderUsageLimit(error: unknown): boolean {
|
|
89
|
+
if (!(error instanceof Error)) return false;
|
|
90
|
+
return /(?:rate[ -]?limit|usage[ -]?limit|quota|too many requests|\b429\b|credits? exhausted|insufficient (?:quota|credits)|try again (?:in|after)|reset(?:s)? (?:in|at))/i.test(
|
|
91
|
+
error.message,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function providerResetHint(message: string): string | undefined {
|
|
96
|
+
const match = /((?:resets?|retry|try again)\s+(?:in|after)\s+[^.\n]+)/i.exec(message);
|
|
97
|
+
return match?.[1]?.trim();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Wrap an unknown error into a WorkflowError with appropriate classification.
|
|
102
|
+
*/
|
|
103
|
+
export function wrapError(error: unknown, context?: { agentLabel?: string }): WorkflowError {
|
|
104
|
+
if (isWorkflowError(error)) return error;
|
|
105
|
+
|
|
106
|
+
if (isAbortError(error)) {
|
|
107
|
+
return new WorkflowError(
|
|
108
|
+
error instanceof Error ? error.message : "Workflow was aborted",
|
|
109
|
+
WorkflowErrorCode.WORKFLOW_ABORTED,
|
|
110
|
+
{ recoverable: true },
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (isProviderUsageLimit(error)) {
|
|
115
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
116
|
+
return new WorkflowError(message, WorkflowErrorCode.PROVIDER_USAGE_LIMIT, {
|
|
117
|
+
recoverable: true,
|
|
118
|
+
agentLabel: context?.agentLabel,
|
|
119
|
+
resetHint: providerResetHint(message),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (isTimeoutError(error)) {
|
|
124
|
+
return new WorkflowError(
|
|
125
|
+
error instanceof Error ? error.message : "Agent timed out",
|
|
126
|
+
WorkflowErrorCode.AGENT_TIMEOUT,
|
|
127
|
+
{ recoverable: true, agentLabel: context?.agentLabel },
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return new WorkflowError(
|
|
132
|
+
error instanceof Error ? error.message : String(error),
|
|
133
|
+
WorkflowErrorCode.AGENT_EXECUTION_ERROR,
|
|
134
|
+
{ recoverable: true, agentLabel: context?.agentLabel, details: error },
|
|
135
|
+
);
|
|
136
|
+
}
|