@loopingai/core 0.1.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/LICENSE +674 -0
- package/README.md +279 -0
- package/dist/a2a/agent-stub.d.ts +61 -0
- package/dist/a2a/agent-stub.d.ts.map +1 -0
- package/dist/a2a/agent-stub.js +2 -0
- package/dist/a2a/agent-stub.js.map +1 -0
- package/dist/a2a/card.d.ts +119 -0
- package/dist/a2a/card.d.ts.map +1 -0
- package/dist/a2a/card.js +115 -0
- package/dist/a2a/card.js.map +1 -0
- package/dist/a2a/context.d.ts +14 -0
- package/dist/a2a/context.d.ts.map +1 -0
- package/dist/a2a/context.js +55 -0
- package/dist/a2a/context.js.map +1 -0
- package/dist/a2a/executor.d.ts +85 -0
- package/dist/a2a/executor.d.ts.map +1 -0
- package/dist/a2a/executor.js +107 -0
- package/dist/a2a/executor.js.map +1 -0
- package/dist/a2a/index.d.ts +18 -0
- package/dist/a2a/index.d.ts.map +1 -0
- package/dist/a2a/index.js +17 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/a2a/notify.d.ts +75 -0
- package/dist/a2a/notify.d.ts.map +1 -0
- package/dist/a2a/notify.js +161 -0
- package/dist/a2a/notify.js.map +1 -0
- package/dist/a2a/parts.d.ts +46 -0
- package/dist/a2a/parts.d.ts.map +1 -0
- package/dist/a2a/parts.js +95 -0
- package/dist/a2a/parts.js.map +1 -0
- package/dist/a2a/task-store.d.ts +45 -0
- package/dist/a2a/task-store.d.ts.map +1 -0
- package/dist/a2a/task-store.js +100 -0
- package/dist/a2a/task-store.js.map +1 -0
- package/dist/a2a/task.d.ts +86 -0
- package/dist/a2a/task.d.ts.map +1 -0
- package/dist/a2a/task.js +16 -0
- package/dist/a2a/task.js.map +1 -0
- package/dist/a2a/verify.d.ts +64 -0
- package/dist/a2a/verify.d.ts.map +1 -0
- package/dist/a2a/verify.js +122 -0
- package/dist/a2a/verify.js.map +1 -0
- package/dist/agent/budget.d.ts +47 -0
- package/dist/agent/budget.d.ts.map +1 -0
- package/dist/agent/budget.js +43 -0
- package/dist/agent/budget.js.map +1 -0
- package/dist/agent/control.d.ts +110 -0
- package/dist/agent/control.d.ts.map +1 -0
- package/dist/agent/control.js +115 -0
- package/dist/agent/control.js.map +1 -0
- package/dist/agent/final-reply.d.ts +49 -0
- package/dist/agent/final-reply.d.ts.map +1 -0
- package/dist/agent/final-reply.js +52 -0
- package/dist/agent/final-reply.js.map +1 -0
- package/dist/agent/history.d.ts +83 -0
- package/dist/agent/history.d.ts.map +1 -0
- package/dist/agent/history.js +117 -0
- package/dist/agent/history.js.map +1 -0
- package/dist/agent/index.d.ts +17 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +17 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/inference.d.ts +52 -0
- package/dist/agent/inference.d.ts.map +1 -0
- package/dist/agent/inference.js +79 -0
- package/dist/agent/inference.js.map +1 -0
- package/dist/agent/model.d.ts +75 -0
- package/dist/agent/model.d.ts.map +1 -0
- package/dist/agent/model.js +62 -0
- package/dist/agent/model.js.map +1 -0
- package/dist/agent/session.d.ts +92 -0
- package/dist/agent/session.d.ts.map +1 -0
- package/dist/agent/session.js +80 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/config.d.ts +159 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +92 -0
- package/dist/config.js.map +1 -0
- package/dist/contract/index.d.ts +10 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +9 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/plugin.d.ts +163 -0
- package/dist/contract/plugin.d.ts.map +1 -0
- package/dist/contract/plugin.js +39 -0
- package/dist/contract/plugin.js.map +1 -0
- package/dist/contract/recipe.d.ts +170 -0
- package/dist/contract/recipe.d.ts.map +1 -0
- package/dist/contract/recipe.js +2 -0
- package/dist/contract/recipe.js.map +1 -0
- package/dist/contract/validation.d.ts +86 -0
- package/dist/contract/validation.d.ts.map +1 -0
- package/dist/contract/validation.js +76 -0
- package/dist/contract/validation.js.map +1 -0
- package/dist/db/db.d.ts +131 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +91 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/index.d.ts +9 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +9 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations/index.d.ts +21 -0
- package/dist/db/migrations/index.d.ts.map +1 -0
- package/dist/db/migrations/index.js +54 -0
- package/dist/db/migrations/index.js.map +1 -0
- package/dist/db/models/subtasks.d.ts +102 -0
- package/dist/db/models/subtasks.d.ts.map +1 -0
- package/dist/db/models/subtasks.js +285 -0
- package/dist/db/models/subtasks.js.map +1 -0
- package/dist/db/models/tasks.d.ts +92 -0
- package/dist/db/models/tasks.d.ts.map +1 -0
- package/dist/db/models/tasks.js +212 -0
- package/dist/db/models/tasks.js.map +1 -0
- package/dist/db/schema.d.ts +488 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +91 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/env.d.ts +46 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +40 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/platform.d.ts +47 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +47 -0
- package/dist/platform.js.map +1 -0
- package/dist/runtime/index.d.ts +86 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +123 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/tool-families.d.ts +33 -0
- package/dist/runtime/tool-families.d.ts.map +1 -0
- package/dist/runtime/tool-families.js +62 -0
- package/dist/runtime/tool-families.js.map +1 -0
- package/dist/subagent/fingerprint.d.ts +38 -0
- package/dist/subagent/fingerprint.d.ts.map +1 -0
- package/dist/subagent/fingerprint.js +97 -0
- package/dist/subagent/fingerprint.js.map +1 -0
- package/dist/subagent/index.d.ts +147 -0
- package/dist/subagent/index.d.ts.map +1 -0
- package/dist/subagent/index.js +299 -0
- package/dist/subagent/index.js.map +1 -0
- package/dist/subagent/prompt.d.ts +34 -0
- package/dist/subagent/prompt.d.ts.map +1 -0
- package/dist/subagent/prompt.js +46 -0
- package/dist/subagent/prompt.js.map +1 -0
- package/dist/subagent/run.d.ts +151 -0
- package/dist/subagent/run.d.ts.map +1 -0
- package/dist/subagent/run.js +491 -0
- package/dist/subagent/run.js.map +1 -0
- package/dist/subagent/workspace.d.ts +65 -0
- package/dist/subagent/workspace.d.ts.map +1 -0
- package/dist/subagent/workspace.js +53 -0
- package/dist/subagent/workspace.js.map +1 -0
- package/dist/subtasks/catalog.d.ts +40 -0
- package/dist/subtasks/catalog.d.ts.map +1 -0
- package/dist/subtasks/catalog.js +36 -0
- package/dist/subtasks/catalog.js.map +1 -0
- package/dist/subtasks/decomposition.d.ts +90 -0
- package/dist/subtasks/decomposition.d.ts.map +1 -0
- package/dist/subtasks/decomposition.js +205 -0
- package/dist/subtasks/decomposition.js.map +1 -0
- package/dist/subtasks/delegate.d.ts +77 -0
- package/dist/subtasks/delegate.d.ts.map +1 -0
- package/dist/subtasks/delegate.js +102 -0
- package/dist/subtasks/delegate.js.map +1 -0
- package/dist/subtasks/index.d.ts +11 -0
- package/dist/subtasks/index.d.ts.map +1 -0
- package/dist/subtasks/index.js +11 -0
- package/dist/subtasks/index.js.map +1 -0
- package/dist/subtasks/scheduler.d.ts +49 -0
- package/dist/subtasks/scheduler.d.ts.map +1 -0
- package/dist/subtasks/scheduler.js +48 -0
- package/dist/subtasks/scheduler.js.map +1 -0
- package/dist/subtasks/subtask-types.d.ts +100 -0
- package/dist/subtasks/subtask-types.d.ts.map +1 -0
- package/dist/subtasks/subtask-types.js +111 -0
- package/dist/subtasks/subtask-types.js.map +1 -0
- package/dist/subtasks/types.d.ts +321 -0
- package/dist/subtasks/types.d.ts.map +1 -0
- package/dist/subtasks/types.js +16 -0
- package/dist/subtasks/types.js.map +1 -0
- package/dist/testing/auth.d.ts +12 -0
- package/dist/testing/auth.d.ts.map +1 -0
- package/dist/testing/auth.js +25 -0
- package/dist/testing/auth.js.map +1 -0
- package/dist/testing/do.d.ts +30 -0
- package/dist/testing/do.d.ts.map +1 -0
- package/dist/testing/do.js +26 -0
- package/dist/testing/do.js.map +1 -0
- package/dist/testing/fake-session.d.ts +27 -0
- package/dist/testing/fake-session.d.ts.map +1 -0
- package/dist/testing/fake-session.js +38 -0
- package/dist/testing/fake-session.js.map +1 -0
- package/dist/testing/fixtures.d.ts +27 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +67 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/index.d.ts +31 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +31 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-model.d.ts +43 -0
- package/dist/testing/mock-model.d.ts.map +1 -0
- package/dist/testing/mock-model.js +62 -0
- package/dist/testing/mock-model.js.map +1 -0
- package/dist/testing/node.d.ts +24 -0
- package/dist/testing/node.d.ts.map +1 -0
- package/dist/testing/node.js +24 -0
- package/dist/testing/node.js.map +1 -0
- package/dist/testing/vcr-global-setup.d.ts +3 -0
- package/dist/testing/vcr-global-setup.d.ts.map +1 -0
- package/dist/testing/vcr-global-setup.js +9 -0
- package/dist/testing/vcr-global-setup.js.map +1 -0
- package/dist/testing/vcr-shared.d.ts +21 -0
- package/dist/testing/vcr-shared.d.ts.map +1 -0
- package/dist/testing/vcr-shared.js +21 -0
- package/dist/testing/vcr-shared.js.map +1 -0
- package/dist/testing/vcr-spec.d.ts +17 -0
- package/dist/testing/vcr-spec.d.ts.map +1 -0
- package/dist/testing/vcr-spec.js +72 -0
- package/dist/testing/vcr-spec.js.map +1 -0
- package/dist/testing/vcr.d.ts +81 -0
- package/dist/testing/vcr.d.ts.map +1 -0
- package/dist/testing/vcr.js +211 -0
- package/dist/testing/vcr.js.map +1 -0
- package/dist/worker/index.d.ts +62 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +194 -0
- package/dist/worker/index.js.map +1 -0
- package/eslint-rules/index.js +31 -0
- package/eslint-rules/no-deprecated-object-properties.js +81 -0
- package/package.json +147 -0
- package/scripts/generate-keys.mjs +53 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@loopingai/core` — the mandatory foundation for a Looping agent.
|
|
3
|
+
*
|
|
4
|
+
* This root entry carries only what nearly every consumer touches: the plugin
|
|
5
|
+
* contract, the config shape, the runtime factory, and the platform facts.
|
|
6
|
+
* Everything else lives behind a subpath (`/a2a`, `/agent`, `/db`, `/subtasks`,
|
|
7
|
+
* `/subagent`, `/worker`, `/testing`), so importing the delegation layer does not
|
|
8
|
+
* pull in the A2A adapter and importing the test harness never reaches a
|
|
9
|
+
* production bundle.
|
|
10
|
+
*/
|
|
11
|
+
export { createAgentRuntime, RuntimeSetupError, buildRecipeTools, collectToolFamilies, type AgentRuntime, type CreateAgentRuntimeOptions } from "./runtime/index.js";
|
|
12
|
+
export { PLUGIN_CONTRACT_VERSION, definePlugin, type AgentPlugin, type EmitProgress, type EnrichResultContext, type PluginRequirements, type RecipeToolSet, type ResolveRuntimeContext, type ToolFamilyBuilder, type ToolFamilyContext } from "./contract/plugin.js";
|
|
13
|
+
export type { DelegationNames, RecipeLimits, ResolvedRecipe, SubtaskParams, SubtaskParamsSchema, SubtaskParamsShape, SubtaskTypeSpec, ValidatedRecipe } from "./contract/recipe.js";
|
|
14
|
+
export { RecipeValidationError, resolveLimits, validateRecipe, type RecipePolicy } from "./contract/validation.js";
|
|
15
|
+
export { ConfigError, DEFAULT_CORE_CONFIG, resolveConfig, type AgentLimits, type CoreConfig, type CoreConfigOverrides, type ModelConfig, type RecallConfig, type SessionConfig } from "./config.js";
|
|
16
|
+
export { parseGatewayOrigins, type A2ASecretsEnv, type AiEnv, type CoreEnv } from "./env.js";
|
|
17
|
+
export { CHUNK_SOFT_MS, MAX_CHUNKS_PER_BRANCH, STEP_TIMEOUT_MS, STEPS_PER_INSTANCE } from "./platform.js";
|
|
18
|
+
export type { PluginStore } from "./db/db.js";
|
|
19
|
+
export { makeWorkspaceHandle, WorkspaceLimitError, WORKSPACE_MAX_FILES, WORKSPACE_MAX_FILE_BYTES, type WorkspaceBacking, type WorkspaceEntry, type WorkspaceHandle } from "./subagent/workspace.js";
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC/B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,uBAAuB,EACvB,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,eAAe,EACf,YAAY,EACZ,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,OAAO,EACb,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@loopingai/core` — the mandatory foundation for a Looping agent.
|
|
3
|
+
*
|
|
4
|
+
* This root entry carries only what nearly every consumer touches: the plugin
|
|
5
|
+
* contract, the config shape, the runtime factory, and the platform facts.
|
|
6
|
+
* Everything else lives behind a subpath (`/a2a`, `/agent`, `/db`, `/subtasks`,
|
|
7
|
+
* `/subagent`, `/worker`, `/testing`), so importing the delegation layer does not
|
|
8
|
+
* pull in the A2A adapter and importing the test harness never reaches a
|
|
9
|
+
* production bundle.
|
|
10
|
+
*/
|
|
11
|
+
export { createAgentRuntime, RuntimeSetupError, buildRecipeTools, collectToolFamilies } from "./runtime/index.js";
|
|
12
|
+
export { PLUGIN_CONTRACT_VERSION, definePlugin } from "./contract/plugin.js";
|
|
13
|
+
export { RecipeValidationError, resolveLimits, validateRecipe } from "./contract/validation.js";
|
|
14
|
+
export { ConfigError, DEFAULT_CORE_CONFIG, resolveConfig } from "./config.js";
|
|
15
|
+
export { parseGatewayOrigins } from "./env.js";
|
|
16
|
+
export { CHUNK_SOFT_MS, MAX_CHUNKS_PER_BRANCH, STEP_TIMEOUT_MS, STEPS_PER_INSTANCE } from "./platform.js";
|
|
17
|
+
export { makeWorkspaceHandle, WorkspaceLimitError, WORKSPACE_MAX_FILES, WORKSPACE_MAX_FILE_BYTES } from "./subagent/workspace.js";
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EAGpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,uBAAuB,EACvB,YAAY,EASb,MAAM,sBAAsB,CAAC;AAa9B,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,cAAc,EAEf,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,aAAa,EAOd,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EAIpB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAIvB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EAIzB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the Cloudflare Workflows runtime imposes, and the two numbers derived from
|
|
3
|
+
* it. Nothing here is a budget or a preference — see {@link file://./config.ts}
|
|
4
|
+
* for those, and note that no Recipe can reach these. They change when the
|
|
5
|
+
* platform changes, and for no other reason.
|
|
6
|
+
*
|
|
7
|
+
* The distinction is worth keeping sharp, because collapsing it is what produced
|
|
8
|
+
* the bug this file was extracted during: a *turn count* was used to keep a step
|
|
9
|
+
* under the step timeout, which only works if you can predict how long a turn
|
|
10
|
+
* takes. You cannot. Time bounds time here; turns bound cost, over in `config.ts`.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Platform fact: a `step.do(...)` callback is killed at ~10 minutes (Workflows'
|
|
14
|
+
* default step timeout). {@link CHUNK_SOFT_MS} is sized against this.
|
|
15
|
+
*/
|
|
16
|
+
export declare const STEP_TIMEOUT_MS: number;
|
|
17
|
+
/**
|
|
18
|
+
* Platform fact: a single Workflow instance may run ~10,000 steps (paid plan).
|
|
19
|
+
* {@link MAX_CHUNKS_PER_BRANCH} is sized against this — see the worst-case
|
|
20
|
+
* product asserted in `platform.spec.ts`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const STEPS_PER_INSTANCE = 10000;
|
|
23
|
+
/**
|
|
24
|
+
* How long one durable chunk may run before it checkpoints and yields a fresh
|
|
25
|
+
* step. Comfortably inside {@link STEP_TIMEOUT_MS} so a slow model turn in flight
|
|
26
|
+
* when the soft limit trips still has room to finish.
|
|
27
|
+
*
|
|
28
|
+
* This is the *only* thing keeping a step under the timeout. A subagent otherwise
|
|
29
|
+
* runs until its turn or wall-clock budget is spent, however many turns that takes
|
|
30
|
+
* — which is the point: the runner no longer guesses at turn duration.
|
|
31
|
+
*/
|
|
32
|
+
export declare const CHUNK_SOFT_MS: number;
|
|
33
|
+
/**
|
|
34
|
+
* Hard ceiling on durable chunk steps for one Subtask branch. A backstop, not a
|
|
35
|
+
* budget: the Workflow *fails* a branch that reaches it, so reaching it is a bug.
|
|
36
|
+
* It is held unreachable by two constraints, both asserted in
|
|
37
|
+
* `platform.spec.ts`:
|
|
38
|
+
*
|
|
39
|
+
* 1. It exceeds every Recipe's `maxTurns`. A chunk that yields always advanced at
|
|
40
|
+
* least one turn, so a run takes at most `maxTurns` chunks however short they
|
|
41
|
+
* are — and they do get short, because `CHUNK_SOFT_MS` and progress events both
|
|
42
|
+
* end one early. That bound survives both; a nominal `maxTurns / turnsPerChunk`
|
|
43
|
+
* estimate survived neither, which is why no such estimate exists any more.
|
|
44
|
+
* 2. The worst-case step product stays under {@link STEPS_PER_INSTANCE}.
|
|
45
|
+
*/
|
|
46
|
+
export declare const MAX_CHUNKS_PER_BRANCH = 40;
|
|
47
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAc,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAAa,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC"}
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the Cloudflare Workflows runtime imposes, and the two numbers derived from
|
|
3
|
+
* it. Nothing here is a budget or a preference — see {@link file://./config.ts}
|
|
4
|
+
* for those, and note that no Recipe can reach these. They change when the
|
|
5
|
+
* platform changes, and for no other reason.
|
|
6
|
+
*
|
|
7
|
+
* The distinction is worth keeping sharp, because collapsing it is what produced
|
|
8
|
+
* the bug this file was extracted during: a *turn count* was used to keep a step
|
|
9
|
+
* under the step timeout, which only works if you can predict how long a turn
|
|
10
|
+
* takes. You cannot. Time bounds time here; turns bound cost, over in `config.ts`.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Platform fact: a `step.do(...)` callback is killed at ~10 minutes (Workflows'
|
|
14
|
+
* default step timeout). {@link CHUNK_SOFT_MS} is sized against this.
|
|
15
|
+
*/
|
|
16
|
+
export const STEP_TIMEOUT_MS = 10 * 60_000;
|
|
17
|
+
/**
|
|
18
|
+
* Platform fact: a single Workflow instance may run ~10,000 steps (paid plan).
|
|
19
|
+
* {@link MAX_CHUNKS_PER_BRANCH} is sized against this — see the worst-case
|
|
20
|
+
* product asserted in `platform.spec.ts`.
|
|
21
|
+
*/
|
|
22
|
+
export const STEPS_PER_INSTANCE = 10_000;
|
|
23
|
+
/**
|
|
24
|
+
* How long one durable chunk may run before it checkpoints and yields a fresh
|
|
25
|
+
* step. Comfortably inside {@link STEP_TIMEOUT_MS} so a slow model turn in flight
|
|
26
|
+
* when the soft limit trips still has room to finish.
|
|
27
|
+
*
|
|
28
|
+
* This is the *only* thing keeping a step under the timeout. A subagent otherwise
|
|
29
|
+
* runs until its turn or wall-clock budget is spent, however many turns that takes
|
|
30
|
+
* — which is the point: the runner no longer guesses at turn duration.
|
|
31
|
+
*/
|
|
32
|
+
export const CHUNK_SOFT_MS = 4 * 60_000;
|
|
33
|
+
/**
|
|
34
|
+
* Hard ceiling on durable chunk steps for one Subtask branch. A backstop, not a
|
|
35
|
+
* budget: the Workflow *fails* a branch that reaches it, so reaching it is a bug.
|
|
36
|
+
* It is held unreachable by two constraints, both asserted in
|
|
37
|
+
* `platform.spec.ts`:
|
|
38
|
+
*
|
|
39
|
+
* 1. It exceeds every Recipe's `maxTurns`. A chunk that yields always advanced at
|
|
40
|
+
* least one turn, so a run takes at most `maxTurns` chunks however short they
|
|
41
|
+
* are — and they do get short, because `CHUNK_SOFT_MS` and progress events both
|
|
42
|
+
* end one early. That bound survives both; a nominal `maxTurns / turnsPerChunk`
|
|
43
|
+
* estimate survived neither, which is why no such estimate exists any more.
|
|
44
|
+
* 2. The worst-case step product stays under {@link STEPS_PER_INSTANCE}.
|
|
45
|
+
*/
|
|
46
|
+
export const MAX_CHUNKS_PER_BRANCH = 40;
|
|
47
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,GAAG,MAAM,CAAC;AAE3C;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAEzC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAG,MAAM,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ToolSet } from "ai";
|
|
2
|
+
import { type CoreConfig, type CoreConfigOverrides } from "../config.js";
|
|
3
|
+
import { type AgentPlugin, type EnrichResultContext, type ResolveRuntimeContext, type ToolFamilyBuilder } from "../contract/plugin.js";
|
|
4
|
+
import type { PluginStore } from "../db/db.js";
|
|
5
|
+
import type { RecipePolicy } from "../contract/validation.js";
|
|
6
|
+
import { type SubtaskTypeRegistry } from "../subtasks/subtask-types.js";
|
|
7
|
+
import type { RecipeExecutionResult, SubtaskRuntime } from "../subtasks/types.js";
|
|
8
|
+
export { buildRecipeTools, collectToolFamilies } from "./tool-families.js";
|
|
9
|
+
/**
|
|
10
|
+
* The agent runtime: everything that used to be a module-level constant,
|
|
11
|
+
* resolved once per Durable Object instance from the host's config and its
|
|
12
|
+
* installed plugins.
|
|
13
|
+
*
|
|
14
|
+
* This is the whole point of the package split. In the predecessor repo the
|
|
15
|
+
* subtask registry was imported at module scope and every derived value — the
|
|
16
|
+
* type map, the delegate tool's enum and description, the round contract, the
|
|
17
|
+
* known-tool-family allowlist — was computed at *import time*. That made the
|
|
18
|
+
* registry unoverridable, pulled every domain's module into every bundle, and
|
|
19
|
+
* could not read `env`, which does not exist at module scope on Workers.
|
|
20
|
+
*
|
|
21
|
+
* Build it in `onStart`:
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* async onStart() {
|
|
25
|
+
* this.runtime = createAgentRuntime({
|
|
26
|
+
* config: { model: { chatModelId: "…" } },
|
|
27
|
+
* plugins: plugins(this.env)
|
|
28
|
+
* });
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export interface AgentRuntime {
|
|
33
|
+
config: CoreConfig;
|
|
34
|
+
plugins: readonly AgentPlugin[];
|
|
35
|
+
/** The installed subtask types — what `delegate` may name. */
|
|
36
|
+
types: SubtaskTypeRegistry;
|
|
37
|
+
/** Every tool family the installed plugins registered, by name. */
|
|
38
|
+
toolFamilies: ReadonlyMap<string, ToolFamilyBuilder>;
|
|
39
|
+
/** The capability boundary `validateRecipe` enforces. */
|
|
40
|
+
policy: RecipePolicy;
|
|
41
|
+
/** Plugin-owned stores, to hand to `new AgentDB(storage, { stores })`. */
|
|
42
|
+
stores: readonly PluginStore[];
|
|
43
|
+
/** Every binding and secret the installed plugins require of the host. */
|
|
44
|
+
requirements: {
|
|
45
|
+
secrets: string[];
|
|
46
|
+
bindings: string[];
|
|
47
|
+
};
|
|
48
|
+
/** The plugin that declared a subtask type, or null. */
|
|
49
|
+
pluginForType(type: string): AgentPlugin | null;
|
|
50
|
+
/** Tools the installed plugins offer the *main* agent, merged. */
|
|
51
|
+
mainAgentTools(): ToolSet;
|
|
52
|
+
/**
|
|
53
|
+
* Every plugin's `capability` block, for the main agent's soul. Returns `""`
|
|
54
|
+
* when none declares one, so a call site can append unconditionally.
|
|
55
|
+
*/
|
|
56
|
+
renderCapabilities(): string;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the session state an execution needs, by asking the plugin that owns
|
|
59
|
+
* its type. Returns `{}` for a type whose plugin declares no
|
|
60
|
+
* `resolveRuntime` — most of them.
|
|
61
|
+
*/
|
|
62
|
+
resolveRuntime(ctx: ResolveRuntimeContext): Promise<SubtaskRuntime>;
|
|
63
|
+
/** Let the owning plugin amend a terminal result before it is persisted. */
|
|
64
|
+
enrichResult(ctx: EnrichResultContext, result: RecipeExecutionResult): Promise<RecipeExecutionResult>;
|
|
65
|
+
/** Let the owning plugin release whatever `resolveRuntime` acquired. */
|
|
66
|
+
onAbort(ctx: ResolveRuntimeContext): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
export interface CreateAgentRuntimeOptions {
|
|
69
|
+
plugins: readonly AgentPlugin[];
|
|
70
|
+
config?: CoreConfigOverrides;
|
|
71
|
+
/**
|
|
72
|
+
* Verify that every secret and binding the plugins declared is actually
|
|
73
|
+
* present, given the Worker `env`. Off by default because core cannot know
|
|
74
|
+
* which of a consumer's bindings are optional; pass `env` to switch it on.
|
|
75
|
+
*/
|
|
76
|
+
env?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Thrown when the installed plugins and the host disagree — a contract-version
|
|
80
|
+
* skew, a duplicate key, or a missing binding. Always at DO start, never mid-request.
|
|
81
|
+
*/
|
|
82
|
+
export declare class RuntimeSetupError extends Error {
|
|
83
|
+
constructor(message: string);
|
|
84
|
+
}
|
|
85
|
+
export declare function createAgentRuntime(options: CreateAgentRuntimeOptions): AgentRuntime;
|
|
86
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,8DAA8D;IAC9D,KAAK,EAAE,mBAAmB,CAAC;IAC3B,mEAAmE;IACnE,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACrD,yDAAyD;IACzD,MAAM,EAAE,YAAY,CAAC;IACrB,0EAA0E;IAC1E,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,0EAA0E;IAC1E,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAExD,wDAAwD;IACxD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAChD,kEAAkE;IAClE,cAAc,IAAI,OAAO,CAAC;IAC1B;;;OAGG;IACH,kBAAkB,IAAI,MAAM,CAAC;IAE7B;;;;OAIG;IACH,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACpE,4EAA4E;IAC5E,YAAY,CACV,GAAG,EAAE,mBAAmB,EACxB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAClC,wEAAwE;IACxE,OAAO,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,yBAAyB,GACjC,YAAY,CAiId"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { resolveConfig } from "../config.js";
|
|
2
|
+
import { PLUGIN_CONTRACT_VERSION } from "../contract/plugin.js";
|
|
3
|
+
import { makeSubtaskTypes } from "../subtasks/subtask-types.js";
|
|
4
|
+
import { collectToolFamilies } from "./tool-families.js";
|
|
5
|
+
export { buildRecipeTools, collectToolFamilies } from "./tool-families.js";
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when the installed plugins and the host disagree — a contract-version
|
|
8
|
+
* skew, a duplicate key, or a missing binding. Always at DO start, never mid-request.
|
|
9
|
+
*/
|
|
10
|
+
export class RuntimeSetupError extends Error {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "RuntimeSetupError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function createAgentRuntime(options) {
|
|
17
|
+
const config = resolveConfig(options.config);
|
|
18
|
+
const plugins = options.plugins;
|
|
19
|
+
// --- contract + identity checks, all up front -----------------------------
|
|
20
|
+
const byKey = new Map();
|
|
21
|
+
for (const plugin of plugins) {
|
|
22
|
+
if (byKey.has(plugin.key)) {
|
|
23
|
+
throw new RuntimeSetupError(`duplicate plugin key "${plugin.key}" — two installed plugins claim it`);
|
|
24
|
+
}
|
|
25
|
+
byKey.set(plugin.key, plugin);
|
|
26
|
+
if (plugin.contractVersion !== PLUGIN_CONTRACT_VERSION) {
|
|
27
|
+
throw new RuntimeSetupError(`plugin "${plugin.key}" was built against plugin contract v${plugin.contractVersion}, ` +
|
|
28
|
+
`but this @loopingai/core speaks v${PLUGIN_CONTRACT_VERSION}. ` +
|
|
29
|
+
"Upgrade whichever of the two is behind — they publish from separate repos, " +
|
|
30
|
+
"so a version train can leave one lagging.");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// --- what the plugins contribute ------------------------------------------
|
|
34
|
+
const specs = plugins.flatMap((p) => (p.subtaskType ? [p.subtaskType] : []));
|
|
35
|
+
const types = makeSubtaskTypes(specs);
|
|
36
|
+
const toolFamilies = collectToolFamilies(plugins);
|
|
37
|
+
const typeOwner = new Map();
|
|
38
|
+
for (const plugin of plugins) {
|
|
39
|
+
if (plugin.subtaskType)
|
|
40
|
+
typeOwner.set(plugin.subtaskType.key, plugin);
|
|
41
|
+
}
|
|
42
|
+
const stores = plugins.flatMap((p) => (p.store ? [p.store] : []));
|
|
43
|
+
const secrets = [
|
|
44
|
+
...new Set(plugins.flatMap((p) => [...(p.requires?.secrets ?? [])]))
|
|
45
|
+
];
|
|
46
|
+
const bindings = [
|
|
47
|
+
...new Set(plugins.flatMap((p) => [...(p.requires?.bindings ?? [])]))
|
|
48
|
+
];
|
|
49
|
+
if (options.env) {
|
|
50
|
+
const missing = [];
|
|
51
|
+
for (const plugin of plugins) {
|
|
52
|
+
for (const name of [
|
|
53
|
+
...(plugin.requires?.secrets ?? []),
|
|
54
|
+
...(plugin.requires?.bindings ?? [])
|
|
55
|
+
]) {
|
|
56
|
+
const value = options.env[name];
|
|
57
|
+
if (value === undefined || value === null || value === "") {
|
|
58
|
+
missing.push(`${name} (required by "${plugin.key}")`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (missing.length > 0) {
|
|
63
|
+
throw new RuntimeSetupError(`missing bindings or secrets: ${missing.join(", ")}. ` +
|
|
64
|
+
"A plugin cannot add its own wrangler binding — declare these in wrangler.jsonc " +
|
|
65
|
+
"(and `wrangler secret put` the secrets).");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const policy = {
|
|
69
|
+
modelAllowlist: new Set([
|
|
70
|
+
config.model.chatModelId,
|
|
71
|
+
config.model.fallbackChatModelId
|
|
72
|
+
]),
|
|
73
|
+
defaultPrimaryModelId: config.model.chatModelId,
|
|
74
|
+
defaultFallbackModelId: config.model.fallbackChatModelId,
|
|
75
|
+
knownToolFamilies: new Set(toolFamilies.keys()),
|
|
76
|
+
baselineLimits: config.subagentLimits
|
|
77
|
+
};
|
|
78
|
+
const pluginForType = (type) => typeOwner.get(type) ?? null;
|
|
79
|
+
return {
|
|
80
|
+
config,
|
|
81
|
+
plugins,
|
|
82
|
+
types,
|
|
83
|
+
toolFamilies,
|
|
84
|
+
policy,
|
|
85
|
+
stores,
|
|
86
|
+
requirements: { secrets, bindings },
|
|
87
|
+
pluginForType,
|
|
88
|
+
mainAgentTools() {
|
|
89
|
+
const tools = {};
|
|
90
|
+
for (const plugin of plugins) {
|
|
91
|
+
if (plugin.mainAgentTools)
|
|
92
|
+
Object.assign(tools, plugin.mainAgentTools());
|
|
93
|
+
}
|
|
94
|
+
return tools;
|
|
95
|
+
},
|
|
96
|
+
renderCapabilities() {
|
|
97
|
+
const blocks = [];
|
|
98
|
+
for (const plugin of plugins) {
|
|
99
|
+
if (plugin.capability)
|
|
100
|
+
blocks.push(plugin.capability);
|
|
101
|
+
}
|
|
102
|
+
return blocks.join("\n\n");
|
|
103
|
+
},
|
|
104
|
+
async resolveRuntime(ctx) {
|
|
105
|
+
const plugin = pluginForType(ctx.type);
|
|
106
|
+
if (!plugin?.resolveRuntime)
|
|
107
|
+
return {};
|
|
108
|
+
return (await plugin.resolveRuntime(ctx));
|
|
109
|
+
},
|
|
110
|
+
async enrichResult(ctx, result) {
|
|
111
|
+
const plugin = pluginForType(ctx.request.type);
|
|
112
|
+
if (!plugin?.enrichResult)
|
|
113
|
+
return result;
|
|
114
|
+
return plugin.enrichResult(ctx, result);
|
|
115
|
+
},
|
|
116
|
+
async onAbort(ctx) {
|
|
117
|
+
const plugin = pluginForType(ctx.type);
|
|
118
|
+
if (plugin?.onAbort)
|
|
119
|
+
await plugin.onAbort(ctx);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RecipeToolSet, ToolFamilyBuilder, ToolFamilyContext } from "../contract/plugin.js";
|
|
2
|
+
import type { SubtaskRuntime } from "../subtasks/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Assemble a recipe's toolset from the installed families.
|
|
5
|
+
*
|
|
6
|
+
* This replaces the predecessor's dispatcher, which was an `if / else if` chain
|
|
7
|
+
* naming three families inline — including a domain one — inside otherwise
|
|
8
|
+
* generic code, with static imports of that domain's modules at the top of the
|
|
9
|
+
* file. That is the single edit that made every agent's bundle carry every
|
|
10
|
+
* domain, and it is why this takes a map instead.
|
|
11
|
+
*
|
|
12
|
+
* A family a recipe names but no plugin registered is skipped rather than
|
|
13
|
+
* throwing: `validateRecipe` already dropped unknown families, so reaching one
|
|
14
|
+
* here means the policy and the registry disagreed, and a subagent that silently
|
|
15
|
+
* runs with fewer tools degrades better than one that fails a whole branch. The
|
|
16
|
+
* skipped names are returned so a caller can log them.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildRecipeTools<TRuntime = SubtaskRuntime>(families: readonly string[], registry: ReadonlyMap<string, ToolFamilyBuilder<TRuntime>>, ctx: ToolFamilyContext<TRuntime>): RecipeToolSet<TRuntime> & {
|
|
19
|
+
skipped: string[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Collect every family builder the installed plugins registered, refusing
|
|
23
|
+
* duplicates.
|
|
24
|
+
*
|
|
25
|
+
* Two plugins claiming one family name is a misconfiguration whose symptom would
|
|
26
|
+
* otherwise be a subagent silently getting the wrong domain's tools — so it fails
|
|
27
|
+
* at DO start, named, instead.
|
|
28
|
+
*/
|
|
29
|
+
export declare function collectToolFamilies<TRuntime = SubtaskRuntime>(plugins: readonly {
|
|
30
|
+
key: string;
|
|
31
|
+
toolFamilies?: Record<string, ToolFamilyBuilder<TRuntime>>;
|
|
32
|
+
}[]): Map<string, ToolFamilyBuilder<TRuntime>>;
|
|
33
|
+
//# sourceMappingURL=tool-families.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-families.d.ts","sourceRoot":"","sources":["../../src/runtime/tool-families.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAG,cAAc,EACxD,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC,EAC1D,GAAG,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GAC/B,aAAa,CAAC,QAAQ,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAwBjD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,GAAG,cAAc,EAC3D,OAAO,EAAE,SAAS;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;CAC5D,EAAE,GACF,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAgB1C"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assemble a recipe's toolset from the installed families.
|
|
3
|
+
*
|
|
4
|
+
* This replaces the predecessor's dispatcher, which was an `if / else if` chain
|
|
5
|
+
* naming three families inline — including a domain one — inside otherwise
|
|
6
|
+
* generic code, with static imports of that domain's modules at the top of the
|
|
7
|
+
* file. That is the single edit that made every agent's bundle carry every
|
|
8
|
+
* domain, and it is why this takes a map instead.
|
|
9
|
+
*
|
|
10
|
+
* A family a recipe names but no plugin registered is skipped rather than
|
|
11
|
+
* throwing: `validateRecipe` already dropped unknown families, so reaching one
|
|
12
|
+
* here means the policy and the registry disagreed, and a subagent that silently
|
|
13
|
+
* runs with fewer tools degrades better than one that fails a whole branch. The
|
|
14
|
+
* skipped names are returned so a caller can log them.
|
|
15
|
+
*/
|
|
16
|
+
export function buildRecipeTools(families, registry, ctx) {
|
|
17
|
+
const tools = {};
|
|
18
|
+
const aborts = [];
|
|
19
|
+
const skipped = [];
|
|
20
|
+
for (const family of families) {
|
|
21
|
+
const build = registry.get(family);
|
|
22
|
+
if (!build) {
|
|
23
|
+
skipped.push(family);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const built = build(ctx);
|
|
27
|
+
Object.assign(tools, built.tools);
|
|
28
|
+
if (built.abort)
|
|
29
|
+
aborts.push(built.abort);
|
|
30
|
+
}
|
|
31
|
+
const abort = aborts.length === 0
|
|
32
|
+
? undefined
|
|
33
|
+
: async (c) => {
|
|
34
|
+
for (const run of aborts)
|
|
35
|
+
await run(c);
|
|
36
|
+
};
|
|
37
|
+
return { tools, abort, skipped };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Collect every family builder the installed plugins registered, refusing
|
|
41
|
+
* duplicates.
|
|
42
|
+
*
|
|
43
|
+
* Two plugins claiming one family name is a misconfiguration whose symptom would
|
|
44
|
+
* otherwise be a subagent silently getting the wrong domain's tools — so it fails
|
|
45
|
+
* at DO start, named, instead.
|
|
46
|
+
*/
|
|
47
|
+
export function collectToolFamilies(plugins) {
|
|
48
|
+
const registry = new Map();
|
|
49
|
+
const owner = new Map();
|
|
50
|
+
for (const plugin of plugins) {
|
|
51
|
+
for (const [family, build] of Object.entries(plugin.toolFamilies ?? {})) {
|
|
52
|
+
const existing = owner.get(family);
|
|
53
|
+
if (existing) {
|
|
54
|
+
throw new Error(`tool family "${family}" is registered by both "${existing}" and "${plugin.key}"`);
|
|
55
|
+
}
|
|
56
|
+
owner.set(family, plugin.key);
|
|
57
|
+
registry.set(family, build);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return registry;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=tool-families.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-families.js","sourceRoot":"","sources":["../../src/runtime/tool-families.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAA2B,EAC3B,QAA0D,EAC1D,GAAgC;IAEhC,MAAM,KAAK,GAAY,EAAE,CAAC;IAC1B,MAAM,MAAM,GAA+D,EAAE,CAAC;IAC9E,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,KAAK;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,KAAK,GACT,MAAM,CAAC,MAAM,KAAK,CAAC;QACjB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,KAAK,EAAE,CAA8B,EAAE,EAAE;YACvC,KAAK,MAAM,GAAG,IAAI,MAAM;gBAAE,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC;IAER,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAGG;IAEH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuC,CAAC;IAChE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAC;YACxE,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,gBAAgB,MAAM,4BAA4B,QAAQ,UAAU,MAAM,CAAC,GAAG,GAAG,CAClF,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9B,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RecipeExecutionRequest } from "../subtasks/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Version of the canonicalization format below.
|
|
4
|
+
*
|
|
5
|
+
* Bump it **only** when a change to `canonicalRequest` would make two equal
|
|
6
|
+
* executions hash differently. Bumping invalidates every cached result and every
|
|
7
|
+
* in-flight run's checkpoint, so it is a deliberate act, not a side effect.
|
|
8
|
+
*/
|
|
9
|
+
export declare const FINGERPRINT_VERSION = 1;
|
|
10
|
+
/**
|
|
11
|
+
* Canonical JSON of the fields that define an execution's identity, rebuilt as
|
|
12
|
+
* literals in fixed key order so `JSON.stringify` is deterministic (object
|
|
13
|
+
* insertion order). Array order is semantic and preserved: the parent builds
|
|
14
|
+
* references and dependency results from ordinal-ordered rows, so a retry of the
|
|
15
|
+
* same execution is byte-identical.
|
|
16
|
+
*
|
|
17
|
+
* **Limits are canonicalized as *declared*, not as merged.** The predecessor
|
|
18
|
+
* merged them against the house baseline first, on the reasoning that `{}` and
|
|
19
|
+
* an explicit restatement of the baseline are the same execution and should hash
|
|
20
|
+
* alike. That reasoning is sound but its cost is not payable once the baseline
|
|
21
|
+
* lives in a versioned package: a patch release that nudges a default would
|
|
22
|
+
* change every fingerprint at once, and every in-flight subagent run would miss
|
|
23
|
+
* its checkpoint and restart from turn zero having already spent its budget.
|
|
24
|
+
*
|
|
25
|
+
* Hashing the sparse declaration inverts that trade. A recipe that spells out
|
|
26
|
+
* the baseline explicitly gets a different key from one that omits it — worth
|
|
27
|
+
* exactly one redundant execution, once, for a recipe nobody writes — and the
|
|
28
|
+
* host's baseline becomes free to move. {@link FINGERPRINT_VERSION} is the
|
|
29
|
+
* deliberate lever for the invalidation the merge used to cause accidentally.
|
|
30
|
+
*/
|
|
31
|
+
export declare function canonicalRequest(request: RecipeExecutionRequest): string;
|
|
32
|
+
/**
|
|
33
|
+
* SHA-256 hex digest of the canonical request — the deterministic key for the
|
|
34
|
+
* subagent's single cached terminal result. The raw (pre-validation) request is
|
|
35
|
+
* fingerprinted, so the key matches exactly what the parent re-sends on retry.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fingerprintRequest(request: RecipeExecutionRequest): Promise<string>;
|
|
38
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/subagent/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAGnE;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAuCxE;AAqBD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAMjB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version of the canonicalization format below.
|
|
3
|
+
*
|
|
4
|
+
* Bump it **only** when a change to `canonicalRequest` would make two equal
|
|
5
|
+
* executions hash differently. Bumping invalidates every cached result and every
|
|
6
|
+
* in-flight run's checkpoint, so it is a deliberate act, not a side effect.
|
|
7
|
+
*/
|
|
8
|
+
export const FINGERPRINT_VERSION = 1;
|
|
9
|
+
/**
|
|
10
|
+
* Canonical JSON of the fields that define an execution's identity, rebuilt as
|
|
11
|
+
* literals in fixed key order so `JSON.stringify` is deterministic (object
|
|
12
|
+
* insertion order). Array order is semantic and preserved: the parent builds
|
|
13
|
+
* references and dependency results from ordinal-ordered rows, so a retry of the
|
|
14
|
+
* same execution is byte-identical.
|
|
15
|
+
*
|
|
16
|
+
* **Limits are canonicalized as *declared*, not as merged.** The predecessor
|
|
17
|
+
* merged them against the house baseline first, on the reasoning that `{}` and
|
|
18
|
+
* an explicit restatement of the baseline are the same execution and should hash
|
|
19
|
+
* alike. That reasoning is sound but its cost is not payable once the baseline
|
|
20
|
+
* lives in a versioned package: a patch release that nudges a default would
|
|
21
|
+
* change every fingerprint at once, and every in-flight subagent run would miss
|
|
22
|
+
* its checkpoint and restart from turn zero having already spent its budget.
|
|
23
|
+
*
|
|
24
|
+
* Hashing the sparse declaration inverts that trade. A recipe that spells out
|
|
25
|
+
* the baseline explicitly gets a different key from one that omits it — worth
|
|
26
|
+
* exactly one redundant execution, once, for a recipe nobody writes — and the
|
|
27
|
+
* host's baseline becomes free to move. {@link FINGERPRINT_VERSION} is the
|
|
28
|
+
* deliberate lever for the invalidation the merge used to cause accidentally.
|
|
29
|
+
*/
|
|
30
|
+
export function canonicalRequest(request) {
|
|
31
|
+
const canonical = {
|
|
32
|
+
v: FINGERPRINT_VERSION,
|
|
33
|
+
taskId: request.taskId,
|
|
34
|
+
subtaskId: request.subtaskId,
|
|
35
|
+
type: request.type,
|
|
36
|
+
recipe: {
|
|
37
|
+
key: request.recipe.key,
|
|
38
|
+
version: request.recipe.version,
|
|
39
|
+
primaryModelId: request.recipe.primaryModelId,
|
|
40
|
+
fallbackModelId: request.recipe.fallbackModelId,
|
|
41
|
+
soul: request.recipe.soul,
|
|
42
|
+
toolFamilies: request.recipe.toolFamilies,
|
|
43
|
+
enabled: request.recipe.enabled,
|
|
44
|
+
limits: canonicalLimits(request.recipe.limits),
|
|
45
|
+
historyWindow: request.recipe.historyWindow,
|
|
46
|
+
reportMetrics: request.recipe.reportMetrics
|
|
47
|
+
},
|
|
48
|
+
prompt: request.prompt,
|
|
49
|
+
references: request.references.map((ref) => ({
|
|
50
|
+
role: ref.role,
|
|
51
|
+
text: ref.text
|
|
52
|
+
})),
|
|
53
|
+
dependencyResults: request.dependencyResults.map((dep) => ({
|
|
54
|
+
subtaskId: dep.subtaskId,
|
|
55
|
+
type: dep.type,
|
|
56
|
+
resultParts: dep.resultParts.map((part) => ({
|
|
57
|
+
kind: part.kind,
|
|
58
|
+
text: part.text
|
|
59
|
+
}))
|
|
60
|
+
})),
|
|
61
|
+
// Params ARE identity: the same prompt against a different external resource
|
|
62
|
+
// is different work, and must not replay a cached result. Key order is fixed
|
|
63
|
+
// by sorting, so an equivalent params object always canonicalizes identically.
|
|
64
|
+
params: Object.fromEntries(Object.entries(request.params).sort(([a], [b]) => (a < b ? -1 : 1)))
|
|
65
|
+
};
|
|
66
|
+
return JSON.stringify(canonical);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A recipe's declared budget, normalized: only positive integers count (matching
|
|
70
|
+
* what `resolveLimits` would honor), and fields appear in fixed order with
|
|
71
|
+
* absent ones omitted. So `{}`, `{ maxTurns: 0 }`, and `{ maxTurns: 1.5 }` all
|
|
72
|
+
* canonicalize alike — they all mean "inherit the baseline".
|
|
73
|
+
*/
|
|
74
|
+
function canonicalLimits(limits) {
|
|
75
|
+
const keep = (n) => typeof n === "number" && Number.isInteger(n) && n > 0 ? n : undefined;
|
|
76
|
+
const out = {};
|
|
77
|
+
const maxTurns = keep(limits?.maxTurns);
|
|
78
|
+
if (maxTurns !== undefined)
|
|
79
|
+
out.maxTurns = maxTurns;
|
|
80
|
+
const maxWallMs = keep(limits?.maxWallMs);
|
|
81
|
+
if (maxWallMs !== undefined)
|
|
82
|
+
out.maxWallMs = maxWallMs;
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* SHA-256 hex digest of the canonical request — the deterministic key for the
|
|
87
|
+
* subagent's single cached terminal result. The raw (pre-validation) request is
|
|
88
|
+
* fingerprinted, so the key matches exactly what the parent re-sends on retry.
|
|
89
|
+
*/
|
|
90
|
+
export async function fingerprintRequest(request) {
|
|
91
|
+
const bytes = new TextEncoder().encode(canonicalRequest(request));
|
|
92
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
93
|
+
return [...new Uint8Array(digest)]
|
|
94
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
95
|
+
.join("");
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/subagent/fingerprint.ts"],"names":[],"mappings":"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"}
|