pi-extensible-workflows 1.0.0 → 1.0.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/dist/src/agent-execution.js +47 -7
- package/dist/src/ambient-workflow-evals.js +14 -33
- package/dist/src/doctor.js +3 -5
- package/dist/src/index.d.ts +7 -4
- package/dist/src/index.js +176 -117
- package/dist/src/persistence.d.ts +2 -0
- package/dist/src/persistence.js +27 -4
- package/dist/src/workflow-evals.d.ts +1 -0
- package/dist/src/workflow-evals.js +23 -25
- package/package.json +5 -2
- package/skills/pi-extensible-workflows/SKILL.md +6 -2
- package/src/agent-execution.ts +45 -7
- package/src/ambient-workflow-evals.ts +18 -28
- package/src/doctor.ts +2 -5
- package/src/index.ts +145 -79
- package/src/persistence.ts +23 -4
- package/src/workflow-evals.ts +13 -16
|
@@ -120,6 +120,43 @@ export async function createNativeAgentSession(input) {
|
|
|
120
120
|
}
|
|
121
121
|
function changedOption(options, baseline, key) { return JSON.stringify(options[key]) !== JSON.stringify(baseline[key]); }
|
|
122
122
|
function validThinking(value) { return typeof value === "string" && ["off", "minimal", "low", "medium", "high", "xhigh", "max"].includes(value); }
|
|
123
|
+
function jsonValue(value, seen = new Set()) {
|
|
124
|
+
if (value === null || typeof value === "boolean" || typeof value === "string")
|
|
125
|
+
return true;
|
|
126
|
+
if (typeof value === "number")
|
|
127
|
+
return Number.isFinite(value);
|
|
128
|
+
if (typeof value !== "object" || seen.has(value))
|
|
129
|
+
return false;
|
|
130
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
|
|
131
|
+
return false;
|
|
132
|
+
const keys = Reflect.ownKeys(value);
|
|
133
|
+
if (keys.some((key) => typeof key !== "string"))
|
|
134
|
+
return false;
|
|
135
|
+
seen.add(value);
|
|
136
|
+
const valid = (Array.isArray(value) ? Array.from(value) : keys.map((key) => value[key])).every((item) => jsonValue(item, seen));
|
|
137
|
+
seen.delete(value);
|
|
138
|
+
return valid;
|
|
139
|
+
}
|
|
140
|
+
function jsonObject(value) { return jsonValue(value) && typeof value === "object" && value !== null && !Array.isArray(value); }
|
|
141
|
+
function isChildAgentToolParams(value) {
|
|
142
|
+
if (!jsonObject(value) || typeof value.prompt !== "string" || typeof value.label !== "string")
|
|
143
|
+
return false;
|
|
144
|
+
if (value.tools !== undefined && (!Array.isArray(value.tools) || value.tools.some((tool) => typeof tool !== "string")))
|
|
145
|
+
return false;
|
|
146
|
+
if (value.model !== undefined && typeof value.model !== "string")
|
|
147
|
+
return false;
|
|
148
|
+
if (value.thinking !== undefined && !validThinking(value.thinking))
|
|
149
|
+
return false;
|
|
150
|
+
if (value.role !== undefined && typeof value.role !== "string")
|
|
151
|
+
return false;
|
|
152
|
+
if (value.outputSchema !== undefined && !jsonObject(value.outputSchema))
|
|
153
|
+
return false;
|
|
154
|
+
if (value.retries !== undefined && (typeof value.retries !== "number" || !Number.isInteger(value.retries) || value.retries < 0))
|
|
155
|
+
return false;
|
|
156
|
+
if (value.timeoutMs !== undefined && (value.timeoutMs !== null && (typeof value.timeoutMs !== "number" || !Number.isInteger(value.timeoutMs) || value.timeoutMs < 1)))
|
|
157
|
+
return false;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
123
160
|
function fallbackSetupContext(root, options, signal) {
|
|
124
161
|
const identity = options.agentIdentity ?? { structuralPath: [], callSite: options.label, occurrence: 1 };
|
|
125
162
|
const run = root.runContext ?? Object.freeze({ cwd: root.cwd, sessionId: "", runId: "", workflow: Object.freeze({ name: options.workflowName }), args: null, signal });
|
|
@@ -686,7 +723,6 @@ export class FairAgentScheduler {
|
|
|
686
723
|
if (nodes.every(({ restored }) => restored))
|
|
687
724
|
run.logical = 0;
|
|
688
725
|
}
|
|
689
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-argument, @typescript-eslint/restrict-template-expressions */
|
|
690
726
|
toolsFor(parentId, resolveTools) {
|
|
691
727
|
const parent = this.#node(parentId);
|
|
692
728
|
if (!parent.options.tools.includes("agent"))
|
|
@@ -694,11 +730,15 @@ export class FairAgentScheduler {
|
|
|
694
730
|
const agentTool = {
|
|
695
731
|
name: "agent", label: "Child Agent", description: "Start a direct child agent",
|
|
696
732
|
parameters: Type.Object({ prompt: Type.String(), label: Type.String(), tools: Type.Optional(Type.Array(Type.String())), model: Type.Optional(Type.String()), thinking: Type.Optional(Type.String()), role: Type.Optional(Type.String()), outputSchema: Type.Optional(Type.Unsafe({})), retries: Type.Optional(Type.Integer({ minimum: 0 })), timeoutMs: Type.Optional(Type.Union([Type.Integer({ minimum: 1 }), Type.Null()])) }, { additionalProperties: true }),
|
|
697
|
-
execute: async (_id,
|
|
733
|
+
execute: async (_id, rawParams) => {
|
|
734
|
+
if (!isChildAgentToolParams(rawParams))
|
|
735
|
+
throw new WorkflowError("INVALID_METADATA", "Invalid child agent parameters");
|
|
736
|
+
const params = rawParams;
|
|
698
737
|
if (params.role !== undefined && (params.model !== undefined || params.thinking !== undefined || params.tools !== undefined))
|
|
699
738
|
throw new WorkflowError("INVALID_METADATA", "Role agents must not specify model, thinking, or tools");
|
|
700
739
|
const tools = (params.tools !== undefined || params.role !== undefined ? resolveTools?.(params.role, params.tools, params.model, parent.options.tools, params.thinking) : undefined) ?? params.tools ?? parent.options.tools;
|
|
701
|
-
const agentOptions =
|
|
740
|
+
const agentOptions = { ...params };
|
|
741
|
+
Reflect.deleteProperty(agentOptions, "prompt");
|
|
702
742
|
const options = { label: params.label, requestedLabel: params.label, cwd: parent.options.cwd, tools, agentOptions, ...(params.model ? { model: params.model } : {}), ...(params.thinking ? { thinking: params.thinking } : {}), ...(params.role ? { role: params.role } : {}), ...(params.outputSchema ? { schema: params.outputSchema } : {}), ...(params.retries === undefined ? {} : { retries: params.retries }), ...(params.timeoutMs === undefined ? {} : { timeoutMs: params.timeoutMs }) };
|
|
703
743
|
const child = this.spawn(parent.runId, params.prompt, options, parentId);
|
|
704
744
|
return { content: [{ type: "text", text: JSON.stringify({ id: child.id }) }], details: { id: child.id } };
|
|
@@ -745,17 +785,17 @@ export class FairAgentScheduler {
|
|
|
745
785
|
#inherit(parent, options) {
|
|
746
786
|
if (!options.label.trim() || !options.cwd || !Array.isArray(options.tools))
|
|
747
787
|
throw new WorkflowError("INVALID_METADATA", "Agents require label, cwd, and tools");
|
|
788
|
+
const inheritedTools = options.tools;
|
|
748
789
|
if (!parent)
|
|
749
|
-
return Object.freeze({ ...options, tools: Object.freeze([...
|
|
790
|
+
return Object.freeze({ ...options, tools: Object.freeze([...inheritedTools]), ...(options.agentOptions ? { agentOptions: structuredClone(options.agentOptions) } : {}), ...(options.agentIdentity ? { agentIdentity: Object.freeze({ ...options.agentIdentity, structuralPath: Object.freeze([...options.agentIdentity.structuralPath]) }) } : {}) });
|
|
750
791
|
if (options.cwd !== parent.options.cwd)
|
|
751
792
|
throw new WorkflowError("UNKNOWN_TOOL", "Child cwd cannot differ from its parent");
|
|
752
|
-
const forbidden =
|
|
793
|
+
const forbidden = inheritedTools.find((tool) => !parent.options.tools.includes(tool));
|
|
753
794
|
if (forbidden)
|
|
754
795
|
throw new WorkflowError("UNKNOWN_TOOL", `Child tool escalates parent boundary: ${forbidden}`);
|
|
755
796
|
const identity = options.agentIdentity ?? parent.options.agentIdentity;
|
|
756
|
-
return Object.freeze({ ...options, cwd: parent.options.cwd, tools: Object.freeze([...
|
|
797
|
+
return Object.freeze({ ...options, cwd: parent.options.cwd, tools: Object.freeze([...inheritedTools]), ...(options.agentOptions ? { agentOptions: structuredClone(options.agentOptions) } : {}), ...(parent.options.parentBreadcrumb && !options.parentBreadcrumb ? { parentBreadcrumb: parent.options.parentBreadcrumb } : {}), ...(identity ? { agentIdentity: Object.freeze({ ...identity, structuralPath: Object.freeze([...identity.structuralPath]) }) } : {}), ...(parent.options.worktreeOwner ? { worktreeOwner: parent.options.worktreeOwner } : {}) });
|
|
757
798
|
}
|
|
758
|
-
/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-argument, @typescript-eslint/restrict-template-expressions */
|
|
759
799
|
#enqueue(runId, node, start) { this.#runs.get(runId)?.queue.push({ ...(node ? { node } : {}), start }); this.#dispatch(); }
|
|
760
800
|
#dispatch() {
|
|
761
801
|
while (this.#active < this.sessionLimit && this.#runOrder.length) {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
-
import { existsSync, mkdirSync, mkdtempSync,
|
|
4
|
+
import { existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { homedir, tmpdir } from "node:os";
|
|
6
6
|
import { join, relative } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { CAPTURE_IDENTITY } from "./eval-capture-extension.js";
|
|
9
|
-
import {
|
|
9
|
+
import { isObject } from "./index.js";
|
|
10
|
+
import { extractCapturedWorkflows, extractParentOracleFile, findSessionFile } from "./workflow-evals.js";
|
|
10
11
|
export const AMBIENT_OPT_IN = "PI_WORKFLOW_EVAL_AMBIENT";
|
|
11
12
|
export const AMBIENT_CAPTURE_NOTE = "Ambient Tier D uses the explicit capture extension. Pi 0.80.6 orders CLI extensions before discovered extensions and the first tool registration wins, so ambient tools and skills remain available while workflow execution stays capture-only.";
|
|
12
13
|
export const AMBIENT_INVOCATION_MODE = "ambient-capture-only";
|
|
@@ -234,34 +235,12 @@ function emptyAccounting() {
|
|
|
234
235
|
function ambientAgentDir(environment) {
|
|
235
236
|
return environment.PI_CODING_AGENT_DIR ?? process.env.PI_CODING_AGENT_DIR ?? join(homedir(), ".pi", "agent");
|
|
236
237
|
}
|
|
237
|
-
function isObject(value) { return typeof value === "object" && value !== null && !Array.isArray(value); }
|
|
238
|
-
function findSessionFile(directory, sessionId) {
|
|
239
|
-
if (!existsSync(directory))
|
|
240
|
-
return undefined;
|
|
241
|
-
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
242
|
-
const path = join(directory, entry.name);
|
|
243
|
-
if (entry.isDirectory()) {
|
|
244
|
-
const found = findSessionFile(path, sessionId);
|
|
245
|
-
if (found)
|
|
246
|
-
return found;
|
|
247
|
-
}
|
|
248
|
-
else if (entry.name.endsWith(".jsonl")) {
|
|
249
|
-
try {
|
|
250
|
-
const header = JSON.parse(readFileSync(path, "utf8").split("\n")[0] ?? "{}");
|
|
251
|
-
if (isObject(header) && header.id === sessionId)
|
|
252
|
-
return path;
|
|
253
|
-
}
|
|
254
|
-
catch { /* Ignore incomplete sessions. */ }
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
return undefined;
|
|
258
|
-
}
|
|
259
238
|
function emptyResult(candidate, repository, worktree, environment, error) {
|
|
260
239
|
const accounting = emptyAccounting();
|
|
261
240
|
return {
|
|
262
241
|
id: candidate.id, status: "failed", workflows: [], accounting, accountingTrustworthy: false, diagnostics: [], errors: [error],
|
|
263
242
|
manifest: {
|
|
264
|
-
invocationMode: AMBIENT_INVOCATION_MODE, fixtureRoot: repository.fixtureRoot, worktreePath: worktree.path, ambientAgentDir: ambientAgentDir(environment), fixtureFileList: worktree.fixtureFiles, gitStatusBefore: worktree.gitStatusBefore,
|
|
243
|
+
invocationMode: AMBIENT_INVOCATION_MODE, fixtureRoot: repository.fixtureRoot, worktreePath: worktree.path, ambientAgentDir: ambientAgentDir(environment), fixtureFileList: worktree.fixtureFiles, gitStatusBefore: worktree.gitStatusBefore, parentToolSequence: [], skillReads: [], workflowCalls: [], workflowCallCount: 0, tokenCost: accounting,
|
|
265
244
|
cleanup: { processExited: false, processGroupTerminated: false, worktreeRemoved: false, fixtureRepoRemoved: false, tempRootRemoved: false, captureIdentityVerified: false, realWorkflowAgentsLaunched: 0 },
|
|
266
245
|
},
|
|
267
246
|
};
|
|
@@ -271,12 +250,13 @@ async function runAmbientCase(repository, candidate, artifactsDir, environment,
|
|
|
271
250
|
const sessionId = randomUUID();
|
|
272
251
|
const sessionDir = join(repository.root, "sessions", candidate.id);
|
|
273
252
|
let result;
|
|
274
|
-
let
|
|
253
|
+
let failure;
|
|
254
|
+
let gitStatusAfter;
|
|
275
255
|
try {
|
|
276
256
|
const pi = await runAmbientPiProcess({ worktree: worktree.path, sessionDir, sessionId, prompt: candidate.prompt, provider, model, ...(thinking ? { thinking } : {}), ...(piCommand ? { piCommand } : {}), timeoutMs: candidate.timeoutMs, maxCost: candidate.maxCost, environment });
|
|
277
257
|
const sessionFile = findSessionFile(sessionDir, sessionId);
|
|
278
258
|
if (!sessionFile)
|
|
279
|
-
|
|
259
|
+
failure = "Ambient parent session was not written.";
|
|
280
260
|
else {
|
|
281
261
|
const oracle = extractParentOracleFile(sessionFile);
|
|
282
262
|
const workflows = extractCapturedWorkflows(oracle);
|
|
@@ -286,14 +266,14 @@ async function runAmbientCase(repository, candidate, artifactsDir, environment,
|
|
|
286
266
|
result = {
|
|
287
267
|
id: candidate.id, status, workflows, accounting: oracle.usage, accountingTrustworthy: !pi.timedOut && !pi.budgetExceeded && pi.exitCode === 0, diagnostics: [pi.stderr].filter(Boolean), errors,
|
|
288
268
|
manifest: {
|
|
289
|
-
invocationMode: AMBIENT_INVOCATION_MODE, fixtureRoot: repository.fixtureRoot, worktreePath: worktree.path, ambientAgentDir: ambientAgentDir(environment), fixtureFileList: worktree.fixtureFiles, gitStatusBefore: worktree.gitStatusBefore,
|
|
269
|
+
invocationMode: AMBIENT_INVOCATION_MODE, fixtureRoot: repository.fixtureRoot, worktreePath: worktree.path, ambientAgentDir: ambientAgentDir(environment), fixtureFileList: worktree.fixtureFiles, gitStatusBefore: worktree.gitStatusBefore, parentToolSequence: oracle.parentToolSequence, skillReads: oracle.skillReads, workflowCalls: workflows, workflowCallCount: oracle.workflowCallCount, tokenCost: oracle.usage,
|
|
290
270
|
cleanup: { processExited: pi.exitCode !== null, processGroupTerminated: pi.processGroupTerminated, worktreeRemoved: false, fixtureRepoRemoved: false, tempRootRemoved: false, captureIdentityVerified, realWorkflowAgentsLaunched: 0 },
|
|
291
271
|
},
|
|
292
272
|
};
|
|
293
273
|
}
|
|
294
274
|
}
|
|
295
275
|
catch (error) {
|
|
296
|
-
|
|
276
|
+
failure = error instanceof Error ? error.message : String(error);
|
|
297
277
|
}
|
|
298
278
|
finally {
|
|
299
279
|
try {
|
|
@@ -304,12 +284,13 @@ async function runAmbientCase(repository, candidate, artifactsDir, environment,
|
|
|
304
284
|
}
|
|
305
285
|
const worktreeRemoved = removeAmbientCaseWorktree(repository, worktree);
|
|
306
286
|
if (!result)
|
|
307
|
-
result = emptyResult(candidate, repository, worktree, environment, "Ambient case produced no result.");
|
|
287
|
+
result = emptyResult(candidate, repository, worktree, environment, failure ?? "Ambient case produced no result.");
|
|
308
288
|
const cleanup = { ...result.manifest.cleanup, worktreeRemoved };
|
|
309
|
-
result = { ...result, manifest: { ...result.manifest,
|
|
310
|
-
writeFileSync(join(artifactsDir, `${candidate.id}.json`), `${JSON.stringify(result, null, 2)}\n`, { mode: 0o600 });
|
|
289
|
+
result = { ...result, manifest: { ...result.manifest, cleanup } };
|
|
311
290
|
}
|
|
312
|
-
|
|
291
|
+
const finalized = { ...result, manifest: { ...result.manifest, gitStatusAfter } };
|
|
292
|
+
writeFileSync(join(artifactsDir, `${candidate.id}.json`), `${JSON.stringify(finalized, null, 2)}\n`, { mode: 0o600 });
|
|
293
|
+
return finalized;
|
|
313
294
|
}
|
|
314
295
|
export function assertAmbientOptIn(environment = process.env) {
|
|
315
296
|
if (environment[AMBIENT_OPT_IN] !== "1")
|
package/dist/src/doctor.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
|
2
2
|
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
3
3
|
import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
|
|
4
4
|
import { ModelRuntime, createAgentSessionFromServices, createAgentSessionServices, getAgentDir, hasTrustRequiringProjectResources, SessionManager, SettingsManager, } from "@earendil-works/pi-coding-agent";
|
|
5
|
-
import { DEFAULT_SETTINGS, loadSettings,
|
|
5
|
+
import { DEFAULT_SETTINGS, loadSettings, resolveAgentResourcePolicy, resolveModelReference, parseRoleMarkdown, preflight, registeredWorkflowDefinitions, workflowRoleDirectories, workflowProjectSettingsPath, workflowSettingsPath, WorkflowError, } from "./index.js";
|
|
6
6
|
const THINKING_HINT = "Use off, minimal, low, medium, high, xhigh, or max.";
|
|
7
7
|
function canonical(path) {
|
|
8
8
|
const absolute = resolve(path);
|
|
@@ -153,9 +153,6 @@ function inspectRole(path, activeTools, knownModels, availableModels, diagnostic
|
|
|
153
153
|
diagnostics.push(diagnostic("error", "ROLE_TOOL_INACTIVE", `Tool is unknown or inactive: ${tool}`, path, "Use a tool listed under Active tools or enable its Pi extension."));
|
|
154
154
|
return definition;
|
|
155
155
|
}
|
|
156
|
-
class DoctorModelSet extends Set {
|
|
157
|
-
has(value) { parseModelReference(value); return true; }
|
|
158
|
-
}
|
|
159
156
|
function matchResourcePolicy(policy, pi) {
|
|
160
157
|
const extensions = new Set((pi.extensions ?? []).map(canonical));
|
|
161
158
|
const skills = new Set(pi.skills ?? []);
|
|
@@ -245,12 +242,13 @@ export async function doctor(options = {}) {
|
|
|
245
242
|
let valid = true;
|
|
246
243
|
try {
|
|
247
244
|
const checked = preflight(workflow.script, {
|
|
248
|
-
models: new
|
|
245
|
+
models: new Set(pi.knownModels),
|
|
249
246
|
tools: activeTools,
|
|
250
247
|
agentTypes: new Set(definitions.keys()),
|
|
251
248
|
modelAliases: aliases,
|
|
252
249
|
knownModels,
|
|
253
250
|
settingsPath,
|
|
251
|
+
skipModelAvailability: true,
|
|
254
252
|
}, [], { name, description: workflow.description });
|
|
255
253
|
for (const model of checked.referenced.models)
|
|
256
254
|
if (!knownModels.has(model) || !availableModels.has(model))
|
package/dist/src/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import { RunStore } from "./persistence.js";
|
|
|
5
5
|
import type { AwaitingCheckpoint, PersistedRun, WorktreeReference } from "./persistence.js";
|
|
6
6
|
export declare const RUN_STATES: readonly ["queued", "running", "pausing", "paused", "awaiting_input", "completed", "failed", "stopped", "interrupted", "budget_exhausted"];
|
|
7
7
|
export declare const AGENT_STATES: readonly ["queued", "running", "waiting_for_child", "paused", "retrying", "completed", "failed", "cancelled"];
|
|
8
|
-
export declare const
|
|
9
|
-
export
|
|
8
|
+
export declare const WORKFLOW_CALL_KINDS: readonly ["agent", "conversation", "parallel", "pipeline", "checkpoint", "phase", "withWorktree"];
|
|
9
|
+
export type WorkflowCallKind = (typeof WORKFLOW_CALL_KINDS)[number];
|
|
10
10
|
export declare const WORKFLOW_RUN_STARTED_EVENT = "workflow:run-started";
|
|
11
11
|
export declare const WORKFLOW_RUN_RESUMED_EVENT = "workflow:run-resumed";
|
|
12
12
|
export declare const WORKFLOW_RUN_STATE_CHANGED_EVENT = "workflow:run-state-changed";
|
|
@@ -215,7 +215,7 @@ export interface AgentRecord {
|
|
|
215
215
|
activity?: AgentActivity | undefined;
|
|
216
216
|
}
|
|
217
217
|
export interface WorkflowRunEvent {
|
|
218
|
-
type:
|
|
218
|
+
type: string;
|
|
219
219
|
message: string;
|
|
220
220
|
}
|
|
221
221
|
export interface RunRecord {
|
|
@@ -290,6 +290,7 @@ export interface WorkflowRunContext {
|
|
|
290
290
|
}
|
|
291
291
|
export interface WorkflowFunctionContext extends WorkflowOrchestrationContext {
|
|
292
292
|
run: Readonly<WorkflowRunContext>;
|
|
293
|
+
invoke: (name: string, input: Readonly<Record<string, JsonValue>>) => Promise<JsonValue>;
|
|
293
294
|
}
|
|
294
295
|
export interface WorkflowFunction {
|
|
295
296
|
description: string;
|
|
@@ -339,6 +340,8 @@ export declare class RunLifecycle {
|
|
|
339
340
|
terminal(state: "completed" | "failed" | "stopped" | "interrupted" | "budget_exhausted", reason?: string): Promise<void>;
|
|
340
341
|
}
|
|
341
342
|
export declare const DEFAULT_SETTINGS: Readonly<WorkflowSettings>;
|
|
343
|
+
declare function object(value: unknown): value is Record<string, unknown>;
|
|
344
|
+
export { object as isObject };
|
|
342
345
|
export declare function validateBudget(value: unknown): WorkflowBudget | undefined;
|
|
343
346
|
export declare function validateBudgetPatch(value: unknown): WorkflowBudgetPatch;
|
|
344
347
|
export declare class WorkflowBudgetRuntime {
|
|
@@ -395,7 +398,7 @@ export interface StaticWorkflowScope {
|
|
|
395
398
|
key: string | null;
|
|
396
399
|
}
|
|
397
400
|
export interface StaticWorkflowCall {
|
|
398
|
-
kind:
|
|
401
|
+
kind: WorkflowCallKind;
|
|
399
402
|
start: number;
|
|
400
403
|
end: number;
|
|
401
404
|
name: string | null;
|