@yanlinglabs/winter-agent-runtime 0.0.27
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/LICENSE +21 -0
- package/NOTICE +41 -0
- package/README.md +64 -0
- package/dist/checkpoint/file-history.d.ts +81 -0
- package/dist/checkpoint/rewind.d.ts +55 -0
- package/dist/checkpoint/seam.d.ts +47 -0
- package/dist/checkpoint/sink.d.ts +66 -0
- package/dist/commands/builtins-listing.d.ts +40 -0
- package/dist/commands/resolver.d.ts +103 -0
- package/dist/commands/seam.d.ts +53 -0
- package/dist/compaction/controller.d.ts +23 -0
- package/dist/compaction/retention.d.ts +35 -0
- package/dist/compaction/seam.d.ts +115 -0
- package/dist/compaction/summarizer.d.ts +79 -0
- package/dist/context/agent-listing.d.ts +39 -0
- package/dist/context/assembler.d.ts +46 -0
- package/dist/context/attachments.d.ts +104 -0
- package/dist/context/dynamic-sections.d.ts +31 -0
- package/dist/context/git-fixture.d.ts +18 -0
- package/dist/context/git-status.d.ts +16 -0
- package/dist/context/imports.d.ts +22 -0
- package/dist/context/injection.d.ts +53 -0
- package/dist/context/memory-key.d.ts +46 -0
- package/dist/context/memory.d.ts +28 -0
- package/dist/context/minimal-prompt.d.ts +5 -0
- package/dist/context/output-styles.d.ts +68 -0
- package/dist/context/plan-mode.d.ts +29 -0
- package/dist/context/request-layout.d.ts +138 -0
- package/dist/context/rules.d.ts +63 -0
- package/dist/context/seam.d.ts +136 -0
- package/dist/context/tool-epoch.d.ts +118 -0
- package/dist/context/winter-code-preset.d.ts +39 -0
- package/dist/context/winter-md.d.ts +81 -0
- package/dist/embedded-host.d.ts +48 -0
- package/dist/embedded-host.js +155 -0
- package/dist/embedded-protocol.d.ts +44 -0
- package/dist/embedded-worker.d.ts +1 -0
- package/dist/embedded-worker.js +74 -0
- package/dist/embedded.d.ts +34 -0
- package/dist/embedded.js +9 -0
- package/dist/engine.d.ts +1298 -0
- package/dist/hooks/additional-context.d.ts +21 -0
- package/dist/hooks/bounds.d.ts +6 -0
- package/dist/hooks/bridge-invoker.d.ts +3 -0
- package/dist/hooks/command-invoker.d.ts +52 -0
- package/dist/hooks/from-config.d.ts +31 -0
- package/dist/hooks/hook-stage.d.ts +25 -0
- package/dist/hooks/input-validator.d.ts +6 -0
- package/dist/hooks/reducer.d.ts +74 -0
- package/dist/hooks/registry.d.ts +33 -0
- package/dist/hooks/runner.d.ts +105 -0
- package/dist/index-584yahed.js +6037 -0
- package/dist/index-97t2rmtf.js +42 -0
- package/dist/index-9qgkpv56.js +27183 -0
- package/dist/index-bef62z3r.js +437 -0
- package/dist/index-rkhh0457.js +187 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +353 -0
- package/dist/main.d.ts +1 -0
- package/dist/mcp/client.d.ts +105 -0
- package/dist/mcp/control-seam.d.ts +25 -0
- package/dist/mcp/control.d.ts +5 -0
- package/dist/mcp/elicitation.d.ts +35 -0
- package/dist/mcp/env.d.ts +12 -0
- package/dist/mcp/lifecycle.d.ts +142 -0
- package/dist/mcp/output-cap.d.ts +15 -0
- package/dist/mcp/state.d.ts +24 -0
- package/dist/mcp/test-fixtures.d.ts +88 -0
- package/dist/mcp/transports/__fixtures__/stdio-server.d.ts +1 -0
- package/dist/mcp/transports/http.d.ts +5 -0
- package/dist/mcp/transports/sdk.d.ts +5 -0
- package/dist/mcp/transports/sse.d.ts +3 -0
- package/dist/mcp/transports/stdio.d.ts +35 -0
- package/dist/mcp/winter-server.d.ts +2 -0
- package/dist/messaging/reference-adapter.d.ts +88 -0
- package/dist/messaging/router.d.ts +8 -0
- package/dist/paths/project-dir-name.d.ts +2 -0
- package/dist/paths/temp.d.ts +25 -0
- package/dist/permissions/approvals.d.ts +107 -0
- package/dist/permissions/auto/caches.d.ts +53 -0
- package/dist/permissions/auto/config.d.ts +37 -0
- package/dist/permissions/auto/engine.d.ts +74 -0
- package/dist/permissions/auto/envelope.d.ts +45 -0
- package/dist/permissions/auto/inheritance.d.ts +27 -0
- package/dist/permissions/edit-recognition.d.ts +30 -0
- package/dist/permissions/evaluator.d.ts +284 -0
- package/dist/permissions/file-rules.d.ts +384 -0
- package/dist/permissions/grammar.d.ts +113 -0
- package/dist/permissions/paths.d.ts +32 -0
- package/dist/permissions/policy-state.d.ts +64 -0
- package/dist/permissions/prompt-stage.d.ts +3 -0
- package/dist/permissions/protected.d.ts +54 -0
- package/dist/permissions/ruleset.d.ts +134 -0
- package/dist/permissions/shell-structure.d.ts +41 -0
- package/dist/plugins/bundle.d.ts +100 -0
- package/dist/plugins/installed.d.ts +30 -0
- package/dist/plugins/loader.d.ts +56 -0
- package/dist/plugins/manifest.d.ts +115 -0
- package/dist/production-wiring.d.ts +340 -0
- package/dist/protocol/channel.d.ts +22 -0
- package/dist/provider/advisor-route.d.ts +47 -0
- package/dist/provider/bridge.d.ts +124 -0
- package/dist/provider/classifier/model-classifier.d.ts +82 -0
- package/dist/provider/classifier/prompt.d.ts +62 -0
- package/dist/provider/classifier/verdict-schema.d.ts +83 -0
- package/dist/provider/credential-api.d.ts +160 -0
- package/dist/provider/family-listing.d.ts +27 -0
- package/dist/provider/first-party.d.ts +4 -0
- package/dist/provider/keychain-store.d.ts +59 -0
- package/dist/provider/lean-prompt.d.ts +7 -0
- package/dist/provider/mock.d.ts +55 -0
- package/dist/provider/scenario-fake.d.ts +96 -0
- package/dist/provider/selection.d.ts +115 -0
- package/dist/provider/session-provider.d.ts +426 -0
- package/dist/provider/slots.d.ts +120 -0
- package/dist/provider/stream-frames.d.ts +25 -0
- package/dist/provider/tool-secret.d.ts +57 -0
- package/dist/rpc/bridge.d.ts +14 -0
- package/dist/rpc/mcp-control.d.ts +26 -0
- package/dist/runtime.d.ts +14 -0
- package/dist/sandbox/profile.d.ts +249 -0
- package/dist/sandbox/spawn.d.ts +139 -0
- package/dist/settings/env-filter.d.ts +52 -0
- package/dist/settings/loaders/hooks.d.ts +44 -0
- package/dist/settings/loaders/mcp-config.d.ts +83 -0
- package/dist/settings/loaders/plugin-mcp.d.ts +3 -0
- package/dist/settings/loaders/strict-plugin-only.d.ts +13 -0
- package/dist/settings/resolve.d.ts +2 -0
- package/dist/settings/sources.d.ts +2 -0
- package/dist/settings/trust.d.ts +36 -0
- package/dist/skills/attachment.d.ts +25 -0
- package/dist/skills/frontmatter.d.ts +64 -0
- package/dist/skills/index.d.ts +16 -0
- package/dist/skills/listing.d.ts +89 -0
- package/dist/skills/loader.d.ts +104 -0
- package/dist/skills/option.d.ts +68 -0
- package/dist/skills/permission-rules.d.ts +21 -0
- package/dist/skills/runtime.d.ts +21 -0
- package/dist/skills/store.d.ts +163 -0
- package/dist/store/continuation-attach.d.ts +44 -0
- package/dist/store/dialect.d.ts +526 -0
- package/dist/store/provider-state.d.ts +188 -0
- package/dist/store/resume.d.ts +92 -0
- package/dist/structured/ajv-seam.d.ts +7 -0
- package/dist/structured/descriptor.d.ts +9 -0
- package/dist/structured/seam.d.ts +51 -0
- package/dist/structured/validator.d.ts +22 -0
- package/dist/subagents/activity.d.ts +13 -0
- package/dist/subagents/availability.d.ts +30 -0
- package/dist/subagents/builtin-agents.d.ts +37 -0
- package/dist/subagents/child-engine.d.ts +198 -0
- package/dist/subagents/child-handle.d.ts +344 -0
- package/dist/subagents/definitions.d.ts +189 -0
- package/dist/subagents/fork.d.ts +55 -0
- package/dist/subagents/git-root.d.ts +1 -0
- package/dist/subagents/limits.d.ts +28 -0
- package/dist/subagents/notification-queue.d.ts +233 -0
- package/dist/subagents/plugin-agents.d.ts +5 -0
- package/dist/subagents/policy.d.ts +46 -0
- package/dist/subagents/register-default-factory.d.ts +66 -0
- package/dist/subagents/resolution.d.ts +56 -0
- package/dist/subagents/restore.d.ts +9 -0
- package/dist/subagents/roster.d.ts +17 -0
- package/dist/subagents/test-fakes.d.ts +12 -0
- package/dist/subagents/tool-pools.d.ts +69 -0
- package/dist/subagents/watchdog.d.ts +13 -0
- package/dist/subagents/workspace.d.ts +27 -0
- package/dist/testing.d.ts +5 -0
- package/dist/testing.js +194 -0
- package/dist/tools/background-tasks.d.ts +10 -0
- package/dist/tools/descriptors/_shared.d.ts +34 -0
- package/dist/tools/descriptors/advisor.d.ts +1 -0
- package/dist/tools/descriptors/agent.d.ts +47 -0
- package/dist/tools/descriptors/artifact.d.ts +1 -0
- package/dist/tools/descriptors/ask-user-question.d.ts +1 -0
- package/dist/tools/descriptors/bash.d.ts +20 -0
- package/dist/tools/descriptors/claude-design.d.ts +1 -0
- package/dist/tools/descriptors/cron-create.d.ts +1 -0
- package/dist/tools/descriptors/cron-delete.d.ts +1 -0
- package/dist/tools/descriptors/cron-list.d.ts +1 -0
- package/dist/tools/descriptors/edit.d.ts +1 -0
- package/dist/tools/descriptors/end-conversation.d.ts +1 -0
- package/dist/tools/descriptors/enter-plan-mode.d.ts +1 -0
- package/dist/tools/descriptors/enter-worktree.d.ts +1 -0
- package/dist/tools/descriptors/exit-plan-mode.d.ts +1 -0
- package/dist/tools/descriptors/exit-worktree.d.ts +1 -0
- package/dist/tools/descriptors/glob.d.ts +1 -0
- package/dist/tools/descriptors/grep.d.ts +1 -0
- package/dist/tools/descriptors/index.d.ts +59 -0
- package/dist/tools/descriptors/list-agents.d.ts +1 -0
- package/dist/tools/descriptors/list-mcp-resources-tool.d.ts +1 -0
- package/dist/tools/descriptors/lsp.d.ts +1 -0
- package/dist/tools/descriptors/monitor.d.ts +1 -0
- package/dist/tools/descriptors/notebook-edit.d.ts +1 -0
- package/dist/tools/descriptors/powershell.d.ts +1 -0
- package/dist/tools/descriptors/projects.d.ts +1 -0
- package/dist/tools/descriptors/propose-goal.d.ts +1 -0
- package/dist/tools/descriptors/propose-skills.d.ts +1 -0
- package/dist/tools/descriptors/push-notification.d.ts +1 -0
- package/dist/tools/descriptors/read-mcp-resource-dir-tool.d.ts +1 -0
- package/dist/tools/descriptors/read-mcp-resource-tool.d.ts +1 -0
- package/dist/tools/descriptors/read-notifications.d.ts +1 -0
- package/dist/tools/descriptors/read.d.ts +1 -0
- package/dist/tools/descriptors/refresh-mcp-tools.d.ts +1 -0
- package/dist/tools/descriptors/remote-trigger.d.ts +1 -0
- package/dist/tools/descriptors/repl.d.ts +1 -0
- package/dist/tools/descriptors/report-findings.d.ts +1 -0
- package/dist/tools/descriptors/schedule-wakeup.d.ts +1 -0
- package/dist/tools/descriptors/send-feedback.d.ts +1 -0
- package/dist/tools/descriptors/send-message.d.ts +1 -0
- package/dist/tools/descriptors/send-user-file.d.ts +1 -0
- package/dist/tools/descriptors/share-onboarding-guide.d.ts +1 -0
- package/dist/tools/descriptors/show-onboarding-role-picker.d.ts +1 -0
- package/dist/tools/descriptors/skill.d.ts +1 -0
- package/dist/tools/descriptors/structured-output.d.ts +1 -0
- package/dist/tools/descriptors/task-create.d.ts +1 -0
- package/dist/tools/descriptors/task-get.d.ts +1 -0
- package/dist/tools/descriptors/task-list.d.ts +1 -0
- package/dist/tools/descriptors/task-output.d.ts +1 -0
- package/dist/tools/descriptors/task-stop.d.ts +1 -0
- package/dist/tools/descriptors/task-update.d.ts +1 -0
- package/dist/tools/descriptors/todo-write.d.ts +1 -0
- package/dist/tools/descriptors/tool-search.d.ts +1 -0
- package/dist/tools/descriptors/wait-for-mcp-servers.d.ts +1 -0
- package/dist/tools/descriptors/web-fetch.d.ts +8 -0
- package/dist/tools/descriptors/web-search.d.ts +15 -0
- package/dist/tools/descriptors/winter-list-agents.d.ts +1 -0
- package/dist/tools/descriptors/winter-send-message.d.ts +1 -0
- package/dist/tools/descriptors/workflow.d.ts +1 -0
- package/dist/tools/descriptors/write.d.ts +1 -0
- package/dist/tools/impl/_caller.d.ts +14 -0
- package/dist/tools/impl/_domains.d.ts +25 -0
- package/dist/tools/impl/_exa-client.d.ts +122 -0
- package/dist/tools/impl/_exa-session-client.d.ts +23 -0
- package/dist/tools/impl/_inner-model.d.ts +135 -0
- package/dist/tools/impl/_search-budget.d.ts +36 -0
- package/dist/tools/impl/_web-fetch-cache.d.ts +37 -0
- package/dist/tools/impl/_web-fetch-html.d.ts +26 -0
- package/dist/tools/impl/_web-fetch-net.d.ts +99 -0
- package/dist/tools/impl/_web-search-assembler.d.ts +57 -0
- package/dist/tools/impl/advisor.d.ts +37 -0
- package/dist/tools/impl/agent.d.ts +10 -0
- package/dist/tools/impl/ask-user-question.d.ts +5 -0
- package/dist/tools/impl/background-task-runtime.d.ts +272 -0
- package/dist/tools/impl/bash.d.ts +78 -0
- package/dist/tools/impl/cron.d.ts +11 -0
- package/dist/tools/impl/edit.d.ts +1 -0
- package/dist/tools/impl/enter-plan-mode.d.ts +4 -0
- package/dist/tools/impl/enter-worktree.d.ts +25 -0
- package/dist/tools/impl/exit-plan-mode.d.ts +4 -0
- package/dist/tools/impl/exit-worktree.d.ts +4 -0
- package/dist/tools/impl/glob.d.ts +1 -0
- package/dist/tools/impl/grep.d.ts +19 -0
- package/dist/tools/impl/index.d.ts +37 -0
- package/dist/tools/impl/list-agents.d.ts +7 -0
- package/dist/tools/impl/list-mcp-resources-tool.d.ts +9 -0
- package/dist/tools/impl/monitor.d.ts +66 -0
- package/dist/tools/impl/notebook-edit.d.ts +1 -0
- package/dist/tools/impl/push-notification.d.ts +4 -0
- package/dist/tools/impl/read-ladder.d.ts +25 -0
- package/dist/tools/impl/read-mcp-resource-dir-tool.d.ts +9 -0
- package/dist/tools/impl/read-mcp-resource-tool.d.ts +9 -0
- package/dist/tools/impl/read-notifications.d.ts +5 -0
- package/dist/tools/impl/read.d.ts +44 -0
- package/dist/tools/impl/refresh-mcp-tools.d.ts +8 -0
- package/dist/tools/impl/report-findings.d.ts +1 -0
- package/dist/tools/impl/schedule-wakeup.d.ts +2 -0
- package/dist/tools/impl/send-message.d.ts +7 -0
- package/dist/tools/impl/skill.d.ts +5 -0
- package/dist/tools/impl/task-graph.d.ts +1 -0
- package/dist/tools/impl/task-output.d.ts +16 -0
- package/dist/tools/impl/task-stop.d.ts +11 -0
- package/dist/tools/impl/todo-write.d.ts +8 -0
- package/dist/tools/impl/tool-search.d.ts +4 -0
- package/dist/tools/impl/wait-for-mcp-servers.d.ts +29 -0
- package/dist/tools/impl/web-fetch.d.ts +36 -0
- package/dist/tools/impl/web-search.d.ts +30 -0
- package/dist/tools/impl/workflow.d.ts +5 -0
- package/dist/tools/impl/write.d.ts +8 -0
- package/dist/tools/paths-seam.d.ts +6 -0
- package/dist/tools/read-state.d.ts +12 -0
- package/dist/tools/registry.d.ts +423 -0
- package/dist/tools/task-graph-store.d.ts +61 -0
- package/dist/toolsearch/aliases.d.ts +26 -0
- package/dist/toolsearch/exposure.d.ts +30 -0
- package/dist/toolsearch/ranking.d.ts +6 -0
- package/dist/toolsearch/search.d.ts +45 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/web/fetchable-url.d.ts +28 -0
- package/dist/web/preapproved-hosts.d.ts +52 -0
- package/dist/web/private-address.d.ts +55 -0
- package/dist/web/session-runtime.d.ts +86 -0
- package/dist/workflows/bridge.d.ts +87 -0
- package/dist/workflows/budget.d.ts +24 -0
- package/dist/workflows/host-registry.d.ts +142 -0
- package/dist/workflows/journal.d.ts +29 -0
- package/dist/workflows/meta.d.ts +45 -0
- package/dist/workflows/registry.d.ts +24 -0
- package/dist/workflows/runtime.d.ts +254 -0
- package/dist/workflows/sandbox.d.ts +49 -0
- package/dist/workflows/script-api.d.ts +58 -0
- package/dist/workflows/seam.d.ts +92 -0
- package/dist/workflows/semaphore.d.ts +16 -0
- package/dist/workflows/store.d.ts +177 -0
- package/dist/workflows/subprocess-entry.d.ts +38 -0
- package/dist/workflows/subprocess-entry.js +14 -0
- package/dist/workflows/transcript.d.ts +56 -0
- package/dist/workflows/types.d.ts +84 -0
- package/dist/workflows/worker-harness.d.ts +45 -0
- package/package.json +76 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { type JournalEntry } from "./journal.js";
|
|
2
|
+
import { type WorkerCommand } from "./sandbox.js";
|
|
3
|
+
import type { SandboxBrand } from "../sandbox/profile.js";
|
|
4
|
+
import type { BrandProfile, SettingSource } from "@yanlinglabs/winter-agent-sdk";
|
|
5
|
+
import { type WorkflowRef } from "./bridge.js";
|
|
6
|
+
import type { WorkflowSessionRuntime } from "./host-registry.js";
|
|
7
|
+
import { type WorkflowMeta } from "./meta.js";
|
|
8
|
+
import type { WorkflowRunView, WorkflowStatus } from "./types.js";
|
|
9
|
+
import type { WorkflowRunHost } from "./seam.js";
|
|
10
|
+
/** WS-11 §1.6's own three numbers, in one place so nothing re-derives them. */
|
|
11
|
+
export declare const TOTAL_AGENTS_PER_RUN = 1000;
|
|
12
|
+
export declare const MAX_ITEMS_PER_CALL = 4096;
|
|
13
|
+
/** A typed launch/resume refusal -- `code` so a tool executor can render each case differently without matching on message text. */
|
|
14
|
+
export declare class WorkflowRuntimeError extends Error {
|
|
15
|
+
readonly code: "unknown-run" | "cross-session" | "not-stopped" | "sandbox-unavailable" | "no-source";
|
|
16
|
+
constructor(code: "unknown-run" | "cross-session" | "not-stopped" | "sandbox-unavailable" | "no-source", message: string);
|
|
17
|
+
}
|
|
18
|
+
export interface WorkerProcess {
|
|
19
|
+
stdin: NodeJS.WritableStream;
|
|
20
|
+
stdout: NodeJS.ReadableStream;
|
|
21
|
+
pid?: number;
|
|
22
|
+
onExit(cb: (code: number | null) => void): void;
|
|
23
|
+
onError(cb: (err: Error) => void): void;
|
|
24
|
+
kill(): void;
|
|
25
|
+
}
|
|
26
|
+
export type WorkerSpawner = (command: WorkerCommand, opts: {
|
|
27
|
+
home?: string;
|
|
28
|
+
winterHome?: string;
|
|
29
|
+
brand?: SandboxBrand;
|
|
30
|
+
cwd?: string;
|
|
31
|
+
}) => WorkerProcess;
|
|
32
|
+
/**
|
|
33
|
+
* The production spawner: `sandbox-exec -p <profile> <worker>`, its own process-group leader.
|
|
34
|
+
*
|
|
35
|
+
* `sandbox: false` spawns the worker DIRECTLY, with no seatbelt. It exists for exactly one caller --
|
|
36
|
+
* `scripts/verify-workflow.ts` on a host that has no `/usr/bin/sandbox-exec` (the linux CI runner),
|
|
37
|
+
* where that gate's subject is the COMPILED ARGV DISPATCH and refusing to run at all would leave that
|
|
38
|
+
* leg unverified. It is NOT a production posture and nothing in the runtime reaches it: `launch`
|
|
39
|
+
* refuses outright when the sandbox is required and unavailable, and the seatbelt's own claims are
|
|
40
|
+
* proved separately in `workflows/worker.darwin.test.ts`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function realWorkerSpawner(opts?: {
|
|
43
|
+
sandbox?: boolean;
|
|
44
|
+
}): WorkerSpawner;
|
|
45
|
+
export interface WorkflowRuntimeDeps {
|
|
46
|
+
session: WorkflowSessionRuntime;
|
|
47
|
+
caps?: {
|
|
48
|
+
concurrency?: number;
|
|
49
|
+
totalAgents?: number;
|
|
50
|
+
maxItemsPerCall?: number;
|
|
51
|
+
};
|
|
52
|
+
/** Test seam. Defaults to `realWorkerSpawner()`. */
|
|
53
|
+
spawnWorker?: WorkerSpawner;
|
|
54
|
+
/** Test seam over the worker COMMAND (pre-sandbox). Defaults to the compiled-vs-dev split. */
|
|
55
|
+
workerCommand?: () => WorkerCommand;
|
|
56
|
+
/** Overridable resolver for a nested `workflow(nameOrRef)`. Defaults to store.ts's project resolution. */
|
|
57
|
+
resolveNestedWorkflow?: (ref: WorkflowRef, ctx: {
|
|
58
|
+
cwd: string;
|
|
59
|
+
trustedWorkspace: boolean;
|
|
60
|
+
brand?: BrandProfile;
|
|
61
|
+
pluginWorkflows?: readonly {
|
|
62
|
+
name: string;
|
|
63
|
+
workflowsPath?: string;
|
|
64
|
+
workflowsPaths?: readonly string[];
|
|
65
|
+
}[];
|
|
66
|
+
winterHome?: string;
|
|
67
|
+
settingSources?: readonly SettingSource[];
|
|
68
|
+
}) => Promise<{
|
|
69
|
+
ok: true;
|
|
70
|
+
source: string;
|
|
71
|
+
} | {
|
|
72
|
+
ok: false;
|
|
73
|
+
error: string;
|
|
74
|
+
}>;
|
|
75
|
+
/** Skips the `sandbox-exec` availability refusal. Only a non-default spawner has any business setting this. */
|
|
76
|
+
requireSandbox?: boolean;
|
|
77
|
+
}
|
|
78
|
+
export interface WorkflowLaunchInput {
|
|
79
|
+
sessionId: string;
|
|
80
|
+
cwd: string;
|
|
81
|
+
trustedWorkspace: boolean;
|
|
82
|
+
source: string;
|
|
83
|
+
meta: Pick<WorkflowMeta, "name" | "description"> & Partial<WorkflowMeta>;
|
|
84
|
+
args?: unknown;
|
|
85
|
+
/**
|
|
86
|
+
* The MODEL's own `tool_use` id for the Workflow call (F11). REQUIRED, and deliberately so: WS-10
|
|
87
|
+
* §4 correlates a child's forwarded frames on `SpawnChildRequest.parentToolUseId`, and the previous
|
|
88
|
+
* `?? run.task.taskId` fallback quietly substituted a task id -- a different id space entirely, and
|
|
89
|
+
* exactly the class of fabricated-value-on-a-pinned-field that this lane already removed once from
|
|
90
|
+
* `task_started.workflow_name`. The tool executor refuses the call outright when `ctx.toolUseId` is
|
|
91
|
+
* absent rather than inventing one here.
|
|
92
|
+
*/
|
|
93
|
+
parentToolUseId: string;
|
|
94
|
+
/** Only `resume` supplies these; a fresh launch never does. */
|
|
95
|
+
runId?: string;
|
|
96
|
+
resumeJournal?: JournalEntry[];
|
|
97
|
+
}
|
|
98
|
+
export interface WorkflowLaunchResult {
|
|
99
|
+
taskId: string;
|
|
100
|
+
runId: string;
|
|
101
|
+
/**
|
|
102
|
+
* `meta.name` VERBATIM -- item (g) doc-asserts (`4061`) that `WorkflowOutput.workflowName` is
|
|
103
|
+
* `meta.name` and equals `task_started.workflow_name`. It is threaded rather than recovered from
|
|
104
|
+
* the persisted filename, because that filename is SANITIZED (`store.ts`'s `sanitizeFileStem`):
|
|
105
|
+
* a `meta.name` of `My Workflow!` persists as `My-Workflow-<runId>.js`, so a filename-derived name
|
|
106
|
+
* would silently disagree with the pin for every name outside the slug alphabet.
|
|
107
|
+
*/
|
|
108
|
+
name: string;
|
|
109
|
+
scriptPath: string;
|
|
110
|
+
transcriptDir: string;
|
|
111
|
+
status: WorkflowStatus;
|
|
112
|
+
summary: string;
|
|
113
|
+
}
|
|
114
|
+
export declare class WorkflowRuntime {
|
|
115
|
+
private readonly deps;
|
|
116
|
+
private readonly registry;
|
|
117
|
+
private readonly live;
|
|
118
|
+
private readonly settlers;
|
|
119
|
+
/** Kept beside `live` because `finish` runs AFTER teardown deleted the LiveRun and still has to settle the task. */
|
|
120
|
+
private readonly tasks;
|
|
121
|
+
/** A-14: same reason as `tasks` -- the terminal record is written after the LiveRun is gone. */
|
|
122
|
+
private readonly transcripts;
|
|
123
|
+
/** Each run's source + launch context, so `resume` can replay it verbatim. Never pruned -- one string per run this session launched. */
|
|
124
|
+
private readonly launches;
|
|
125
|
+
private readonly runsDir;
|
|
126
|
+
private readonly concurrency;
|
|
127
|
+
private readonly totalAgents;
|
|
128
|
+
private readonly maxItemsPerCall;
|
|
129
|
+
private readonly spawnWorker;
|
|
130
|
+
constructor(deps: WorkflowRuntimeDeps);
|
|
131
|
+
launch(input: WorkflowLaunchInput, host: WorkflowRunHost): WorkflowLaunchResult;
|
|
132
|
+
/**
|
|
133
|
+
* WS-11 §1.5: a same-session resume of a STOPPED run, replaying its journal.
|
|
134
|
+
*
|
|
135
|
+
* Both preconditions are the pin's own (`sdk-tools.d.ts:2786`: "same-session only, with the prior
|
|
136
|
+
* run stopped first via TaskStop") and both are typed refusals rather than silent no-ops -- this
|
|
137
|
+
* launches a subprocess, so a typo'd runId failing loudly is worth more than a quiet nothing.
|
|
138
|
+
* `sessionId` is taken from the CALLER, never from the input, so a run cannot be resumed into a
|
|
139
|
+
* session that did not own it.
|
|
140
|
+
*
|
|
141
|
+
* RULING I6 (fix wave) -- `opts.replacement` / `opts.args`: a resume that supplies a NEW source
|
|
142
|
+
* (the model edited the persisted script between the stop and the resume, which is exactly what
|
|
143
|
+
* WS-11 §1.3's loop tells it to do) runs the NEW source against the OLD journal. The positional
|
|
144
|
+
* replay then diverges at the first changed call and everything from there runs live, which is
|
|
145
|
+
* §1.5's own contract. This used to rebuild the launch from `this.launches` unconditionally, so a
|
|
146
|
+
* `{scriptPath: <edited>, resumeFromRunId}` call silently re-ran the PRIOR source and a changed
|
|
147
|
+
* `args` was dropped -- the edit loop's own door was the one input the door ignored. With neither
|
|
148
|
+
* supplied, the original launch input is replayed verbatim (the ruling's other half).
|
|
149
|
+
*/
|
|
150
|
+
resume(runId: string, sessionId: string, host: WorkflowRunHost, opts?: {
|
|
151
|
+
parentToolUseId?: string;
|
|
152
|
+
/**
|
|
153
|
+
* The edited script AND its re-parsed meta, together: `meta.name` is what the new run's task,
|
|
154
|
+
* persisted filename and `WorkflowOutput.workflowName` are built from, so carrying the source
|
|
155
|
+
* without re-parsing the meta would label the edited run with the old script's name.
|
|
156
|
+
*/
|
|
157
|
+
replacement?: {
|
|
158
|
+
source: string;
|
|
159
|
+
meta: WorkflowLaunchInput["meta"];
|
|
160
|
+
};
|
|
161
|
+
/** Supplied = the new args; OMITTED = the original launch's args, unchanged. */
|
|
162
|
+
args?: unknown;
|
|
163
|
+
}): WorkflowLaunchResult;
|
|
164
|
+
stop(runId: string): boolean;
|
|
165
|
+
get(runId: string): WorkflowRunView | undefined;
|
|
166
|
+
list(sessionId: string): WorkflowRunView[];
|
|
167
|
+
/** Resolves when the run reaches a terminal state. An already-terminal or unknown run resolves immediately. */
|
|
168
|
+
await(runId: string): Promise<WorkflowRunView>;
|
|
169
|
+
/**
|
|
170
|
+
* Whether a run reached `stopped` (as opposed to `failed`). The frozen `WorkflowTaskHandle` has no
|
|
171
|
+
* `stop()`, so this is how a host renders the third terminal state truthfully -- see
|
|
172
|
+
* `tools/impl/workflow.ts`'s `fail` implementation.
|
|
173
|
+
*/
|
|
174
|
+
wasStopped(runId: string): boolean;
|
|
175
|
+
/** Test-only: simulates an external kill, for the crash-fallback path. */
|
|
176
|
+
killWorkerForTest(runId: string): void;
|
|
177
|
+
private onWorkerMessage;
|
|
178
|
+
private reply;
|
|
179
|
+
/**
|
|
180
|
+
* The authoritative half of every cap. Checked in this order, deliberately:
|
|
181
|
+
* 1. the TOTAL cap, before the semaphore -- a run pinned at capacity must fail fast rather than
|
|
182
|
+
* queue behind work that can never help it (Norma's original ordering, kept);
|
|
183
|
+
* 2. the BUDGET ceiling, for the same reason;
|
|
184
|
+
* 3. only then a slot.
|
|
185
|
+
*/
|
|
186
|
+
private serviceAgent;
|
|
187
|
+
/**
|
|
188
|
+
* Spawns one child and resolves what `agent()` should see.
|
|
189
|
+
*
|
|
190
|
+
* NULL, not a throw, for every terminal child OUTCOME (WS-11 §1.6: "Resolves `null` when the user
|
|
191
|
+
* skips the agent or it dies on a terminal error") -- a failed child, a stopped child, a child
|
|
192
|
+
* whose text does not validate.
|
|
193
|
+
*
|
|
194
|
+
* A `spawnAgent` that THROWS is NOT one of those (whole-branch m5). It means the HOST could not
|
|
195
|
+
* start an agent at all -- `tools/impl/workflow.ts` throws exactly that when the session has no
|
|
196
|
+
* child-spawn capability -- and `script-api.ts`'s own contract lists "no spawn capability at all"
|
|
197
|
+
* beside the agent cap and the budget ceiling as the refusals a script must not be able to
|
|
198
|
+
* swallow. This used to fold it into the same `null`, so a workflow in a session with no spawn
|
|
199
|
+
* capability "completed" with `.filter(Boolean)`-swallowed empties and the real cause appeared
|
|
200
|
+
* nowhere. It now comes back as a refusal, which `serviceAgent` turns into the same
|
|
201
|
+
* teardown-then-`ok:false` the caps use. Nothing escapes as an unhandled rejection either way.
|
|
202
|
+
*/
|
|
203
|
+
private spawnAndAwaitChild;
|
|
204
|
+
/**
|
|
205
|
+
* `agent({schema})` rides `SpawnChildRequest.outputFormat` (T3's Lane W item 5) -- the child is put
|
|
206
|
+
* on the identical `StructuredOutput` mechanism the top-level session uses, never a second one.
|
|
207
|
+
*
|
|
208
|
+
* CLOSED by RULING P5-I (Phase 5 fix wave). `ChildResult.structuredOutput` now carries the child's
|
|
209
|
+
* own validated object, so `agent({schema})` returns it directly. This function is the FALLBACK
|
|
210
|
+
* for a child that produced none: it parses the child's text and re-validates it through
|
|
211
|
+
* `host.structured` -- the same validator, so no second opinion is introduced -- and resolves NULL
|
|
212
|
+
* when there is nothing valid, which is the "died on a terminal error" arm of the same rule.
|
|
213
|
+
*
|
|
214
|
+
* The gap it used to be: `child-engine.ts`'s `observe` read `message.result`, which the engine's
|
|
215
|
+
* structured SUCCESS variant does not set (it carries `structured_output` and no `result`), so a
|
|
216
|
+
* child forced onto `StructuredOutput` -- which is every schema'd call -- resolved `null`.
|
|
217
|
+
*/
|
|
218
|
+
private validateStructured;
|
|
219
|
+
private buildSpawnRequest;
|
|
220
|
+
/**
|
|
221
|
+
* `agentType` and `effort` BOTH arrive as the child's DEFINITION, because that is the only route
|
|
222
|
+
* either has: `SpawnChildRequest` carries `definition` and no `effort` at all, and engine.ts's own
|
|
223
|
+
* `buildChildInheritance` reads effort exclusively from `req.definition?.effort` (engine.ts:1236,
|
|
224
|
+
* whose comment says so outright: "AgentInput/SpawnChildRequest carry no effort field at all").
|
|
225
|
+
*
|
|
226
|
+
* With `effort` and no `agentType`, a MINIMAL definition is synthesized. That is safe rather than
|
|
227
|
+
* clever: `buildChildInheritance`'s base for a bare child is already `systemPrompt: ""`, an absent
|
|
228
|
+
* `tools` inherits the parent's whole advertised pool, and an absent `permissionMode` changes
|
|
229
|
+
* nothing -- so the synthesized definition differs from a bare child in exactly the one field it
|
|
230
|
+
* exists to carry.
|
|
231
|
+
*/
|
|
232
|
+
private resolveChildDefinition;
|
|
233
|
+
/** A nested `workflow(nameOrRef)`: resolved PARENT-side, because the worker can read no files. */
|
|
234
|
+
private serviceNestedWorkflow;
|
|
235
|
+
/**
|
|
236
|
+
* `phase` is the group this progress report belongs to (F2): an agent's own `opts.phase` when it
|
|
237
|
+
* supplied one, otherwise the run's current global phase. Passing it explicitly is the whole point
|
|
238
|
+
* -- WS-11 §1.6 gives `opts.phase` the job of "avoiding races on the global `phase()` state inside
|
|
239
|
+
* `pipeline`/`parallel` stages", and reading the ambient phase here would reintroduce exactly that
|
|
240
|
+
* race for two agents running concurrently under different phases.
|
|
241
|
+
*/
|
|
242
|
+
private syncCounts;
|
|
243
|
+
/**
|
|
244
|
+
* `usage` is filled on EVERY progress report, not just where it is convenient. `WorkflowProgress`
|
|
245
|
+
* types it optional, but the pinned `task_progress` message it lands on makes the triple REQUIRED
|
|
246
|
+
* (frames.ts) -- so a host mapping this to the wire would otherwise have to invent the numbers.
|
|
247
|
+
* All three are real readings: tokens from the session accountant, `tool_uses` from this run's own
|
|
248
|
+
* agent count, `duration_ms` from the parent's wall clock (the worker has no clock -- `Date.now` is
|
|
249
|
+
* withheld inside it by design).
|
|
250
|
+
*/
|
|
251
|
+
private emitProgress;
|
|
252
|
+
private teardown;
|
|
253
|
+
private finish;
|
|
254
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type SandboxBrand } from "../sandbox/profile.js";
|
|
2
|
+
import { WORKFLOW_WORKER_ARGV_FLAG, WORKFLOW_WORKER_BRIDGE_FLAG } from "./subprocess-entry.js";
|
|
3
|
+
export { WORKFLOW_WORKER_ARGV_FLAG, WORKFLOW_WORKER_BRIDGE_FLAG };
|
|
4
|
+
declare const SANDBOX_EXEC_PATH = "/usr/bin/sandbox-exec";
|
|
5
|
+
export interface WorkerCommand {
|
|
6
|
+
file: string;
|
|
7
|
+
args: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface ResolveWorkerCommandOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Overridable for tests; defaults to a real detection of the single-file `$bunfs` executable.
|
|
12
|
+
* Stating either field bypasses a host command installed by `setHostWorkflowWorkerCommand`.
|
|
13
|
+
*/
|
|
14
|
+
compiled?: boolean;
|
|
15
|
+
execPath?: string;
|
|
16
|
+
}
|
|
17
|
+
/** True inside a `bun build --compile` single-file executable. */
|
|
18
|
+
export declare function isCompiledBinary(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Install the host's workflow-worker command for this realm; returns a restore function. `undefined`
|
|
21
|
+
* clears it (the default applies again). The command is copied, so a caller mutating its own object
|
|
22
|
+
* afterwards changes nothing here.
|
|
23
|
+
*/
|
|
24
|
+
export declare function setHostWorkflowWorkerCommand(command: WorkerCommand | undefined): () => void;
|
|
25
|
+
export declare function resolveWorkerCommand(opts?: ResolveWorkerCommandOptions): WorkerCommand;
|
|
26
|
+
export interface BuildWorkerSpawnOptions {
|
|
27
|
+
command: WorkerCommand;
|
|
28
|
+
/**
|
|
29
|
+
* The session's WINTER HOME. Supplying it is what emits the run-directory read-deny (R5-5);
|
|
30
|
+
* `undefined` opts out EXPLICITLY, which is the only way to opt out now that the profile builder's
|
|
31
|
+
* own argument is required. Every production call site passes a real value, and worker.test.ts pins
|
|
32
|
+
* the difference between the two profiles.
|
|
33
|
+
*/
|
|
34
|
+
home?: string;
|
|
35
|
+
/**
|
|
36
|
+
* The RESOLVED Winter home (fix wave I1, the resolved-home class): when it is not
|
|
37
|
+
* `<home>/<homeDirName>`, the profile ALSO denies `<winterHome>/run` -- a `<PREFIX>HOME` pointing
|
|
38
|
+
* at a differently-named root is otherwise unprotected. Both anchors are emitted; overlapping
|
|
39
|
+
* denies cost nothing.
|
|
40
|
+
*/
|
|
41
|
+
winterHome?: string;
|
|
42
|
+
/** P7a (D19): the session's brand -- the dot-dir names the worker profile fences. */
|
|
43
|
+
brand?: SandboxBrand;
|
|
44
|
+
}
|
|
45
|
+
/** The actual `(file, args)` to spawn: sandbox-exec wrapping the worker command under the tight profile. */
|
|
46
|
+
export declare function buildWorkerSpawn(opts: BuildWorkerSpawnOptions): WorkerCommand;
|
|
47
|
+
/** WS-12 §3's own availability rule, reused rather than re-derived. */
|
|
48
|
+
export declare function workflowSandboxAvailable(): boolean;
|
|
49
|
+
export { SANDBOX_EXEC_PATH };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type JournalEntry } from "./journal.js";
|
|
2
|
+
import type { BudgetSnapshot } from "./budget.js";
|
|
3
|
+
import type { AgentOpts } from "./types.js";
|
|
4
|
+
import type { WorkflowRef } from "./bridge.js";
|
|
5
|
+
/**
|
|
6
|
+
* What the bridge answers for one `agent()` call.
|
|
7
|
+
*
|
|
8
|
+
* The `ok: true, value: null` / `ok: false` split IS the WS-11 §1.6 contract, expressed in the type:
|
|
9
|
+
* a skipped or terminally-failed agent RESOLVES null (so `.filter(Boolean)` works, which is what the
|
|
10
|
+
* spec tells authors to write), while a refusal the script must not be able to swallow -- the agent
|
|
11
|
+
* cap, the budget ceiling, no spawn capability at all -- comes back `ok: false` and THROWS.
|
|
12
|
+
*/
|
|
13
|
+
export type AgentBridgeResult = {
|
|
14
|
+
ok: true;
|
|
15
|
+
value: unknown;
|
|
16
|
+
budget?: BudgetSnapshot;
|
|
17
|
+
} | {
|
|
18
|
+
ok: false;
|
|
19
|
+
error: string;
|
|
20
|
+
budget?: BudgetSnapshot;
|
|
21
|
+
};
|
|
22
|
+
export type WorkflowResolveResult = {
|
|
23
|
+
ok: true;
|
|
24
|
+
source: string;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
error: string;
|
|
28
|
+
};
|
|
29
|
+
export interface ScriptApiDeps {
|
|
30
|
+
source: string;
|
|
31
|
+
args: unknown;
|
|
32
|
+
concurrency: number;
|
|
33
|
+
totalAgentCap: number;
|
|
34
|
+
maxItemsPerCall: number;
|
|
35
|
+
budget: BudgetSnapshot;
|
|
36
|
+
agent(prompt: string, opts?: AgentOpts): Promise<AgentBridgeResult>;
|
|
37
|
+
/** Resolves a nested `workflow(nameOrRef)` to its SOURCE. Parent-side: the worker cannot read the project workflows dir. */
|
|
38
|
+
resolveWorkflow(ref: WorkflowRef, args: unknown): Promise<WorkflowResolveResult>;
|
|
39
|
+
phase(title: string): void;
|
|
40
|
+
log(message: string): void;
|
|
41
|
+
/** F8: called ONCE, with how many leading `agent()` calls replayed from the resume journal. */
|
|
42
|
+
reportCachedPrefix?(count: number): void;
|
|
43
|
+
/** WS-11 §1.5: the prior run's ordered `agent()` results. Absent/empty for a fresh run. */
|
|
44
|
+
resumeJournal?: JournalEntry[];
|
|
45
|
+
}
|
|
46
|
+
export interface ScriptRunResult {
|
|
47
|
+
meta: unknown;
|
|
48
|
+
result: unknown;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Compiles and runs one workflow body, returning its captured `meta` and its `return` value.
|
|
52
|
+
*
|
|
53
|
+
* Throws only for the conditions WS-11 §1.6/§1.8 say must throw: a syntax error, a determinism-guard
|
|
54
|
+
* violation, a cap breach, a budget ceiling, an unresolvable or over-nested `workflow()`, or whatever
|
|
55
|
+
* the body itself threw. Everything a script is meant to be able to absorb (`parallel`'s failing
|
|
56
|
+
* thunk, a skipped agent) resolves instead.
|
|
57
|
+
*/
|
|
58
|
+
export declare function runWorkflowScript(deps: ScriptApiDeps): Promise<ScriptRunResult>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { ContextAccountant } from "../engine.js";
|
|
2
|
+
import type { ChildHandle, SpawnChildRequest } from "../subagents/child-handle.js";
|
|
3
|
+
import type { StructuredOutputSeam } from "../structured/seam.js";
|
|
4
|
+
/**
|
|
5
|
+
* A running workflow's progress. WINTER-DEFINED (the pinned surface has no workflow-progress type),
|
|
6
|
+
* but shaped to land on the pinned `task_progress` message without a second mapping: that message's
|
|
7
|
+
* `usage` triple is REQUIRED and is `{total_tokens, tool_uses, duration_ms}`, so a progress report
|
|
8
|
+
* that could not fill all three would produce a frame the pin cannot accept.
|
|
9
|
+
*
|
|
10
|
+
* `running`/`completed`/`total` are WS-11 §1.8's own step counters.
|
|
11
|
+
*/
|
|
12
|
+
export interface WorkflowProgress {
|
|
13
|
+
running: number;
|
|
14
|
+
completed: number;
|
|
15
|
+
total: number;
|
|
16
|
+
/** Free-form, model-facing; lands on `task_progress.summary`. */
|
|
17
|
+
summary?: string;
|
|
18
|
+
/** Lands on `task_progress.last_tool_name`. */
|
|
19
|
+
lastToolName?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Phase 5 Task 8 (rider 27): the PHASE GROUP this report belongs to, structurally.
|
|
22
|
+
*
|
|
23
|
+
* Lane W's NEEDS_CONTEXT 7: WS-11 §1.2's "an unmatched `phase()` gets its own group" was honoured
|
|
24
|
+
* in the runtime's own state and reflected in the progress TEXT (`"Title: detail"` for a declared
|
|
25
|
+
* phase versus a bare `"Title"` for an ad-hoc one), but a host rendering a progress tree could not
|
|
26
|
+
* reconstruct the grouping -- it had to parse prose, and a declared phase whose entry carries no
|
|
27
|
+
* `detail` renders identically to an ad-hoc one, so the prose is not even a reliable signal.
|
|
28
|
+
*
|
|
29
|
+
* `declaredPhase` distinguishes the two cases the text cannot.
|
|
30
|
+
*
|
|
31
|
+
* WHAT THIS DOES NOT DO, stated at the field because a reader will look for it: neither value
|
|
32
|
+
* reaches the WIRE. The pinned `task_progress` message (WS-06 §3.5) carries
|
|
33
|
+
* `summary`/`last_tool_name`/`usage` and no phase field, and putting a Winter-invented key on a
|
|
34
|
+
* pinned frame is precisely the divergence class this phase refuses. So the grouping is legible to
|
|
35
|
+
* a host that consumes the SEAM, and on the wire it remains prose. Closing that half needs either
|
|
36
|
+
* a captured pinned field or a deliberate disclosed extension -- neither of which T8 may invent.
|
|
37
|
+
*/
|
|
38
|
+
phase?: string;
|
|
39
|
+
/** True when `phase` matched a declared `meta.phases` entry rather than being an ad-hoc `phase()` call. */
|
|
40
|
+
declaredPhase?: boolean;
|
|
41
|
+
usage?: {
|
|
42
|
+
total_tokens: number;
|
|
43
|
+
tool_uses: number;
|
|
44
|
+
duration_ms: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The handle one workflow RUN holds. `complete`/`fail` are terminal and idempotent -- a worker that
|
|
49
|
+
* crashes after reporting completion must not be able to re-fail its own task (WS-11 §1.8's
|
|
50
|
+
* `running -> completed | failed | stopped` is a one-way lifecycle).
|
|
51
|
+
*/
|
|
52
|
+
export interface WorkflowTaskHandle {
|
|
53
|
+
taskId: string;
|
|
54
|
+
emit(progress: WorkflowProgress): void;
|
|
55
|
+
complete(result: unknown): void;
|
|
56
|
+
fail(error: string): void;
|
|
57
|
+
}
|
|
58
|
+
export interface WorkflowRunHost {
|
|
59
|
+
/**
|
|
60
|
+
* Registers this run as a background task. `kind` is the single literal `"workflow"` -- Winter's
|
|
61
|
+
* INTERNAL `BackgroundTaskKind` spelling. It is NOT what goes on the wire: capture (3) and item (g)
|
|
62
|
+
* both pin `task_started.task_type` / `WorkflowOutput.taskType` as `"local_workflow"`, and
|
|
63
|
+
* `tools/background-tasks.ts`'s own `wireTaskType(kind)` is the one mapping between them. A lane
|
|
64
|
+
* that hand-writes either spelling at an emission site is the drift this split exists to prevent.
|
|
65
|
+
*/
|
|
66
|
+
createTask(kind: "workflow", meta: {
|
|
67
|
+
runId: string;
|
|
68
|
+
name: string;
|
|
69
|
+
}): WorkflowTaskHandle;
|
|
70
|
+
/** Spawns a child agent -- the SAME path the Agent tool uses, so `agent({schema})` rides `outputFormat` through `SpawnChildRequest` rather than a parallel mechanism. */
|
|
71
|
+
spawnAgent(req: SpawnChildRequest): Promise<ChildHandle>;
|
|
72
|
+
/** Schema validation, borrowed from Lane K (R5-12's named W->K coupling) -- never a second validator. */
|
|
73
|
+
structured: StructuredOutputSeam;
|
|
74
|
+
/** The session's context accounting -- what a workflow's `budget` ceiling reads. */
|
|
75
|
+
accountant: ContextAccountant;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The spine's test double: an in-memory host recording tasks, progress and terminal calls. It spawns
|
|
79
|
+
* no processes and creates no files, so a lane can exercise its orchestration logic long before its
|
|
80
|
+
* real subprocess runtime works.
|
|
81
|
+
*/
|
|
82
|
+
export declare function fakeWorkflowRunHost(deps: {
|
|
83
|
+
structured: StructuredOutputSeam;
|
|
84
|
+
accountant: ContextAccountant;
|
|
85
|
+
spawnAgent?: (req: SpawnChildRequest) => Promise<ChildHandle>;
|
|
86
|
+
log?: Array<{
|
|
87
|
+
kind: string;
|
|
88
|
+
taskId: string;
|
|
89
|
+
event: "created" | "progress" | "complete" | "fail";
|
|
90
|
+
detail?: unknown;
|
|
91
|
+
}>;
|
|
92
|
+
}): WorkflowRunHost;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** The ceiling half of `min(16, CPUs - 2)`. Exported so a test asserts the CONSTANT, not a re-derived literal. */
|
|
2
|
+
export declare const DEFAULT_MAX_CONCURRENCY = 16;
|
|
3
|
+
/**
|
|
4
|
+
* WS-11 §1.6: "concurrent `agent()` calls `min(16, CPUs - 2)` per run (excess queue and run as slots
|
|
5
|
+
* free)".
|
|
6
|
+
*
|
|
7
|
+
* Floored at 1: on a 1- or 2-core machine `CPUs - 2` is 0 or negative, and a semaphore with zero
|
|
8
|
+
* permits deadlocks every run that calls `agent()` even once -- silently, with no error, forever.
|
|
9
|
+
* The floor is the difference between "slow on a small machine" and "broken on a small machine".
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveConcurrencyCap(cpuCount?: number): number;
|
|
12
|
+
export interface Semaphore {
|
|
13
|
+
acquire(): Promise<void>;
|
|
14
|
+
release(): void;
|
|
15
|
+
}
|
|
16
|
+
export declare function makeSemaphore(max: number): Semaphore;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { type BrandProfile, type SettingSource } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
import { type WorkflowMetaPhase } from "./meta.js";
|
|
3
|
+
/** The project workflows directory for a brand -- `<brand.projectDirName>/workflows`. */
|
|
4
|
+
export declare function projectWorkflowsDir(brand?: Pick<BrandProfile, "projectDirName">): string;
|
|
5
|
+
/** Winter's own value, for every caller that has not threaded a brand. */
|
|
6
|
+
export declare const PROJECT_WORKFLOWS_DIR: string;
|
|
7
|
+
export type ResolvedWorkflowSource = {
|
|
8
|
+
ok: true;
|
|
9
|
+
source: string;
|
|
10
|
+
path: string | undefined;
|
|
11
|
+
source_kind: "project" | "user" | "builtin" | "plugin";
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
error: string;
|
|
15
|
+
};
|
|
16
|
+
/** A minimal projection of `plugins/bundle.ts`'s `PluginBundle` -- only the fields workflow resolution needs. */
|
|
17
|
+
export interface PluginWorkflowSource {
|
|
18
|
+
name: string;
|
|
19
|
+
workflowsPath?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Fix round 4 (minors, M-3's last bullet): the manifest's own `workflows` override -- see
|
|
22
|
+
* `PluginBundle.workflowsPaths`'s own comment for why this is mutually exclusive with
|
|
23
|
+
* `workflowsPath` above rather than additive to it. `pluginWorkflowSourcePaths` below is where the
|
|
24
|
+
* two are combined into the single list every scan actually walks.
|
|
25
|
+
*/
|
|
26
|
+
workflowsPaths?: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Shared by `resolveWorkflowByName` and `listWorkflowsForListing` -- resolution and listing read the
|
|
30
|
+
* SAME tiers under the SAME gates, so they can never disagree about what exists.
|
|
31
|
+
*/
|
|
32
|
+
export interface WorkflowDiscoveryOptions {
|
|
33
|
+
cwd: string;
|
|
34
|
+
/**
|
|
35
|
+
* TRUST-GATED, deliberately, and this is a disclosed judgment call (see the lane report).
|
|
36
|
+
*
|
|
37
|
+
* A project `workflows/*.js` file is EXECUTABLE CODE a project supplies and the model runs -- the
|
|
38
|
+
* same category as a project `agents/*.md`, which RULING R4-7 keeps trust-gated, and not the
|
|
39
|
+
* category of skills/commands/instructions, which P5-T1 capture (b) makes merely SOURCE-gated. Norma
|
|
40
|
+
* trust-gated its own project workflow directory for the same reason. The consequence is real and
|
|
41
|
+
* worth stating: in an untrusted workspace `name` resolves nothing, so a freshly-cloned repo's
|
|
42
|
+
* workflows do not run until the workspace is trusted. `script`/`scriptPath` are unaffected.
|
|
43
|
+
*
|
|
44
|
+
* A PLUGIN workflow (below) is DELIBERATELY NOT gated on this bit, for the identical reason every
|
|
45
|
+
* other plugin-contributed resource in this codebase (skills, agents, commands, output styles,
|
|
46
|
+
* MCP servers) is not: a plugin is loaded because the HOST or the USER already decided to, outside
|
|
47
|
+
* the repository, so gating it on workspace trust would make plugin behaviour depend on which
|
|
48
|
+
* directory the session happens to be in. The USER tier (below) is not gated on this bit either,
|
|
49
|
+
* for the same reason skills' user tier is not (skills/store.ts's header).
|
|
50
|
+
*/
|
|
51
|
+
trustedWorkspace: boolean;
|
|
52
|
+
/** P7a (D19): the session's brand -- the project dot-dir workflows live under. Omitted = `WINTER_BRAND`. */
|
|
53
|
+
brand?: Pick<BrandProfile, "projectDirName">;
|
|
54
|
+
/**
|
|
55
|
+
* WS-21 §6.3 item 1 (fix round 2): the session's ENABLED plugins that ship a `workflows/`
|
|
56
|
+
* directory. Omitted (every pre-fix-round-2 caller) means a `<plugin>:<name>` name simply falls
|
|
57
|
+
* through to "unknown workflow", exactly as it did before this field existed.
|
|
58
|
+
*/
|
|
59
|
+
pluginWorkflows?: readonly PluginWorkflowSource[];
|
|
60
|
+
/**
|
|
61
|
+
* SV-5 fix round 3: the RESOLVED winter root (`SkillIndexOptions.winterHome`'s identical
|
|
62
|
+
* convention and identical naming rationale) -- `<winterHome>/workflows` is the user tier.
|
|
63
|
+
* Omitted means no user tier is read (every pre-fix-round-3 caller), not an error.
|
|
64
|
+
*/
|
|
65
|
+
winterHome?: string | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Fix round 3 (I-4): source gating, mirroring `skills/store.ts`'s `sourcesAllow` exactly.
|
|
68
|
+
* Omitted = all tiers allowed (claude's own `settingSources` default). A caller that wants the
|
|
69
|
+
* project workflows directory (`projectWorkflowsDir`) un-read when the run's `settingSources`
|
|
70
|
+
* excludes `"project"` -- e.g. a `settingSources:["user"]` run that is ALSO
|
|
71
|
+
* `trustedWorkspace:true` -- must pass it; nothing derives it from `trustedWorkspace`, which is a
|
|
72
|
+
* different, narrower gate (R4-7) than this one.
|
|
73
|
+
*/
|
|
74
|
+
settingSources?: readonly SettingSource[] | undefined;
|
|
75
|
+
}
|
|
76
|
+
export interface ResolveWorkflowByNameOptions extends WorkflowDiscoveryOptions {
|
|
77
|
+
/** Injectable for the test that proves built-ins are consulted first; production passes nothing. */
|
|
78
|
+
builtins?: Record<string, string>;
|
|
79
|
+
}
|
|
80
|
+
export declare function listBuiltinWorkflows(): string[];
|
|
81
|
+
/** Built-ins first, then a plugin (WS-21 §6.3 item 1), the trusted project directory, or the user directory. Never throws. */
|
|
82
|
+
export declare function resolveWorkflowByName(name: string, opts: ResolveWorkflowByNameOptions): ResolvedWorkflowSource;
|
|
83
|
+
export interface WorkflowListingEntry {
|
|
84
|
+
name: string;
|
|
85
|
+
description: string;
|
|
86
|
+
source: "project" | "user" | "plugin";
|
|
87
|
+
/** The script's real filesystem path -- carried through so a caller building a `SkillMeta`-shaped synthetic entry (production-wiring.ts) never has to invent one. */
|
|
88
|
+
path: string;
|
|
89
|
+
/** Fix round 4 (I-E): carried through for a synthetic skill/command prompt's own structure -- claude's own `m()` includes both alongside name/description. */
|
|
90
|
+
whenToUse?: string;
|
|
91
|
+
phases?: WorkflowMetaPhase[];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* SV-5 (batch-2, second round, extended in fix round 3) -- the router same-view test: the pinned
|
|
95
|
+
* binary lists EVERY discovered workflow (user + project + plugin; built-in excluded, the pinned
|
|
96
|
+
* binary's own `d()`/`Ru()` gate that separately and Winter ships none -- see `BUILTIN_WORKFLOWS`)
|
|
97
|
+
* in the init `skills`/`slash_commands` fields and the model-facing Skill listing, named
|
|
98
|
+
* `<plugin>:<meta.name>` for a plugin workflow or bare `<meta.name>` for a user/project one --
|
|
99
|
+
* `getWorkflowCommands` in the pinned binary's own workflow-discovery module maps its FULL discovery
|
|
100
|
+
* result through a `{type:"prompt", name: o.name, description: o.description, ...}` projection,
|
|
101
|
+
* `o.name` already being the qualified/bare identity discovery assigned. `production-wiring.ts` is
|
|
102
|
+
* the one caller, folding this into all three listing surfaces.
|
|
103
|
+
*
|
|
104
|
+
* ORDER matches claude's own final merge in `j()`/`QX()`: plugin entries first (builtins would lead,
|
|
105
|
+
* but Winter has none to list), then user+project merged and name-sorted -- a project entry
|
|
106
|
+
* overriding a user entry of the same name the same way resolution above does, so listing and
|
|
107
|
+
* resolution can never disagree about which tier's copy is "the" workflow of that name.
|
|
108
|
+
*/
|
|
109
|
+
export declare function listWorkflowsForListing(opts: WorkflowDiscoveryOptions): WorkflowListingEntry[];
|
|
110
|
+
/**
|
|
111
|
+
* Fix round 4 (I-E, the router same-view test): claude's own `m()` (dump-confirmed) turns every
|
|
112
|
+
* discovered workflow into a `{type:"prompt", kind:"workflow", ...}` command whose PROMPT runs the
|
|
113
|
+
* named workflow and carries the description, `whenToUse` and phases, ending with an instruction to
|
|
114
|
+
* invoke the Workflow tool by name. `SkillMeta` has no dedicated "workflow" shape, so this builds the
|
|
115
|
+
* BODY TEXT `SkillIndex`'s own synthetic-entry seam (`SkillIndexOptions.syntheticSkills`) stores for
|
|
116
|
+
* `Skill("<name>")` to return -- the WS-11 §2.3 contract ("invocation inserts the resolved skill
|
|
117
|
+
* instructions into the main conversation") applied to a workflow instead of a SKILL.md body.
|
|
118
|
+
*
|
|
119
|
+
* THE PROMPT TEXT IS WINTER-AUTHORED, per the user's own ruling that prompts stay Winter's own
|
|
120
|
+
* wording while INTERFACE strings (a field name, a listing label, an error message) may ship
|
|
121
|
+
* verbatim from the pinned binary -- this is prompt content the model reads and acts on, not an
|
|
122
|
+
* interface string, so it is worded fresh here rather than reproduced from the dump. The
|
|
123
|
+
* STRUCTURE claude's own `m()` carries (name, description, `whenToUse`, phases, then the invoke
|
|
124
|
+
* instruction) is preserved; the wording is not claude's.
|
|
125
|
+
*
|
|
126
|
+
* Fix round 5 (promoted minor, the re-review of 57e7fef..20b623e): `/plugin:name some args` must
|
|
127
|
+
* carry `some args` into the invoke line as `Workflow({ name, args })`, matching claude. This
|
|
128
|
+
* body is a SINGLE static string shared by BOTH the `Skill` tool door and the `/name args`
|
|
129
|
+
* slash-command door -- and only the LATTER substitutes `$ARGUMENTS`/`$ARGUMENTS_JSON`
|
|
130
|
+
* (`commands/resolver.ts`'s own "DISCLOSED ASYMMETRY" header: the Skill tool hands a body over
|
|
131
|
+
* verbatim, never substituting). Baking an args token into the ONE unconditional invoke line would
|
|
132
|
+
* leave it literal, unsubstituted, in what the model sees through the Skill-tool door, which is
|
|
133
|
+
* worse than dropping args entirely. So the args-carrying line is a SECOND, explicitly CONDITIONAL
|
|
134
|
+
* sentence: it still contains the literal token (nothing else can make the slash-command door's
|
|
135
|
+
* substitution reach it), but is worded so a model reading it unsubstituted (the Skill-tool door, or
|
|
136
|
+
* a bare `/name` with nothing after it, where the tokens substitute to `""`/`'""'`) recognises it
|
|
137
|
+
* does not apply and falls back to the first, unconditional line instead.
|
|
138
|
+
*
|
|
139
|
+
* Fix round 6 (a promoted minor, the re-review against the pinned 2.1.250 dump): the args value must
|
|
140
|
+
* be ESCAPED the way claude's own `S(e)` does, matching `createWorkflowCommand`'s
|
|
141
|
+
* `getPromptForCommand` (dump-confirmed: `a=e?\`{ name: ${i}, args: ${S(e)} }\`:...\`, i=S(o.name)`
|
|
142
|
+
* -- inferred to be JSON-string-quoting from the call-site shape: applied to a plain, always-defined
|
|
143
|
+
* string, used with no additional quotes around it). Using the RAW `$ARGUMENTS` token inside
|
|
144
|
+
* hand-written quotes (round 5's own shape) would let a literal `"` or `\` in the typed args break
|
|
145
|
+
* out of the quoted literal. `$ARGUMENTS_JSON` (`commands/resolver.ts`'s new second token) substitutes
|
|
146
|
+
* with `JSON.stringify(args)` instead -- already quoted and escaped -- so this line writes NO quotes
|
|
147
|
+
* of its own around it.
|
|
148
|
+
*/
|
|
149
|
+
export declare function buildWorkflowSkillPrompt(entry: WorkflowListingEntry): string;
|
|
150
|
+
export interface SessionScriptLocation {
|
|
151
|
+
/** The resolved winter root in production (`resolveWinterHome()`), whose `projects/` child this addresses. */
|
|
152
|
+
winterHome: string;
|
|
153
|
+
projectKey: string;
|
|
154
|
+
/** The session UUID -- the `<session-uuid>` segment of capture (3)'s path. */
|
|
155
|
+
sessionId: string;
|
|
156
|
+
}
|
|
157
|
+
export interface PersistWorkflowScriptInput extends SessionScriptLocation {
|
|
158
|
+
/** `meta.name` (capture (3): `<meta.name>-<runId>.js`). */
|
|
159
|
+
name: string;
|
|
160
|
+
runId: string;
|
|
161
|
+
source: string;
|
|
162
|
+
}
|
|
163
|
+
/** Writes the script and returns its absolute path. Overwrites for the same run, so one run keeps one path. */
|
|
164
|
+
export declare function persistWorkflowScript(input: PersistWorkflowScriptInput): string;
|
|
165
|
+
/** Capture (3)'s sibling: `<session>/subagents/workflows/<runId>` -- what `WorkflowOutput.transcriptDir` reports. */
|
|
166
|
+
export declare function workflowTranscriptDir(input: SessionScriptLocation & {
|
|
167
|
+
runId: string;
|
|
168
|
+
}): string;
|
|
169
|
+
/**
|
|
170
|
+
* The JOURNAL root -- under the SESSION TEMP directory, not the durable projects area.
|
|
171
|
+
*
|
|
172
|
+
* Deliberate, and disclosed. `resumeFromRunId` is SAME-SESSION-ONLY by contract (WS-11 §1.5,
|
|
173
|
+
* `sdk-tools.d.ts:2786`), so a journal has no job to do once the session ends; capture (3) pinned the
|
|
174
|
+
* durable location of the SCRIPT and says nothing about a journal; and WS-01 forbids inventing a new
|
|
175
|
+
* durable directory name. Session temp is the D18 layout's own answer for per-session working state.
|
|
176
|
+
*/
|
|
177
|
+
export declare function workflowRunsDir(sessionTempDir: string): string;
|