@skastr0/prism-linux-x64 0.5.0 → 0.7.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/bin/prism +2 -2
- package/package.json +3 -3
- package/types/compile/errors.d.ts +57 -79
- package/types/compile/runtime/schema-bridge.d.ts +15 -12
- package/types/errors.d.ts +24 -34
- package/types/index.d.ts +2 -1
- package/types/jev.d.ts +254 -0
- package/types/lowerer-capabilities.d.ts +70 -0
- package/types/prism-home.d.ts +3 -4
- package/types/services/jev.d.ts +131 -0
- package/types/types.d.ts +3 -1
- package/types/workflow-harness-detection.d.ts +5 -8
- package/types/workflow-identity.d.ts +34 -6
- package/types/workflow-runner.d.ts +15 -1
- package/types/workflow-scheduler/cron.d.ts +60 -0
- package/types/workflow-scheduler/errors.d.ts +71 -0
- package/types/workflow-scheduler/schedule.d.ts +61 -0
- package/types/workflow-session.d.ts +36 -19
- package/types/workflow-store.d.ts +142 -7
- package/types/workflows.d.ts +94 -15
|
@@ -128,6 +128,55 @@ export declare const LOWERER_CAPABILITIES: {
|
|
|
128
128
|
};
|
|
129
129
|
};
|
|
130
130
|
};
|
|
131
|
+
readonly opencode2: {
|
|
132
|
+
readonly harness: "opencode2";
|
|
133
|
+
readonly family: "coding-harness";
|
|
134
|
+
readonly workflowWorker: true;
|
|
135
|
+
readonly compile: CompileTargetCapabilities;
|
|
136
|
+
readonly surfaces: {
|
|
137
|
+
readonly pluginBundle: {
|
|
138
|
+
readonly kind: "native-plugin-api";
|
|
139
|
+
readonly path: "<opencode-root>/plugins/prism-generated-<plugin>/";
|
|
140
|
+
readonly summary: "Compile emits an OpenCode plugin using @opencode-ai/plugin APIs (shared home with OpenCode 1.x).";
|
|
141
|
+
};
|
|
142
|
+
readonly rules: {
|
|
143
|
+
readonly kind: "direct-file";
|
|
144
|
+
readonly path: "<opencode-root>/AGENTS.md";
|
|
145
|
+
readonly summary: "Install appends managed sections to the native instructions file.";
|
|
146
|
+
};
|
|
147
|
+
readonly commands: {
|
|
148
|
+
readonly kind: "direct-file";
|
|
149
|
+
readonly path: "<opencode-root>/commands/";
|
|
150
|
+
readonly summary: "Install writes markdown command files.";
|
|
151
|
+
};
|
|
152
|
+
readonly agents: {
|
|
153
|
+
readonly kind: "markdown-file";
|
|
154
|
+
readonly path: "<opencode-root>/agents/";
|
|
155
|
+
readonly summary: "Compile writes OpenCode agent markdown files.";
|
|
156
|
+
};
|
|
157
|
+
readonly skills: {
|
|
158
|
+
readonly kind: "markdown-file";
|
|
159
|
+
readonly path: "<opencode-root>/skills/";
|
|
160
|
+
readonly summary: "Install and compile write Agent Skill folders.";
|
|
161
|
+
};
|
|
162
|
+
readonly generatedTools: {
|
|
163
|
+
readonly kind: "native-plugin-api";
|
|
164
|
+
readonly path: "<generated-plugin>/dist/server.mjs";
|
|
165
|
+
readonly summary: "Canonical tools lower to OpenCode plugin tools.";
|
|
166
|
+
};
|
|
167
|
+
readonly hooks: {
|
|
168
|
+
readonly kind: "native-plugin-api";
|
|
169
|
+
readonly path: "<generated-plugin>/dist/server.mjs";
|
|
170
|
+
readonly summary: "Hooks lower through the OpenCode plugin API.";
|
|
171
|
+
};
|
|
172
|
+
readonly agentConfig: {
|
|
173
|
+
readonly kind: "config-patch";
|
|
174
|
+
readonly path: "<opencode-root>/opencode.json#agent.<name>";
|
|
175
|
+
readonly summary: "Compile patches compiler-owned agent keys and plugin entries.";
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
readonly notes: readonly ["OpenCode 2 shares ~/.config/opencode/ with OpenCode 1.x until they consolidate.", "Detected by the `opencode2` binary on PATH, not by the shared config root.", "coding-harness targets opencode2, not opencode. `--harness opencode` remains for V1.", "Workflow worker is `opencode2` only (PRISM_WORKFLOW_OPENCODE2_BIN). Never falls back to `opencode`."];
|
|
179
|
+
};
|
|
131
180
|
readonly openclaw: {
|
|
132
181
|
readonly harness: "openclaw";
|
|
133
182
|
readonly family: "claw-harness";
|
|
@@ -314,6 +363,27 @@ export declare const LOWERER_CAPABILITIES: {
|
|
|
314
363
|
};
|
|
315
364
|
readonly notes: readonly ["The active Kimi Code target uses ~/.kimi-code exclusively.", "Kimi Code plugins are user-scoped in official docs; Prism keeps project scope unsupported for this lowerer.", "Current Moonshot-hosted Kimi Code CLI docs also document project-local .kimi-code/skills and .kimi-code/mcp.json, but Prism does not mix those direct project surfaces with generated user-scoped plugin bundles yet.", "Kimi Code subagents are runtime dispatches, so Prism compiled agents lower as role skills rather than native subagent definitions."];
|
|
316
365
|
};
|
|
366
|
+
readonly "amp-orb": {
|
|
367
|
+
readonly harness: "amp-orb";
|
|
368
|
+
readonly family: "coding-harness";
|
|
369
|
+
readonly workflowWorker: false;
|
|
370
|
+
readonly compile: CompileTargetCapabilities;
|
|
371
|
+
readonly surfaces: {
|
|
372
|
+
readonly pluginBundle: LowererSurfaceCapability;
|
|
373
|
+
readonly rules: LowererSurfaceCapability;
|
|
374
|
+
readonly commands: LowererSurfaceCapability;
|
|
375
|
+
readonly agents: LowererSurfaceCapability;
|
|
376
|
+
readonly skills: {
|
|
377
|
+
readonly kind: "direct-file";
|
|
378
|
+
readonly path: "<amp-orb-checkout>/<skill>/SKILL.md";
|
|
379
|
+
readonly summary: "Install writes flat text skill directories into an explicit hosted skills checkout.";
|
|
380
|
+
};
|
|
381
|
+
readonly generatedTools: LowererSurfaceCapability;
|
|
382
|
+
readonly hooks: LowererSurfaceCapability;
|
|
383
|
+
readonly agentConfig: LowererSurfaceCapability;
|
|
384
|
+
};
|
|
385
|
+
readonly notes: readonly ["amp-orb is a hosted skills checkout, not a second root for amp-code.", "Family is coding-harness so the type fits. It is not a member of the coding-harness preset and not a workflow worker.", "Publication (clone, commit, push, reload) is outside this target."];
|
|
386
|
+
};
|
|
317
387
|
readonly "amp-code": {
|
|
318
388
|
readonly harness: "amp-code";
|
|
319
389
|
readonly family: "coding-harness";
|
package/types/prism-home.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
export declare const PRISM_CONFIG_SCHEMA_VERSION = 1;
|
|
3
3
|
export declare const DEFAULT_BACKUP_RETENTION_PER_TARGET = 3;
|
|
4
|
-
export declare const BackupModeSchema: Schema.
|
|
4
|
+
export declare const BackupModeSchema: Schema.Literals<readonly ["always", "never"]>;
|
|
5
5
|
export type BackupMode = typeof BackupModeSchema.Type;
|
|
6
6
|
export interface PrismBackupConfig {
|
|
7
7
|
readonly mode: BackupMode;
|
|
@@ -15,7 +15,7 @@ export interface PrismConfig {
|
|
|
15
15
|
* Resolve the Prism home directory from an override or the environment.
|
|
16
16
|
*
|
|
17
17
|
* WS2+: new code must NOT call this from library modules — consume the
|
|
18
|
-
* `PrismHome`
|
|
18
|
+
* `PrismHome` service from src/services/prism-env.ts instead; the env
|
|
19
19
|
* read happens exactly once at the CLI edge layer.
|
|
20
20
|
*/
|
|
21
21
|
export declare const resolvePrismHome: (override?: string) => string;
|
|
@@ -27,8 +27,7 @@ export declare const prismBackupDir: (prismHome?: string) => string;
|
|
|
27
27
|
* Workflows are ephemeral orchestration instruments that reference their
|
|
28
28
|
* target repos by absolute path, so they belong in the home root, never
|
|
29
29
|
* inside (or `git add`-ed into) the project they operate on — see the
|
|
30
|
-
* "
|
|
31
|
-
* `prism workflow scaffold` writes here by default (PQ-176).
|
|
30
|
+
* "Author from the goal" section of the prism workflow-authoring skill.
|
|
32
31
|
*/
|
|
33
32
|
export declare const prismWorkflowsSourceDir: (prismHome?: string) => string;
|
|
34
33
|
export declare const defaultPrismConfig: () => PrismConfig;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JevClient — the Effect service behind first-class Jev (TypeSafe System One)
|
|
3
|
+
* decisions in Prism workflows and Prism tools (GLYPH-JEV-03).
|
|
4
|
+
*
|
|
5
|
+
* One implementation serves both surfaces: the workflow runner's native Jev
|
|
6
|
+
* executor (src/workflow-jev.ts) and the compiled `jev/systemone_ask` tool
|
|
7
|
+
* (~/prism-plugins/jev) call this service; nothing else knows the SDK exists.
|
|
8
|
+
*
|
|
9
|
+
* Design contract:
|
|
10
|
+
* - Credentials and endpoints are captured once, when the layer is built.
|
|
11
|
+
* `JevClientLive` reads TYPESAFE_API_KEY / TYPESAFE_BASE_URL /
|
|
12
|
+
* TYPESAFE_DEFAULT_MODEL; `JevClientWith` takes explicit options and never
|
|
13
|
+
* consults the environment.
|
|
14
|
+
* - The TypeSafeClient is constructed lazily on the first live call, because
|
|
15
|
+
* its constructor throws when the API key is missing. Importing this module,
|
|
16
|
+
* compiling plugins, validating workflows, and replaying cached outputs must
|
|
17
|
+
* never require credentials.
|
|
18
|
+
* - The SDK owns transport retry (408/429/5xx, backoff, Retry-After). Prism
|
|
19
|
+
* adds no second retry layer; `timeoutMs` is per HTTP attempt, matching the
|
|
20
|
+
* SDK.
|
|
21
|
+
* - SDK logging is forced off: SDK debug logs can include request/response
|
|
22
|
+
* bodies, i.e. workflow state. Prism telemetry is the bounded channel.
|
|
23
|
+
* - `APIUserAbortError` maps to Effect interruption (the only abort source is
|
|
24
|
+
* the Effect-provided signal); every other SDK error maps to a tagged
|
|
25
|
+
* `JevError.kind`. Raw SDK errors are never rethrown or serialized — they
|
|
26
|
+
* can carry response bodies.
|
|
27
|
+
* - Pre-flight budget guard: requests estimated above
|
|
28
|
+
* `JEV_TOKEN_REQUEST_TARGET` fail `kind: "request"` with a chunking hint
|
|
29
|
+
* instead of a raw API 400 — agent callers can act on that message.
|
|
30
|
+
*/
|
|
31
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
32
|
+
import { type Fetch as SdkFetch, type RetryPolicy as SdkRetryPolicy } from "@typesafe-ai/sdk";
|
|
33
|
+
import { type JevAnswers, type JevQuestions, type JevRequest, type JevResult, type JevUsage } from "../jev.js";
|
|
34
|
+
export declare const JEV_ERROR_KINDS: readonly ["configuration", "request", "authentication", "permission", "rate-limit", "timeout", "connection", "http", "protocol"];
|
|
35
|
+
/**
|
|
36
|
+
* - `configuration`: missing/invalid client configuration (missing API key).
|
|
37
|
+
* - `request`: the request itself was rejected — local validation, the
|
|
38
|
+
* pre-flight token-budget guard, or API 400/422.
|
|
39
|
+
* - `authentication` / `permission`: API 401/403.
|
|
40
|
+
* - `rate-limit`: API 429 (carries `retryAfterMs` when the server sent one).
|
|
41
|
+
* - `timeout` / `connection`: transport failures after SDK retries exhaust.
|
|
42
|
+
* - `http`: any other non-2xx API error, including exhausted 5xx.
|
|
43
|
+
* - `protocol`: a nominally successful response failed the request-correlated
|
|
44
|
+
* result contract (malformed envelope, answer/key mismatch). Terminal and
|
|
45
|
+
* never repairable by re-asking the model.
|
|
46
|
+
*/
|
|
47
|
+
export type JevErrorKind = (typeof JEV_ERROR_KINDS)[number];
|
|
48
|
+
declare const JevError_base: Schema.Class<JevError, Schema.TaggedStruct<"JevError", {
|
|
49
|
+
readonly kind: Schema.Literals<readonly ["configuration", "request", "authentication", "permission", "rate-limit", "timeout", "connection", "http", "protocol"]>;
|
|
50
|
+
readonly message: Schema.String;
|
|
51
|
+
readonly status: Schema.optionalKey<Schema.Number>;
|
|
52
|
+
readonly retryAfterMs: Schema.optionalKey<Schema.Number>;
|
|
53
|
+
readonly sdkErrorName: Schema.optionalKey<Schema.String>;
|
|
54
|
+
}>, import("effect/Cause").YieldableError>;
|
|
55
|
+
export declare class JevError extends JevError_base {
|
|
56
|
+
}
|
|
57
|
+
/** Replacement text for a scrubbed credential. */
|
|
58
|
+
export declare const JEV_REDACTED_SECRET = "[redacted]";
|
|
59
|
+
/**
|
|
60
|
+
* Redact exact occurrences of each known secret from outward diagnostic text.
|
|
61
|
+
* SDK error messages carry server-provided text verbatim (`APIError.describe`
|
|
62
|
+
* copies the response body's error/message/detail), and an upstream
|
|
63
|
+
* diagnostic can echo the Authorization header back — so every JevError that
|
|
64
|
+
* leaves the service boundary is scrubbed with the configured credential.
|
|
65
|
+
* Secrets shorter than 8 characters are skipped: redacting a tiny needle
|
|
66
|
+
* would mangle prose, and real credentials are never that short.
|
|
67
|
+
*/
|
|
68
|
+
export declare const redactJevSecrets: (text: string, secrets: ReadonlyArray<string | undefined>) => string;
|
|
69
|
+
/** Non-secret resolved configuration, safe for identity hashing and logs. */
|
|
70
|
+
export interface JevPublicConfig {
|
|
71
|
+
readonly baseURL: string;
|
|
72
|
+
readonly defaultModel: string;
|
|
73
|
+
}
|
|
74
|
+
export interface JevCallOptions {
|
|
75
|
+
/** Per-HTTP-attempt timeout override, passed through to the SDK. */
|
|
76
|
+
readonly timeoutMs?: number;
|
|
77
|
+
}
|
|
78
|
+
export interface JevClientShape {
|
|
79
|
+
readonly config: JevPublicConfig;
|
|
80
|
+
readonly systemOne: <const Q extends JevQuestions>(request: JevRequest<Q>, options?: JevCallOptions) => Effect.Effect<JevResult<Q>, JevError>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve the non-secret Jev configuration (base URL + default model) without
|
|
84
|
+
* touching the API key. Identity hashing, workflow snapshots, and the CLI use
|
|
85
|
+
* this so a jev task's cache identity is computable without credentials.
|
|
86
|
+
*/
|
|
87
|
+
export type JevEnvLike = {
|
|
88
|
+
readonly TYPESAFE_BASE_URL?: string | undefined;
|
|
89
|
+
readonly TYPESAFE_DEFAULT_MODEL?: string | undefined;
|
|
90
|
+
readonly [key: string]: string | undefined;
|
|
91
|
+
};
|
|
92
|
+
export declare const resolveJevPublicConfig: (env?: JevEnvLike) => JevPublicConfig;
|
|
93
|
+
declare const JevClient_base: Context.ServiceClass<JevClient, "prism/JevClient", JevClientShape>;
|
|
94
|
+
export declare class JevClient extends JevClient_base {
|
|
95
|
+
}
|
|
96
|
+
export type JevClientService = JevClient["Service"];
|
|
97
|
+
export interface JevClientOptions {
|
|
98
|
+
readonly apiKey?: string;
|
|
99
|
+
readonly baseURL?: string;
|
|
100
|
+
readonly defaultModel?: string;
|
|
101
|
+
readonly fetch?: SdkFetch;
|
|
102
|
+
/** SDK retry override (transport-level only). */
|
|
103
|
+
readonly retry?: Partial<SdkRetryPolicy>;
|
|
104
|
+
/** SDK per-attempt timeout override in milliseconds. */
|
|
105
|
+
readonly timeoutMs?: number;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Live layer: captures the TYPESAFE_* environment once at build; the API key
|
|
109
|
+
* is only required when a live call is made.
|
|
110
|
+
*/
|
|
111
|
+
export declare const JevClientLive: Layer.Layer<JevClient>;
|
|
112
|
+
/**
|
|
113
|
+
* Explicit-config layer; never reads environment variables. Missing optional
|
|
114
|
+
* settings fall back to documented non-secret defaults.
|
|
115
|
+
*/
|
|
116
|
+
export declare const JevClientWith: (options: JevClientOptions) => Layer.Layer<JevClient>;
|
|
117
|
+
export interface JevClientTestOptions {
|
|
118
|
+
readonly model?: string;
|
|
119
|
+
readonly usage?: JevUsage;
|
|
120
|
+
/** Override the public config observed by identity/telemetry code. */
|
|
121
|
+
readonly config?: JevPublicConfig;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Stub layer for tests: answers a registered questions contract from memory.
|
|
125
|
+
* The registered answers are validated at construction against the real
|
|
126
|
+
* result codec, so a malformed stub fails the test that wrote it, not the
|
|
127
|
+
* system under test. Calls with a different questions map fail
|
|
128
|
+
* `kind: "request"`. Never touches network or environment.
|
|
129
|
+
*/
|
|
130
|
+
export declare const JevClientTest: <const Q extends JevQuestions>(questions: Q, answers: JevAnswers<Q>, options?: JevClientTestOptions) => Layer.Layer<JevClient>;
|
|
131
|
+
export {};
|
package/types/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core types for prism - the unified plugin distribution system
|
|
3
3
|
*/
|
|
4
|
-
export type HarnessId = "claude-code" | "opencode" | "openclaw" | "hermes" | "codex-cli" | "antigravity-cli" | "kimi-code" | "amp-code" | "cursor" | "factory-droid" | "pi" | "omp" | "grok" | "devin";
|
|
4
|
+
export type HarnessId = "claude-code" | "opencode" | "opencode2" | "openclaw" | "hermes" | "codex-cli" | "antigravity-cli" | "kimi-code" | "amp-code" | "amp-orb" | "cursor" | "factory-droid" | "pi" | "omp" | "grok" | "devin";
|
|
5
5
|
export declare const HARNESS_SCOPES: readonly ["global", "project"];
|
|
6
6
|
export type HarnessScope = (typeof HARNESS_SCOPES)[number];
|
|
7
7
|
export interface HarnessConfig {
|
|
@@ -139,12 +139,14 @@ export interface UnifiedFrontmatter {
|
|
|
139
139
|
description?: string;
|
|
140
140
|
"claude-code"?: ClaudeCodeFrontmatter;
|
|
141
141
|
opencode?: OpenCodeAgentFrontmatter;
|
|
142
|
+
opencode2?: OpenCodeAgentFrontmatter;
|
|
142
143
|
openclaw?: Record<string, unknown>;
|
|
143
144
|
hermes?: Record<string, unknown>;
|
|
144
145
|
"codex-cli"?: CodexCliFrontmatter;
|
|
145
146
|
"antigravity-cli"?: Record<string, unknown>;
|
|
146
147
|
"kimi-code"?: Record<string, unknown>;
|
|
147
148
|
"amp-code"?: Record<string, unknown>;
|
|
149
|
+
"amp-orb"?: Record<string, unknown>;
|
|
148
150
|
cursor?: CursorFrontmatter;
|
|
149
151
|
"factory-droid"?: FactoryDroidFrontmatter;
|
|
150
152
|
pi?: Record<string, unknown>;
|
|
@@ -35,11 +35,9 @@ export interface WorkflowHarnessDetectionSpec {
|
|
|
35
35
|
readonly envVar: string;
|
|
36
36
|
readonly probeArgs: ReadonlyArray<string>;
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* profiles (not the premium tier) so a scaffolded workflow never crashes at
|
|
42
|
-
* run with "no concrete model for workflow worker X".
|
|
38
|
+
* Documented cheap-fast slug for this harness. Detection/probes may cite it.
|
|
39
|
+
* Unpinned workflow tasks must omit the harness model flag so the user's
|
|
40
|
+
* harness default stays in force — do not feed this into spawn.
|
|
43
41
|
*/
|
|
44
42
|
readonly defaultModel: string;
|
|
45
43
|
/**
|
|
@@ -81,9 +79,8 @@ export interface WorkflowHarnessDetectionOptions {
|
|
|
81
79
|
export declare const WORKFLOW_HARNESS_DETECTION_SPECS: Readonly<Record<WorkflowHarnessId, WorkflowHarnessDetectionSpec>>;
|
|
82
80
|
export declare const isWorkflowHarnessId: (id: string) => id is WorkflowHarnessId;
|
|
83
81
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* (src/workflows.ts) — do not hand-maintain a second per-harness default list.
|
|
82
|
+
* Documented cheap-fast slug for a workflow harness, or `undefined` outside
|
|
83
|
+
* the registry. Not applied to unpinned tasks — omit the spawn flag instead.
|
|
87
84
|
*/
|
|
88
85
|
export declare const workflowHarnessDefaultModel: (harness: string) => string | undefined;
|
|
89
86
|
/** Provider paired with `workflowHarnessDefaultModel` for provider-multiplexing harnesses (hermes). */
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type AnyWorkflowTask, type WorkflowSessionPersistence, type WorkflowRuntimeOptions } from "./workflows.js";
|
|
2
|
+
import { type JevQuestions, type JevEntry } from "./jev.js";
|
|
3
|
+
import type { JevPublicConfig } from "./services/jev.js";
|
|
2
4
|
/**
|
|
3
5
|
* `cacheKey` and `promptHash` AND together in the cache primary key
|
|
4
6
|
* (workflow-store.ts) — `cacheKey` never substitutes for `promptHash`, and
|
|
@@ -24,29 +26,55 @@ export interface WorkflowJudgeIdentity {
|
|
|
24
26
|
readonly criterion: string;
|
|
25
27
|
readonly cacheKey: string;
|
|
26
28
|
}
|
|
27
|
-
|
|
29
|
+
interface WorkflowRunTaskSnapshotBase {
|
|
28
30
|
readonly runId: string;
|
|
29
31
|
readonly ordinal: number;
|
|
30
32
|
readonly taskId: string;
|
|
31
33
|
readonly phase?: string;
|
|
32
|
-
readonly prompt: string;
|
|
33
34
|
readonly cacheKey: string;
|
|
34
35
|
readonly promptHash: string;
|
|
36
|
+
readonly outputSchema?: unknown;
|
|
37
|
+
readonly createdAt: string;
|
|
38
|
+
}
|
|
39
|
+
export interface WorkflowWorkerRunTaskSnapshot extends WorkflowRunTaskSnapshotBase {
|
|
40
|
+
readonly kind: "workflow-task";
|
|
41
|
+
readonly prompt: string;
|
|
35
42
|
readonly worker?: {
|
|
36
43
|
readonly worker?: string;
|
|
37
44
|
readonly model?: string;
|
|
38
45
|
readonly profile?: string;
|
|
39
46
|
readonly sessionPersistence?: WorkflowSessionPersistence;
|
|
40
47
|
};
|
|
41
|
-
readonly outputSchema?: unknown;
|
|
42
48
|
readonly finishCriteria: ReadonlyArray<string>;
|
|
43
|
-
readonly createdAt: string;
|
|
44
49
|
}
|
|
45
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Persisted record of one native Jev decision: the exact request that was
|
|
52
|
+
* identity-hashed and executed, with the effective (non-secret) endpoint and
|
|
53
|
+
* model. Never contains the API key.
|
|
54
|
+
*/
|
|
55
|
+
export interface JevRunTaskSnapshot extends WorkflowRunTaskSnapshotBase {
|
|
56
|
+
readonly kind: "jev";
|
|
57
|
+
readonly request: {
|
|
58
|
+
readonly state: JevEntry;
|
|
59
|
+
readonly questions: JevQuestions;
|
|
60
|
+
readonly model: string;
|
|
61
|
+
readonly baseURL: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export type WorkflowRunTaskSnapshot = WorkflowWorkerRunTaskSnapshot | JevRunTaskSnapshot;
|
|
65
|
+
/**
|
|
66
|
+
* Distributive snapshot-input union. Plain `Omit<Union, "createdAt">` would
|
|
67
|
+
* collapse variant-specific properties (`prompt`, `request`), so each
|
|
68
|
+
* variant's input form is spelled out.
|
|
69
|
+
*/
|
|
70
|
+
export type WorkflowRunTaskSnapshotInput = Omit<WorkflowWorkerRunTaskSnapshot, "createdAt"> | Omit<JevRunTaskSnapshot, "createdAt">;
|
|
71
|
+
export declare const workflowTaskIdentity: (workflow: string, task: AnyWorkflowTask, runtimeOptions?: WorkflowRuntimeOptions, jev?: JevPublicConfig) => WorkflowTaskIdentity;
|
|
46
72
|
export declare const workflowRunTaskSnapshotForTask: (input: {
|
|
47
73
|
readonly runId: string;
|
|
48
74
|
readonly ordinal: number;
|
|
49
75
|
readonly workflow: string;
|
|
50
76
|
readonly task: AnyWorkflowTask;
|
|
51
77
|
readonly runtimeOptions?: WorkflowRuntimeOptions;
|
|
52
|
-
|
|
78
|
+
readonly jev?: JevPublicConfig;
|
|
79
|
+
}) => WorkflowRunTaskSnapshotInput;
|
|
80
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type AnyWorkflowDefinition, type AnyWorkflowTask, type WorkflowRuntimeOptions } from "./workflows.js";
|
|
1
|
+
import { type AnyWorkflowDefinition, type AnyWorkflowTask, type AnyWorkflowWorkerTask, type WorkflowRuntimeOptions } from "./workflows.js";
|
|
2
|
+
import type { JevPublicConfig } from "./services/jev.js";
|
|
2
3
|
import type { WorkflowStore } from "./workflow-store.js";
|
|
3
4
|
import { type WorkflowRepairLoopContinuationWorkerId, type WorkflowStableSession } from "./workflow-session.js";
|
|
4
5
|
export interface WorkflowTaskExecution {
|
|
@@ -55,6 +56,12 @@ export type WorkflowTaskRepairLoopOption<Worker extends string> = Worker extends
|
|
|
55
56
|
readonly repair?: never;
|
|
56
57
|
};
|
|
57
58
|
export type WorkflowTaskExecutor = (task: AnyWorkflowTask, context?: WorkflowTaskExecutionContext) => Promise<unknown | WorkflowTaskExecution>;
|
|
59
|
+
/**
|
|
60
|
+
* The worker-shaped half of {@link WorkflowTaskExecutor}: worker adapters and
|
|
61
|
+
* the mock-output path only ever receive workflow worker tasks. Jev tasks are
|
|
62
|
+
* dispatched separately by kind (see workflow-executors.ts).
|
|
63
|
+
*/
|
|
64
|
+
export type WorkflowWorkerTaskExecutor = (task: AnyWorkflowWorkerTask, context?: WorkflowTaskExecutionContext) => Promise<unknown | WorkflowTaskExecution>;
|
|
58
65
|
/**
|
|
59
66
|
* Internal scheduler pacing, not a budget: excess live tasks queue and run as
|
|
60
67
|
* slots free, so this never fails a task. Sized to the machine because each
|
|
@@ -62,11 +69,18 @@ export type WorkflowTaskExecutor = (task: AnyWorkflowTask, context?: WorkflowTas
|
|
|
62
69
|
* about a workflow's intent belongs in this number.
|
|
63
70
|
*/
|
|
64
71
|
export declare const WORKFLOW_TASK_CONCURRENCY: number;
|
|
72
|
+
/**
|
|
73
|
+
* Jev tasks are one HTTP call (not a harness process), so they run on a
|
|
74
|
+
* separate, wider run-scoped limiter than worker tasks. Same semantics: queue,
|
|
75
|
+
* never fail.
|
|
76
|
+
*/
|
|
77
|
+
export declare const WORKFLOW_JEV_CONCURRENCY = 32;
|
|
65
78
|
export declare const runWorkflow: (workflow: AnyWorkflowDefinition, options: {
|
|
66
79
|
readonly executeTask: WorkflowTaskExecutor;
|
|
67
80
|
readonly store?: WorkflowStore;
|
|
68
81
|
readonly mockOutput?: boolean;
|
|
69
82
|
readonly runId?: string;
|
|
70
83
|
readonly runtimeOptions?: WorkflowRuntimeOptions;
|
|
84
|
+
readonly jev?: JevPublicConfig;
|
|
71
85
|
readonly abortSignal?: AbortSignal;
|
|
72
86
|
}) => Promise<WorkflowRunResult>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect's `Cron` module, narrowed to Prism's scheduling dialect.
|
|
3
|
+
*
|
|
4
|
+
* Prism ships no cron parser. `effect`'s `Cron` already implements the
|
|
5
|
+
* five-field dialect Prism documents — names, ranges, steps, lists, Vixie
|
|
6
|
+
* DOM/DOW OR semantics, named timezones, and DST resolution — and it is
|
|
7
|
+
* already a Prism-owned dependency pinned to one exact release by
|
|
8
|
+
* `scripts/effect-version-guard.ts`. Re-deriving a parser here would be a
|
|
9
|
+
* second implementation of the same contract, which AGENTS.md rule 3 forbids.
|
|
10
|
+
*
|
|
11
|
+
* This module is the adapter that *pins the dialect Prism accepts*, so the
|
|
12
|
+
* accepted language lives in one place instead of being whatever the
|
|
13
|
+
* dependency happens to accept today. Two deliberate narrowings, both
|
|
14
|
+
* fail-closed:
|
|
15
|
+
*
|
|
16
|
+
* - **Exactly five fields.** `Cron.parse` also accepts a six-field,
|
|
17
|
+
* seconds-first form. A six-field expression is rejected so an expression
|
|
18
|
+
* copied from a seconds-capable scheduler cannot silently mean something
|
|
19
|
+
* else than it reads.
|
|
20
|
+
* - **Named timezones only.** `Cron.parse` accepts fixed offsets such as
|
|
21
|
+
* `+03:00`. A fixed offset is not DST-aware, so a schedule declared with
|
|
22
|
+
* one drifts by an hour at a transition. A named IANA zone — including the
|
|
23
|
+
* DST-free `Etc/GMT+3` — is required.
|
|
24
|
+
*
|
|
25
|
+
* DST policy is inherited from `effect`'s `Cron` and pinned by `cron.test.ts`:
|
|
26
|
+
* a wall-clock time inside a spring-forward gap resolves to the first valid
|
|
27
|
+
* instant after the gap, and a time inside a fall-back fold resolves to the
|
|
28
|
+
* **first** of the two occurrences. That is a documented policy, not an
|
|
29
|
+
* accident of the dependency, so the tests assert it rather than assume it.
|
|
30
|
+
*
|
|
31
|
+
* Only `next` is exposed. Prism never asks "what was the previous occurrence?"
|
|
32
|
+
* because the durable cursor is the schedule row's `next_due_at` — see
|
|
33
|
+
* `docs/workflow-scheduling.md`. `Cron.prev` is also subtly exclusive at exact
|
|
34
|
+
* minute boundaries, which makes it the wrong primitive for "the occurrence
|
|
35
|
+
* that is due now".
|
|
36
|
+
*/
|
|
37
|
+
import { Cron } from "effect";
|
|
38
|
+
/** The field count Prism accepts. Six-field (seconds-first) expressions are rejected. */
|
|
39
|
+
export declare const WORKFLOW_CRON_FIELD_COUNT = 5;
|
|
40
|
+
export interface ParsedWorkflowCron {
|
|
41
|
+
readonly expression: string;
|
|
42
|
+
readonly timezone: string;
|
|
43
|
+
/** The parsed `effect` `Cron`, ready for `Cron.next`. */
|
|
44
|
+
readonly cron: Cron.Cron;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate a cron expression + timezone pair, returning the parsed schedule.
|
|
48
|
+
*
|
|
49
|
+
* Throws `WorkflowScheduleError` — never a bare string or a dependency's error
|
|
50
|
+
* type — so every rejection carries the field, a headline, and the exact fix.
|
|
51
|
+
*/
|
|
52
|
+
export declare const parseWorkflowCron: (expression: string, timezone: string) => ParsedWorkflowCron;
|
|
53
|
+
/**
|
|
54
|
+
* The first occurrence strictly after `afterMs`.
|
|
55
|
+
*
|
|
56
|
+
* `Cron.next` is exclusive of its argument, which is what the tick algorithm
|
|
57
|
+
* needs: advancing the cursor from a consumed occurrence must never re-yield
|
|
58
|
+
* that same occurrence.
|
|
59
|
+
*/
|
|
60
|
+
export declare const nextWorkflowCronOccurrence: (schedule: ParsedWorkflowCron, afterMs: number) => number;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler error vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* These are `Schema.TaggedError`s rather than plain `Error`s for two reasons:
|
|
5
|
+
* every one of them is both a typed Effect failure *and* a durable record (a
|
|
6
|
+
* scheduler event, an execution's `cause_json`), and `message` is an explicit
|
|
7
|
+
* schema field so the rendered headline survives a round trip through SQLite.
|
|
8
|
+
* `Schema.TaggedError`'s optional third-argument message function is not used
|
|
9
|
+
* because it does not take effect in this Effect release; carrying `message`
|
|
10
|
+
* as a field keeps the rendered text identical before and after persistence.
|
|
11
|
+
*
|
|
12
|
+
* `hint` is required, never optional: AGENTS.md rule 6 forbids warnings, so a
|
|
13
|
+
* failure that cannot name its own remediation does not belong here.
|
|
14
|
+
*/
|
|
15
|
+
import { Schema } from "effect";
|
|
16
|
+
declare const WorkflowScheduleError_base: Schema.Class<WorkflowScheduleError, Schema.TaggedStruct<"WorkflowScheduleError", {
|
|
17
|
+
readonly message: Schema.String;
|
|
18
|
+
readonly field: Schema.String;
|
|
19
|
+
readonly hint: Schema.String;
|
|
20
|
+
}>, import("effect/Cause").YieldableError>;
|
|
21
|
+
/** A declared schedule that Prism cannot accept. `field` is the offending key. */
|
|
22
|
+
export declare class WorkflowScheduleError extends WorkflowScheduleError_base {
|
|
23
|
+
}
|
|
24
|
+
declare const WorkflowScheduleInstallError_base: Schema.Class<WorkflowScheduleInstallError, Schema.TaggedStruct<"WorkflowScheduleInstallError", {
|
|
25
|
+
readonly message: Schema.String;
|
|
26
|
+
readonly hint: Schema.String;
|
|
27
|
+
}>, import("effect/Cause").YieldableError>;
|
|
28
|
+
/** A schedule installation or lifecycle operation Prism refuses to perform. */
|
|
29
|
+
export declare class WorkflowScheduleInstallError extends WorkflowScheduleInstallError_base {
|
|
30
|
+
}
|
|
31
|
+
declare const SchedulerStoreError_base: Schema.Class<SchedulerStoreError, Schema.TaggedStruct<"SchedulerStoreError", {
|
|
32
|
+
readonly message: Schema.String;
|
|
33
|
+
readonly hint: Schema.String;
|
|
34
|
+
readonly path: Schema.String;
|
|
35
|
+
}>, import("effect/Cause").YieldableError>;
|
|
36
|
+
/** The scheduler store could not be opened, migrated, or read as expected. */
|
|
37
|
+
export declare class SchedulerStoreError extends SchedulerStoreError_base {
|
|
38
|
+
}
|
|
39
|
+
declare const SchedulerAlreadyRunningError_base: Schema.Class<SchedulerAlreadyRunningError, Schema.TaggedStruct<"SchedulerAlreadyRunningError", {
|
|
40
|
+
readonly message: Schema.String;
|
|
41
|
+
readonly hint: Schema.String;
|
|
42
|
+
readonly holderInstanceId: Schema.NullOr<Schema.String>;
|
|
43
|
+
readonly holderPid: Schema.NullOr<Schema.Number>;
|
|
44
|
+
}>, import("effect/Cause").YieldableError>;
|
|
45
|
+
/** Another scheduler instance holds the machine-wide instance lock. */
|
|
46
|
+
export declare class SchedulerAlreadyRunningError extends SchedulerAlreadyRunningError_base {
|
|
47
|
+
}
|
|
48
|
+
declare const SchedulerLaunchError_base: Schema.Class<SchedulerLaunchError, Schema.TaggedStruct<"SchedulerLaunchError", {
|
|
49
|
+
readonly message: Schema.String;
|
|
50
|
+
readonly hint: Schema.String;
|
|
51
|
+
readonly executionId: Schema.String;
|
|
52
|
+
}>, import("effect/Cause").YieldableError>;
|
|
53
|
+
/** A worker process could not be launched, or its launch could not be authorized. */
|
|
54
|
+
export declare class SchedulerLaunchError extends SchedulerLaunchError_base {
|
|
55
|
+
}
|
|
56
|
+
declare const SchedulerFatalError_base: Schema.Class<SchedulerFatalError, Schema.TaggedStruct<"SchedulerFatalError", {
|
|
57
|
+
readonly message: Schema.String;
|
|
58
|
+
readonly hint: Schema.String;
|
|
59
|
+
}>, import("effect/Cause").YieldableError>;
|
|
60
|
+
/**
|
|
61
|
+
* The scheduler loop itself hit an unrecoverable defect. The owner's contract
|
|
62
|
+
* is explicit that a scheduler defect must surface and end the process so the
|
|
63
|
+
* service manager restarts it — never be swallowed into an endlessly
|
|
64
|
+
* "healthy"-looking loop.
|
|
65
|
+
*/
|
|
66
|
+
export declare class SchedulerFatalError extends SchedulerFatalError_base {
|
|
67
|
+
}
|
|
68
|
+
export type SchedulerError = WorkflowScheduleError | WorkflowScheduleInstallError | SchedulerStoreError | SchedulerAlreadyRunningError | SchedulerLaunchError | SchedulerFatalError;
|
|
69
|
+
/** One-line headline plus a `hint:` line — the repo's human error shape. */
|
|
70
|
+
export declare const renderSchedulerError: (error: SchedulerError) => string;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inert `schedule` declaration on a workflow definition.
|
|
3
|
+
*
|
|
4
|
+
* A workflow may declare how it wants to be scheduled; declaring it does
|
|
5
|
+
* nothing. `defineWorkflow` records the policy on the definition object and
|
|
6
|
+
* no more — importing, typechecking, validating, or running the file has no
|
|
7
|
+
* scheduling side effect whatsoever. Registration happens only through
|
|
8
|
+
* `prism workflow schedule install`, which reads the declaration back out of
|
|
9
|
+
* the loaded definition. This split is what makes `install` the single
|
|
10
|
+
* activation gate, and it is why a schedule edit requires a reinstall while a
|
|
11
|
+
* task/prompt edit does not.
|
|
12
|
+
*
|
|
13
|
+
* **Only implemented policies are representable.** `overlap` and `missedRuns`
|
|
14
|
+
* each admit exactly one value, so `overlap: "queue"` is a TypeScript error at
|
|
15
|
+
* authoring time and a hard, self-explaining `WorkflowScheduleError` at the
|
|
16
|
+
* cross-version boundary. AGENTS.md rule 6 forbids warnings, and rule 8 says a
|
|
17
|
+
* type that needs a runtime membership check is lying — so the unions stay
|
|
18
|
+
* closed rather than admitting a policy Prism does not implement.
|
|
19
|
+
*
|
|
20
|
+
* The two policies, stated precisely, because both names are easy to misread:
|
|
21
|
+
*
|
|
22
|
+
* - `overlap: "skip"` — at most one unresolved execution per schedule. A due
|
|
23
|
+
* occurrence that arrives while the previous execution is still running,
|
|
24
|
+
* still reserving, or still *uncertain* is consumed as a skip and
|
|
25
|
+
* recorded; it is never queued and never run in parallel. A stranded
|
|
26
|
+
* execution cannot be cleared by a timeout, only by evidence.
|
|
27
|
+
* - `missedRuns: "skip"` — overdue occurrences are coalesced into at most one
|
|
28
|
+
* opportunity. A machine asleep for three hours produces one run on wake, not
|
|
29
|
+
* eighteen, and a scheduler restart behaves the same way rather than silently
|
|
30
|
+
* swallowing an occurrence. Nothing accumulates: the cursor advances whether
|
|
31
|
+
* or not the run succeeds, so a crash-loop fires at most once per occurrence.
|
|
32
|
+
*/
|
|
33
|
+
/** Policies Prism implements for a due occurrence that overlaps a live execution. */
|
|
34
|
+
export declare const WORKFLOW_SCHEDULE_OVERLAP_POLICIES: readonly ["skip"];
|
|
35
|
+
export type WorkflowScheduleOverlap = (typeof WORKFLOW_SCHEDULE_OVERLAP_POLICIES)[number];
|
|
36
|
+
/** Policies Prism implements for occurrences that passed while nothing was watching. */
|
|
37
|
+
export declare const WORKFLOW_SCHEDULE_MISSED_RUN_POLICIES: readonly ["skip"];
|
|
38
|
+
export type WorkflowScheduleMissedRuns = (typeof WORKFLOW_SCHEDULE_MISSED_RUN_POLICIES)[number];
|
|
39
|
+
export interface WorkflowSchedule {
|
|
40
|
+
/** Five-field cron: `minute hour day-of-month month day-of-week`. */
|
|
41
|
+
readonly cron: string;
|
|
42
|
+
/** A named IANA timezone. Fixed UTC offsets are rejected; see `cron.ts`. */
|
|
43
|
+
readonly timezone: string;
|
|
44
|
+
readonly overlap: WorkflowScheduleOverlap;
|
|
45
|
+
readonly missedRuns: WorkflowScheduleMissedRuns;
|
|
46
|
+
}
|
|
47
|
+
/** The complete key set. An unrecognized key is an error, not an ignored field. */
|
|
48
|
+
export declare const WORKFLOW_SCHEDULE_KEYS: ReadonlyArray<keyof WorkflowSchedule>;
|
|
49
|
+
/**
|
|
50
|
+
* Validate an already-loaded `schedule` value and return it typed.
|
|
51
|
+
*
|
|
52
|
+
* Used twice on purpose: `defineWorkflow` calls it so an authoring mistake
|
|
53
|
+
* fails at import with the file in front of the author, and
|
|
54
|
+
* `prism workflow schedule install` calls it again because an installed
|
|
55
|
+
* schedule is data that crossed a boundary (a hand-written object, or a
|
|
56
|
+
* definition produced by a different Prism version) and must not be trusted
|
|
57
|
+
* just because some other layer once checked it.
|
|
58
|
+
*/
|
|
59
|
+
export declare const parseWorkflowSchedule: (value: unknown) => WorkflowSchedule;
|
|
60
|
+
/** Non-throwing form for the `isWorkflowDefinition` type guard. */
|
|
61
|
+
export declare const isWorkflowSchedule: (value: unknown) => value is WorkflowSchedule;
|