@ai-ecoverse/slicc-agent 6.18.17 → 6.19.0
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/README.md +23 -1
- package/dist/codemode/index.js +8 -1
- package/dist/codemode/index.js.map +2 -2
- package/dist/guests/guard.js +32 -2
- package/dist/guests/guard.js.map +2 -2
- package/dist/scoops/cli.js +3 -0
- package/dist/scoops/cli.js.map +2 -2
- package/dist/scoops/index.js +14 -0
- package/dist/scoops/index.js.map +2 -2
- package/dist/scoops/service.js +6 -1
- package/dist/scoops/service.js.map +2 -2
- package/dist/types/codemode/index.d.ts +3 -1
- package/dist/types/guests/guard.d.ts +10 -1
- package/dist/types/scoops/cli.d.ts +2 -1
- package/dist/types/scoops/service.d.ts +11 -1
- package/dist/types/workflow/index.d.ts +104 -0
- package/dist/types/workflow/run.d.ts +137 -0
- package/dist/types/workflow/script.d.ts +20 -0
- package/dist/types/workflow/step.d.ts +53 -0
- package/dist/workflow/index.js +444 -0
- package/dist/workflow/index.js.map +7 -0
- package/dist/workflow/run.js +437 -0
- package/dist/workflow/run.js.map +7 -0
- package/dist/workflow/script.js +250 -0
- package/dist/workflow/script.js.map +7 -0
- package/dist/workflow/step.js +132 -0
- package/dist/workflow/step.js.map +7 -0
- package/package.json +5 -5
- package/packages/vfs-root/skills/agent/SKILL.md +4 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context, JsonValue } from '@earendil-works/chord';
|
|
2
|
-
import { type CodemodeError, type CodemodeOutputItem, type CodemodeResult, type CodemodeSandboxOptions, type CodemodeTool } from '@earendil-works/pi-codemode';
|
|
2
|
+
import { type CodemodeError, type CodemodeOutputItem, type CodemodeResult, type CodemodeRun, type CodemodeRunOptions, type CodemodeSandboxOptions, type CodemodeTool } from '@earendil-works/pi-codemode';
|
|
3
3
|
import { type Agent, type Extension, type ToolExecutionApi, type ToolRegistration } from '@earendil-works/pi-durable';
|
|
4
4
|
export declare const CODEMODE = "codemode";
|
|
5
5
|
export declare const DEFAULT_MAX_OUTPUT_TOKENS = 10000;
|
|
@@ -12,6 +12,7 @@ export interface Sandbox {
|
|
|
12
12
|
signal?: AbortSignal;
|
|
13
13
|
store?: Record<string, unknown>;
|
|
14
14
|
}): Promise<CodemodeResult>;
|
|
15
|
+
start(code: string, options: CodemodeRunOptions): CodemodeRun;
|
|
15
16
|
close(): Promise<void>;
|
|
16
17
|
}
|
|
17
18
|
export type SandboxFactory = (options: CodemodeSandboxOptions) => Sandbox;
|
|
@@ -39,4 +40,5 @@ export declare function disabledBySettings(text: string | undefined): boolean;
|
|
|
39
40
|
export type Fetcher = (url: string) => Promise<Response>;
|
|
40
41
|
export declare function wasmCandidates(from: URL): string[];
|
|
41
42
|
export declare function locateWasm(fetcher: Fetcher, from: URL): Promise<WebAssembly.Module | undefined>;
|
|
43
|
+
export declare function sharedSandbox(): SandboxFactory | undefined;
|
|
42
44
|
export declare function sandboxFactory(wasm: () => Promise<WebAssembly.Module | undefined>, workerUrl?: string | URL): SandboxFactory;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context } from '@earendil-works/chord';
|
|
2
|
-
import { type Extension, type Harness, type SubmissionId } from '@earendil-works/pi-durable';
|
|
2
|
+
import { type ConversationId, type Extension, type Harness, type SubmissionId } from '@earendil-works/pi-durable';
|
|
3
3
|
import type { Approval, Approvals } from '../approvals/index.ts';
|
|
4
4
|
import { type GuestPolicy } from './policy.ts';
|
|
5
5
|
import { type AlwaysTool, type SeatRecord } from './seats.ts';
|
|
@@ -36,6 +36,15 @@ export declare function argumentsHash(args: string): Promise<string>;
|
|
|
36
36
|
export declare function sealedRules(rules: readonly AlwaysTool[]): Promise<AlwaysTool[] | null>;
|
|
37
37
|
export declare function summaryOf(args: Record<string, unknown>): string;
|
|
38
38
|
export declare function reasonOf(item: Approval): string;
|
|
39
|
+
export type InheritedTaint = {
|
|
40
|
+
seat: string | null;
|
|
41
|
+
tier: string;
|
|
42
|
+
};
|
|
43
|
+
export declare const GuestTaintDoc: import("@earendil-works/pi-durable").RewindableConversationDocToken<{
|
|
44
|
+
taints: InheritedTaint[];
|
|
45
|
+
}>;
|
|
46
|
+
type TaintReader = Pick<Harness, 'submission' | 'snapshot'>;
|
|
47
|
+
export declare function runTaints(harness: TaintReader, conversationId: ConversationId, context: Context): Promise<InheritedTaint[]>;
|
|
39
48
|
export declare function taintsOf(inputs: readonly SubmissionId[], seats: Readonly<Record<string, SeatRecord>>, harness: Pick<Harness, 'submission'>, context: Context): Promise<Taint[]>;
|
|
40
49
|
export declare function guestToolGate(harness: () => Held | undefined): GuestToolGate;
|
|
41
50
|
export {};
|
|
@@ -13,7 +13,7 @@ export declare const DEFAULT_WAIT_S = 30;
|
|
|
13
13
|
export declare const MAX_DEPTH = 3;
|
|
14
14
|
export declare const RUN_DIR = "/var/lib/slicc/agent/scoops";
|
|
15
15
|
export declare const THINKING: Set<string>;
|
|
16
|
-
export declare const USAGE = "usage:\n agent [options] (--prompt <text> | --file <path> | -)... run a scoop, wait, print its answer\n agent --async [options] (--prompt <text> | --file <path> | -)... start a scoop, print its handle\n agent <cwd> <allowed-commands> <prompt> the same as a synchronous run, in v6's form\n agent list [--agents] | status <handle> | rename <handle> <name>\n agent send <handle> [--follow-up] (<message> | --file <path> | -)\n agent send <target> --lick=<cron|webhook> [--source <name>] (<message> | --file <path> | -)\n agent send parent <note> from a scoop: a progress note to its cone\n agent wait <handle>... [--timeout <seconds>] [--notify]\n agent stop <handle>\n\noptions:\n --name <name> --agent <role> --model <provider/model> --thinking <level> | --effort <low|medium|high|max>\n --tools <a,b> --read-only <path,path> --system-prompt <text> | --system-prompt-file <path>\n --background-after <seconds> --persist-session | --no-persist-session\n\nA synchronous run removes the scoop's folder afterwards. Its transcript is archived in\n/tmp/agent-sessions/<handle>.md, in /home/sessions/<handle>.md with --persist-session, or nowhere\nwith --no-persist-session. subagent is the same command: subagent spawn = agent --async.\n";
|
|
16
|
+
export declare const USAGE = "usage:\n agent [options] (--prompt <text> | --file <path> | -)... run a scoop, wait, print its answer\n agent --async [options] (--prompt <text> | --file <path> | -)... start a scoop, print its handle\n agent <cwd> <allowed-commands> <prompt> the same as a synchronous run, in v6's form\n agent list [--agents] | status <handle> | rename <handle> <name>\n agent send <handle> [--follow-up] (<message> | --file <path> | -)\n agent send <target> --lick=<cron|webhook> [--source <name>] (<message> | --file <path> | -)\n agent send parent <note> from a scoop: a progress note to its cone\n agent wait <handle>... [--timeout <seconds>] [--notify]\n agent stop <handle>\n agent workflow run|list|status|stop|save ... Claude Code workflows; agent workflow help\n\noptions:\n --name <name> --agent <role> --model <provider/model> --thinking <level> | --effort <low|medium|high|max>\n --tools <a,b> --read-only <path,path> --system-prompt <text> | --system-prompt-file <path>\n --background-after <seconds> --persist-session | --no-persist-session\n\nA synchronous run removes the scoop's folder afterwards. Its transcript is archived in\n/tmp/agent-sessions/<handle>.md, in /home/sessions/<handle>.md with --persist-session, or nowhere\nwith --no-persist-session. subagent is the same command: subagent spawn = agent --async.\n";
|
|
17
17
|
export interface CliOptions {
|
|
18
18
|
env: ExecutionEnv;
|
|
19
19
|
harness: Harness;
|
|
@@ -33,6 +33,7 @@ export interface CliOptions {
|
|
|
33
33
|
panel?: (argv: readonly string[], caller: PanelCaller, context: Context) => Promise<Answer>;
|
|
34
34
|
licks?: Pick<Licks, 'deliver'>;
|
|
35
35
|
webhook?: (name: string, delivery: WebhookDelivery, context: Context) => Promise<boolean>;
|
|
36
|
+
workflow?: (argv: readonly string[], who: Caller, request: Request, context: Context) => Promise<Answer>;
|
|
36
37
|
}
|
|
37
38
|
export interface PanelCaller {
|
|
38
39
|
agentId: string | null;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Context } from '@earendil-works/chord';
|
|
2
|
-
import { type AgentChange, type AnyTask, type Conversation, type ConversationId, type Harness, type ToolRegistration } from '@earendil-works/pi-durable';
|
|
2
|
+
import { type AgentChange, type AnyTask, type Conversation, type ConversationId, type Extension, type Harness, type ToolRegistration, type Tx } from '@earendil-works/pi-durable';
|
|
3
3
|
import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
|
|
4
4
|
import { type Agents, type AgentsState, type Mark, type ScoopRecord } from '../agents.ts';
|
|
5
|
+
import { type InheritedTaint } from '../guests/guard.ts';
|
|
5
6
|
import type { ProcessGroups } from '../kernel/groups.ts';
|
|
6
7
|
import { type Layout } from '../layout.ts';
|
|
7
8
|
import type { Licks } from '../licks/licks.ts';
|
|
@@ -57,6 +58,7 @@ export interface ScoopsHost {
|
|
|
57
58
|
mcp?: (names: readonly string[]) => ToolRegistration[];
|
|
58
59
|
layout?: Layout;
|
|
59
60
|
enforced?: boolean;
|
|
61
|
+
exclude?: readonly Extension[];
|
|
60
62
|
}
|
|
61
63
|
export interface Rewound {
|
|
62
64
|
stopped: string[];
|
|
@@ -99,6 +101,13 @@ export interface SpawnRequest {
|
|
|
99
101
|
fromAgent: boolean;
|
|
100
102
|
request?: string;
|
|
101
103
|
limits: Limits;
|
|
104
|
+
taints?: InheritedTaint[];
|
|
105
|
+
created?: (tx: Tx, made: Spawned) => Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
export interface Spawned {
|
|
108
|
+
folder: string;
|
|
109
|
+
conversation: number;
|
|
110
|
+
tasks: number[];
|
|
102
111
|
}
|
|
103
112
|
export declare function workspace(folder: string, layout?: Layout): string;
|
|
104
113
|
export declare function tail(conversation: Conversation, context: Context): Promise<Mark>;
|
|
@@ -106,6 +115,7 @@ export declare function turnStart(conversation: Conversation, context: Context):
|
|
|
106
115
|
export declare function coneOf(state: Readonly<AgentsState>, conversation: number): string | undefined;
|
|
107
116
|
export declare function findScoop(state: Readonly<AgentsState>, handle: string, cone: string | null): [string, ScoopRecord] | undefined;
|
|
108
117
|
export declare function choosable(tools: readonly ToolRegistration[]): Choosable;
|
|
118
|
+
export declare function agentChange(request: SpawnRequest, folder: string, host: Pick<ScoopsHost, 'tools' | 'mcp' | 'layout' | 'exclude'>): AgentChange;
|
|
109
119
|
export declare function askerName(state: Readonly<AgentsState>, asker: string | null): string;
|
|
110
120
|
export declare function createScoops(host: Promise<ScoopsHost>, tasks: () => ScoopTasks): {
|
|
111
121
|
detach: (made: readonly number[], target: string, context: Context) => Promise<void>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Context, JsonValue } from '@earendil-works/chord';
|
|
2
|
+
import { type AnyTask, type Extension, type Registry, type ToolRegistration } from '@earendil-works/pi-durable';
|
|
3
|
+
import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
|
|
4
|
+
import type { Agents } from '../agents.ts';
|
|
5
|
+
import { sharedSandbox } from '../codemode/index.ts';
|
|
6
|
+
import type { Layout } from '../layout.ts';
|
|
7
|
+
import { type Engine, type RunHost, type RunRecord } from './run.ts';
|
|
8
|
+
export { WorkflowsDoc } from './run.ts';
|
|
9
|
+
export declare const WORKFLOW = "workflow";
|
|
10
|
+
export declare const SAVE_NAME: RegExp;
|
|
11
|
+
export type Answer = {
|
|
12
|
+
code: number;
|
|
13
|
+
out: string;
|
|
14
|
+
};
|
|
15
|
+
export interface Files {
|
|
16
|
+
dir: string;
|
|
17
|
+
env: Pick<ExecutionEnv, 'readTextFile' | 'writeFile' | 'createDir' | 'fileInfo'>;
|
|
18
|
+
cwd: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RunRequest {
|
|
21
|
+
cone: string;
|
|
22
|
+
from?: number | null;
|
|
23
|
+
files: Files;
|
|
24
|
+
target: string;
|
|
25
|
+
script?: boolean;
|
|
26
|
+
args?: JsonValue;
|
|
27
|
+
budget?: number;
|
|
28
|
+
concurrency?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface WorkflowHost extends RunHost {
|
|
31
|
+
envFor(user: string | null, context: Context): Promise<Files['env']>;
|
|
32
|
+
tasks: {
|
|
33
|
+
run: AnyTask;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export declare function workflowsDir(home: string): string;
|
|
37
|
+
export declare function pathOf(files: Files, target: string): string;
|
|
38
|
+
export declare function concurrencyOf(value: number | undefined): number;
|
|
39
|
+
export declare function budgetOf(value: number | undefined): number | null;
|
|
40
|
+
export declare function summary(run: RunRecord): string;
|
|
41
|
+
export declare function outcome(run: RunRecord): Answer;
|
|
42
|
+
export declare function createWorkflows(host: Promise<WorkflowHost>): {
|
|
43
|
+
runs: (context: Context) => Promise<Record<string, RunRecord>>;
|
|
44
|
+
find: (id: string, context: Context) => Promise<RunRecord>;
|
|
45
|
+
start: (request: RunRequest, context: Context) => Promise<string>;
|
|
46
|
+
wait: (id: string, context: Context) => Promise<RunRecord | undefined>;
|
|
47
|
+
stop: (id: string, context: Context) => Promise<RunRecord | undefined>;
|
|
48
|
+
save: (id: string, name: string, force: boolean, files: Files, context: Context) => Promise<Answer>;
|
|
49
|
+
list(cone: string | null, context: Context): Promise<RunRecord[]>;
|
|
50
|
+
};
|
|
51
|
+
export type Workflows = ReturnType<typeof createWorkflows>;
|
|
52
|
+
export interface Invocation {
|
|
53
|
+
cone: string;
|
|
54
|
+
scoop: boolean;
|
|
55
|
+
from: number | null;
|
|
56
|
+
files: Files;
|
|
57
|
+
}
|
|
58
|
+
export declare const USAGE = "usage:\n agent workflow run <file.js | name> [--args <json>] [--budget <tokens>] [--concurrency <n>] [--wait]\n agent workflow run --script '<js>' [same options]\n agent workflow list | status <run> | wait <run> | stop <run> | save <run> <name> [--force]\n\nGlobals: agent(prompt, { label, phase, schema, model, effort, agentType }), parallel(thunks),\npipeline(items, ...stages), phase(title), log(message), console, args, budget (output tokens).\n\nRuns a Claude Code .workflow.js as a durable task; it survives a reload. Without --wait it prints\nthe run id. --budget caps output tokens, --concurrency caps agents running at once. save keeps a\nrun's source as ~/.slicc/workflows/<name>.workflow.js, which agent workflow run <name> runs.\n";
|
|
59
|
+
type Parsed = {
|
|
60
|
+
values: Map<string, string>;
|
|
61
|
+
switches: Set<string>;
|
|
62
|
+
rest: string[];
|
|
63
|
+
};
|
|
64
|
+
export declare function parseArgv(argv: readonly string[]): Parsed;
|
|
65
|
+
export interface RunOptions {
|
|
66
|
+
target?: string;
|
|
67
|
+
script?: string;
|
|
68
|
+
args?: JsonValue;
|
|
69
|
+
budget?: number;
|
|
70
|
+
concurrency?: number;
|
|
71
|
+
wait?: boolean;
|
|
72
|
+
}
|
|
73
|
+
export declare function runWorkflow(workflows: Workflows, who: Invocation, options: RunOptions, context: Context): Promise<Answer>;
|
|
74
|
+
export declare function command(workflows: Workflows, who: Invocation, argv: readonly string[], context: Context): Promise<Answer>;
|
|
75
|
+
export declare const TOOL_DESCRIPTION = "Run a Claude Code dynamic workflow (.workflow.js) as a durable background task that survives a reload, or manage runs.\naction run: give file (a path, or the name of a saved workflow) or script (the source). The source starts with `export const meta = { name, description }`; the body may use top-level await and return a JSON result. Globals: `agent(prompt, { label, phase, schema, model: 'provider/model', effort, agentType })` runs one scoop and resolves to its answer (JSON matching schema, when given), and rejects when it fails; `parallel(thunks)` and `pipeline(items, ...stages)` turn a failed branch into null; `phase(title)`, `log(message)`, `console.*`, `args`, `budget` ({ total, spent(), remaining() } in output tokens). No Date.now(), Math.random(), timers, require, fs or nested workflow().\nbudget caps output tokens, concurrency caps agents running at once (default 8). wait: true blocks until the run ends and returns its result; otherwise the run id comes back at once.\naction list | status (run) | stop (run) | save (run, name, force): manage runs; save keeps the source as ~/.slicc/workflows/<name>.workflow.js.";
|
|
76
|
+
type ToolArgs = {
|
|
77
|
+
action: 'run' | 'list' | 'status' | 'stop' | 'save';
|
|
78
|
+
file?: string;
|
|
79
|
+
script?: string;
|
|
80
|
+
args?: unknown;
|
|
81
|
+
budget?: number;
|
|
82
|
+
concurrency?: number;
|
|
83
|
+
wait?: boolean;
|
|
84
|
+
run?: string;
|
|
85
|
+
name?: string;
|
|
86
|
+
force?: boolean;
|
|
87
|
+
};
|
|
88
|
+
export declare function toolArgv(args: ToolArgs): string[];
|
|
89
|
+
export declare function workflowTool(workflows: Workflows, who: (conversation: number, context: Context) => Promise<Invocation | undefined>): ToolRegistration;
|
|
90
|
+
export interface WorkflowsSetup {
|
|
91
|
+
workflows: Workflows;
|
|
92
|
+
extension: Extension;
|
|
93
|
+
attach(host: Omit<WorkflowHost, 'tasks'>): void;
|
|
94
|
+
}
|
|
95
|
+
export declare function setupWorkflows(registry: Registry): WorkflowsSetup;
|
|
96
|
+
export declare function cliCommand(workflows: Workflows, layout: Layout, env: Files['env'], agents: Pick<Agents, 'state'>): (argv: readonly string[], who: {
|
|
97
|
+
cone: string;
|
|
98
|
+
scoop: string | null;
|
|
99
|
+
fromAgent: boolean;
|
|
100
|
+
}, request: {
|
|
101
|
+
user?: string | null;
|
|
102
|
+
cwd: string;
|
|
103
|
+
}, context: Context) => Promise<Answer>;
|
|
104
|
+
export declare function workflowEngine(factory?: typeof sharedSandbox): () => Engine;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { Context, JsonValue } from '@earendil-works/chord';
|
|
2
|
+
import type { CodemodeHostCall, CodemodeOutcome, CodemodeResult, CodemodeRun, CodemodeRunOptions } from '@earendil-works/pi-codemode';
|
|
3
|
+
import { type TaskRuntime, type Tx } from '@earendil-works/pi-durable';
|
|
4
|
+
import type { InheritedTaint } from '../guests/guard.ts';
|
|
5
|
+
import type { Spawned } from '../scoops/service.ts';
|
|
6
|
+
import { plan, type StepHost } from './step.ts';
|
|
7
|
+
export declare const MAX_LOGS = 200;
|
|
8
|
+
export declare const KEPT_RUNS = 50;
|
|
9
|
+
export type RunStatus = 'running' | 'completed' | 'failed' | 'stopped';
|
|
10
|
+
export type RunRecord = {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
cone: string;
|
|
15
|
+
home: string;
|
|
16
|
+
file: string | null;
|
|
17
|
+
source: string;
|
|
18
|
+
budget: number | null;
|
|
19
|
+
concurrency: number;
|
|
20
|
+
status: RunStatus;
|
|
21
|
+
phase: string | null;
|
|
22
|
+
started: number;
|
|
23
|
+
ended: number | null;
|
|
24
|
+
agents: {
|
|
25
|
+
started: number;
|
|
26
|
+
done: number;
|
|
27
|
+
failed: number;
|
|
28
|
+
running: string[];
|
|
29
|
+
};
|
|
30
|
+
spent: number;
|
|
31
|
+
logs: string[];
|
|
32
|
+
fromAgent: boolean;
|
|
33
|
+
taints: InheritedTaint[];
|
|
34
|
+
result?: JsonValue;
|
|
35
|
+
error?: string;
|
|
36
|
+
};
|
|
37
|
+
export declare const WorkflowsDoc: import("@earendil-works/pi-durable").SessionDocToken<{
|
|
38
|
+
runs: Record<string, RunRecord>;
|
|
39
|
+
}>;
|
|
40
|
+
type Start = {
|
|
41
|
+
startedAt: number;
|
|
42
|
+
seed: number;
|
|
43
|
+
fingerprint: string | null;
|
|
44
|
+
count: number;
|
|
45
|
+
firstIssued: number | null;
|
|
46
|
+
};
|
|
47
|
+
type Entry = {
|
|
48
|
+
id: number;
|
|
49
|
+
name: string;
|
|
50
|
+
at: number;
|
|
51
|
+
outcome: JsonValue;
|
|
52
|
+
issuedAfter: number | null;
|
|
53
|
+
};
|
|
54
|
+
export interface Engine {
|
|
55
|
+
start(code: string, options: CodemodeRunOptions): CodemodeRun;
|
|
56
|
+
}
|
|
57
|
+
export interface RunHost extends StepHost {
|
|
58
|
+
engine: () => Engine;
|
|
59
|
+
}
|
|
60
|
+
type Lookup = () => Promise<RunHost>;
|
|
61
|
+
type RunInput = {
|
|
62
|
+
code: string;
|
|
63
|
+
};
|
|
64
|
+
type RunState = {
|
|
65
|
+
phase: 'start';
|
|
66
|
+
} | {
|
|
67
|
+
phase: 'run';
|
|
68
|
+
};
|
|
69
|
+
export declare const GLOBALS: {
|
|
70
|
+
name: string;
|
|
71
|
+
}[];
|
|
72
|
+
export declare const DIVERGED = "the workflow took another path than before the restart, so it cannot resume";
|
|
73
|
+
export declare function noted(record: RunRecord, args: unknown): void;
|
|
74
|
+
export declare function errorText(result: CodemodeResult): string;
|
|
75
|
+
type Runtime = TaskRuntime<RunInput, RunState, null, object>;
|
|
76
|
+
type Event = {
|
|
77
|
+
kind: 'call';
|
|
78
|
+
call: CodemodeHostCall;
|
|
79
|
+
} | {
|
|
80
|
+
kind: 'idle';
|
|
81
|
+
seq: number;
|
|
82
|
+
issued: number;
|
|
83
|
+
} | {
|
|
84
|
+
kind: 'started';
|
|
85
|
+
fingerprint: string;
|
|
86
|
+
};
|
|
87
|
+
export declare class Driver {
|
|
88
|
+
readonly id: string;
|
|
89
|
+
readonly host: RunHost;
|
|
90
|
+
readonly runtime: Runtime;
|
|
91
|
+
readonly context: Context;
|
|
92
|
+
readonly controller: AbortController;
|
|
93
|
+
readonly issued: Map<number, CodemodeHostCall>;
|
|
94
|
+
readonly steps: Set<Promise<void>>;
|
|
95
|
+
readonly deferred: CodemodeHostCall[];
|
|
96
|
+
readonly queue: (() => void)[];
|
|
97
|
+
journal: Entry[];
|
|
98
|
+
start: Start;
|
|
99
|
+
record: RunRecord | undefined;
|
|
100
|
+
next: number;
|
|
101
|
+
idle: {
|
|
102
|
+
seq: number;
|
|
103
|
+
issued: number;
|
|
104
|
+
} | null;
|
|
105
|
+
agents: number;
|
|
106
|
+
inflight: number;
|
|
107
|
+
spent: number;
|
|
108
|
+
stopped: string | null;
|
|
109
|
+
run: CodemodeRun | undefined;
|
|
110
|
+
constructor(host: RunHost, runtime: Runtime, context: Context);
|
|
111
|
+
get scoped(): Context;
|
|
112
|
+
get lanes(): number;
|
|
113
|
+
load(): Promise<void>;
|
|
114
|
+
halt(reason: string): void;
|
|
115
|
+
replaying(): boolean;
|
|
116
|
+
deliver(seq: number, at: number, id: number, outcome: CodemodeOutcome): void;
|
|
117
|
+
expected(): number | null;
|
|
118
|
+
pump(): void;
|
|
119
|
+
handle(event: Event): void;
|
|
120
|
+
acknowledge(seq: number, issued: number): Promise<void>;
|
|
121
|
+
launch(call: CodemodeHostCall): void;
|
|
122
|
+
journalize(call: CodemodeHostCall, outcome: CodemodeOutcome, effect: (record: RunRecord) => void): Promise<void>;
|
|
123
|
+
refused(): string | null;
|
|
124
|
+
admit(): Promise<void>;
|
|
125
|
+
free(): void;
|
|
126
|
+
live(call: CodemodeHostCall): Promise<void>;
|
|
127
|
+
created(call: CodemodeHostCall): (tx: Tx, made: Spawned) => Promise<void>;
|
|
128
|
+
spawn(call: CodemodeHostCall, planned: ReturnType<typeof plan>, limits: object): Promise<{
|
|
129
|
+
folder: string;
|
|
130
|
+
task: number;
|
|
131
|
+
}>;
|
|
132
|
+
step(call: CodemodeHostCall): Promise<JsonValue>;
|
|
133
|
+
fingerprint(value: string): Promise<void>;
|
|
134
|
+
execute(code: string): Promise<CodemodeResult>;
|
|
135
|
+
}
|
|
136
|
+
export declare function runTask(lookup: Lookup): import("@earendil-works/pi-durable").Task<RunInput, RunState, null, object>;
|
|
137
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const MAX_SOURCE: number;
|
|
2
|
+
export declare const MAX_AGENTS = 1000;
|
|
3
|
+
export declare const MAX_ITEMS = 4096;
|
|
4
|
+
export declare const MAX_SCHEMA: number;
|
|
5
|
+
export declare const DEFAULT_CONCURRENCY = 8;
|
|
6
|
+
export interface Meta {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
}
|
|
10
|
+
export interface Config {
|
|
11
|
+
args?: unknown;
|
|
12
|
+
budget: number | null;
|
|
13
|
+
concurrency: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function maxConcurrency(cores?: number): number;
|
|
16
|
+
export declare function parseMeta(source: string): Meta;
|
|
17
|
+
export declare function stripExports(source: string): string;
|
|
18
|
+
export declare const PRELUDE = "\nclass WorkflowError extends Error {\n constructor(message) {\n super(message);\n this.name = 'WorkflowError';\n }\n}\nconst RealDate = globalThis.Date;\nconst RealMath = globalThis.Math;\nconst banned = (what) => () => {\n throw new WorkflowError(what + ' is not allowed in a workflow; pass time or randomness in args');\n};\nconst Date = function Date(...given) {\n if (new.target === undefined) banned('Date()')();\n if (given.length === 0) banned('new Date()')();\n return new RealDate(...given);\n};\nDate.prototype = RealDate.prototype;\nDate.UTC = RealDate.UTC;\nDate.parse = RealDate.parse;\nDate.now = banned('Date.now()');\nObject.freeze(Date);\nconst Math = {};\nfor (const key of Object.getOwnPropertyNames(RealMath)) Math[key] = RealMath[key];\nMath.random = banned('Math.random()');\nObject.freeze(Math);\nconst crypto = Object.freeze({\n getRandomValues: banned('crypto.getRandomValues()'),\n randomUUID: banned('crypto.randomUUID()'),\n});\nconst performance = Object.freeze({ now: banned('performance.now()') });\nconst setTimeout = banned('setTimeout()');\nconst setInterval = banned('setInterval()');\nconst OPTIONS = ['label', 'phase', 'schema', 'model', 'effort', 'agentType', 'isolation'];\nconst lanes = config.concurrency;\nlet started = 0;\nlet spent = 0;\nlet current = null;\nlet active = 0;\nconst waiting = [];\nconst acquire = async () => {\n if (active < lanes) {\n active++;\n return;\n }\n await new Promise((resume) => waiting.push(resume));\n};\nconst release = () => {\n const next = waiting.shift();\n if (next) next();\n else active--;\n};\nconst textOf = (values) =>\n values.map((value) => (typeof value === 'string' ? value : JSON.stringify(value))).join(' ');\nconst note = (kind, text) => {\n tell({ kind, text }).then(undefined, () => undefined);\n};\nconst gate = () => {\n if (config.budget !== null && spent >= config.budget)\n throw new WorkflowError('agent(): the budget of ' + config.budget + ' output tokens is spent');\n};\nconst failed = (error) => {\n note('log', '[error] ' + (error && error.message ? error.message : String(error)));\n return null;\n};\nconst console = Object.freeze({\n log: (...values) => note('log', textOf(values)),\n info: (...values) => note('log', textOf(values)),\n debug: (...values) => note('log', textOf(values)),\n warn: (...values) => note('log', '[warn] ' + textOf(values)),\n error: (...values) => note('log', '[error] ' + textOf(values)),\n});\nconst budget = Object.freeze({\n total: config.budget,\n spent: () => spent,\n remaining: () => (config.budget === null ? Infinity : Math.max(0, config.budget - spent)),\n});\nfunction phase(title) {\n current = String(title);\n note('phase', current);\n}\nfunction log(message) {\n note('log', String(message));\n}\nfunction workflow() {\n throw new WorkflowError('workflow(): nested workflows are not supported in SLICC');\n}\nasync function agent(prompt, options) {\n if (typeof prompt !== 'string' || !prompt.trim()) throw new WorkflowError('agent() needs a prompt string');\n const given = options === undefined || options === null ? {} : options;\n if (typeof given !== 'object' || Array.isArray(given)) throw new WorkflowError('agent(): options must be an object');\n for (const key of Object.keys(given))\n if (!OPTIONS.includes(key)) throw new WorkflowError('agent(): unknown option ' + key);\n if (given.isolation !== undefined) throw new WorkflowError('agent(): isolation is not supported in SLICC');\n if (started >= 1000) throw new WorkflowError('agent(): a workflow starts at most 1000 agents');\n gate();\n started++;\n await acquire();\n try {\n gate();\n const call = { ...given, prompt };\n if (call.phase === undefined && current !== null) call.phase = current;\n try {\n const answer = await host(call);\n spent += answer.outputTokens;\n return answer.value;\n } catch (error) {\n spent += error && typeof error.outputTokens === 'number' ? error.outputTokens : 0;\n throw error;\n }\n } finally {\n release();\n }\n}\nasync function parallel(thunks) {\n if (!Array.isArray(thunks) || thunks.some((thunk) => typeof thunk !== 'function'))\n throw new WorkflowError('parallel() expects an array of functions');\n if (thunks.length > 4096) throw new WorkflowError('parallel(): at most 4096 items per call');\n return Promise.all(\n thunks.map(async (thunk) => {\n try {\n return await thunk();\n } catch (error) {\n return failed(error);\n }\n })\n );\n}\nasync function pipeline(items, ...stages) {\n if (!Array.isArray(items)) throw new WorkflowError('pipeline() expects an array as its first argument');\n if (items.length > 4096) throw new WorkflowError('pipeline(): at most 4096 items per call');\n if (stages.some((stage) => typeof stage !== 'function')) throw new WorkflowError('pipeline(): every stage must be a function');\n return Promise.all(\n items.map(async (item, index) => {\n let value = item;\n for (const stage of stages) {\n try {\n value = await stage(value, item, index);\n } catch (error) {\n return failed(error);\n }\n if (value === null) return null;\n }\n return value;\n })\n );\n}\nreturn Object.freeze({\n agent, parallel, pipeline, phase, log, workflow, console, budget, args: config.args,\n Date, Math, crypto, performance, setTimeout, setInterval, WorkflowError,\n});\n";
|
|
19
|
+
export declare const PUBLIC: string[];
|
|
20
|
+
export declare function buildCode(source: string, config: Config): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Context, JsonValue } from '@earendil-works/chord';
|
|
2
|
+
import type { Harness, TaskId } from '@earendil-works/pi-durable';
|
|
3
|
+
import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
|
|
4
|
+
import type { Agents } from '../agents.ts';
|
|
5
|
+
import type { Layout } from '../layout.ts';
|
|
6
|
+
import { type Role, type Roles } from '../roles/roles.ts';
|
|
7
|
+
import type { ReportResult } from '../scoops/extension.ts';
|
|
8
|
+
import { type Scoops } from '../scoops/service.ts';
|
|
9
|
+
export declare const EFFORT: Record<string, string>;
|
|
10
|
+
export interface AgentCall {
|
|
11
|
+
prompt: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
phase?: string;
|
|
14
|
+
schema?: JsonValue;
|
|
15
|
+
model?: string;
|
|
16
|
+
effort?: string;
|
|
17
|
+
agentType?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface StepHost {
|
|
20
|
+
harness: Harness;
|
|
21
|
+
agents: Agents;
|
|
22
|
+
scoops: Scoops;
|
|
23
|
+
roles: (context: Context) => Promise<Roles>;
|
|
24
|
+
env: Pick<ExecutionEnv, 'remove'>;
|
|
25
|
+
layout: Layout;
|
|
26
|
+
}
|
|
27
|
+
export declare class StepError extends Error {
|
|
28
|
+
readonly outputTokens: number;
|
|
29
|
+
constructor(message: string, outputTokens?: number);
|
|
30
|
+
}
|
|
31
|
+
export interface Planned {
|
|
32
|
+
name: string;
|
|
33
|
+
prompt: string;
|
|
34
|
+
role?: Role;
|
|
35
|
+
model?: {
|
|
36
|
+
provider: string;
|
|
37
|
+
modelId: string;
|
|
38
|
+
};
|
|
39
|
+
thinking?: string;
|
|
40
|
+
schema?: object;
|
|
41
|
+
}
|
|
42
|
+
export declare function instruction(schema: object): string;
|
|
43
|
+
export declare function plan(given: unknown, roles: Roles): Planned;
|
|
44
|
+
export declare function parseAnswer(text: string, schema: object): JsonValue;
|
|
45
|
+
export declare function outputTokens(harness: Harness, conversation: number, context: Context): Promise<number>;
|
|
46
|
+
export declare function cleanup(host: StepHost, folder: string): Promise<void>;
|
|
47
|
+
export declare function settle(host: StepHost, folder: string, task: number, planned: Planned, wait: (task: number) => Promise<ReportResult>, context: Context): Promise<{
|
|
48
|
+
value: JsonValue;
|
|
49
|
+
outputTokens: number;
|
|
50
|
+
}>;
|
|
51
|
+
export declare function waitReport(wait: (id: TaskId<ReportResult>, context: Context) => Promise<{
|
|
52
|
+
state: unknown;
|
|
53
|
+
}>, task: number, context: Context): Promise<ReportResult>;
|