@agent-compose/sdk 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -33
- package/dist/agent/agent-loop.d.ts +83 -5
- package/dist/agent/run-agent.d.ts +34 -9
- package/dist/client.d.ts +247 -99
- package/dist/index.d.ts +26 -11
- package/dist/index.js +1967 -745
- package/dist/processors/builtins.d.ts +35 -0
- package/dist/processors/index.d.ts +4 -0
- package/dist/processors/processor.d.ts +91 -0
- package/dist/processors/processor.test.d.ts +1 -0
- package/dist/processors/runner.d.ts +19 -0
- package/dist/request-context/index.d.ts +2 -0
- package/dist/request-context/request-context.d.ts +159 -0
- package/dist/request-context/request-context.test.d.ts +1 -0
- package/dist/runtimes/claude.d.ts +27 -50
- package/dist/runtimes/openai-desktop.js +1918 -741
- package/dist/runtimes/vercel.d.ts +34 -0
- package/dist/runtimes/vercel.js +474 -0
- package/dist/sandbox.d.ts +29 -25
- package/dist/step-invocation/__tests__/invoker.test.d.ts +1 -0
- package/dist/step-invocation/__tests__/protocol.test.d.ts +1 -0
- package/dist/step-invocation/__tests__/server.test.d.ts +1 -0
- package/dist/step-invocation/index.d.ts +25 -0
- package/dist/step-invocation/invoker.d.ts +65 -0
- package/dist/step-invocation/protocol.d.ts +44 -0
- package/dist/step-invocation/server.d.ts +63 -0
- package/dist/step-invocation/types.d.ts +72 -0
- package/dist/tools/coding.d.ts +49 -0
- package/dist/tools/coding.test.d.ts +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/types/events.d.ts +36 -0
- package/dist/types/execution-context.d.ts +22 -0
- package/dist/types/runtime.d.ts +32 -0
- package/dist/types/sandbox-environment.d.ts +5 -2
- package/dist/types/sandbox.d.ts +14 -12
- package/dist/types/workflow-metadata.d.ts +51 -0
- package/dist/types/workflow-plan.d.ts +19 -0
- package/dist/types/workflow.d.ts +57 -17
- package/dist/utils/bundler.d.ts +62 -3
- package/dist/workflow-steps/__tests__/observability.test.d.ts +1 -0
- package/dist/workflow-steps/index.d.ts +10 -0
- package/dist/workflow-steps/observability.d.ts +58 -0
- package/dist/workflow-steps/runner.d.ts +96 -0
- package/dist/workflow-steps/step.d.ts +25 -0
- package/dist/workflow-steps/types.d.ts +135 -0
- package/dist/workflow-steps/workflow-steps.test.d.ts +1 -0
- package/dist/workflow-steps/workflow.d.ts +50 -0
- package/dist/workflows/engine.d.ts +27 -13
- package/dist/workflows/invoke-child.d.ts +10 -0
- package/package.json +25 -15
- package/src/agent/agent-loop.ts +197 -26
- package/src/agent/run-agent.ts +40 -15
- package/src/client.ts +326 -76
- package/src/index.ts +124 -10
- package/src/processors/builtins.ts +72 -0
- package/src/processors/index.ts +15 -0
- package/src/processors/processor.ts +103 -0
- package/src/processors/runner.ts +42 -0
- package/src/request-context/index.ts +17 -0
- package/src/request-context/request-context.ts +302 -0
- package/src/runtimes/claude.ts +123 -254
- package/src/runtimes/vercel.ts +180 -0
- package/src/sandbox.ts +53 -21
- package/src/step-invocation/index.ts +33 -0
- package/src/step-invocation/invoker.ts +204 -0
- package/src/step-invocation/protocol.ts +57 -0
- package/src/step-invocation/server.ts +184 -0
- package/src/step-invocation/types.ts +70 -0
- package/src/tools/coding.ts +126 -0
- package/src/tools/index.ts +8 -0
- package/src/types/events.ts +40 -0
- package/src/types/execution-context.ts +30 -0
- package/src/types/runtime.ts +24 -0
- package/src/types/sandbox-environment.ts +7 -5
- package/src/types/sandbox.ts +16 -12
- package/src/types/workflow-metadata.ts +84 -0
- package/src/types/workflow-plan.ts +24 -0
- package/src/types/workflow.ts +139 -25
- package/src/utils/bundler.ts +206 -18
- package/src/utils/source-loader.ts +2 -2
- package/src/workflow-steps/index.ts +30 -0
- package/src/workflow-steps/observability.ts +103 -0
- package/src/workflow-steps/runner.ts +244 -0
- package/src/workflow-steps/step.ts +38 -0
- package/src/workflow-steps/types.ts +134 -0
- package/src/workflow-steps/workflow.ts +95 -0
- package/src/workflows/engine.ts +69 -40
- package/src/workflows/invoke-child.ts +29 -0
package/src/index.ts
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Tools for defining runtimes and workflows, registering/invoking them
|
|
7
7
|
* against an agent-compose server, and running LLM agent loops inside a
|
|
8
|
-
* workflow via `
|
|
8
|
+
* workflow via `agent(opts)`.
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```typescript
|
|
12
|
-
* import { defineWorkflow,
|
|
12
|
+
* import { defineWorkflow, agent, AgentComposeClient } from "@agent-compose/sdk";
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
15
|
|
|
@@ -25,6 +25,7 @@ export type {
|
|
|
25
25
|
AgentRuntime,
|
|
26
26
|
McpServerConfig,
|
|
27
27
|
ModelExecutionContract,
|
|
28
|
+
ToolCallGateResult,
|
|
28
29
|
RuntimeOptions,
|
|
29
30
|
} from "./types/runtime.js";
|
|
30
31
|
|
|
@@ -36,6 +37,42 @@ export type {
|
|
|
36
37
|
AgentBudget,
|
|
37
38
|
WorkflowHooks,
|
|
38
39
|
} from "./types/workflow.js";
|
|
40
|
+
export type { WorkflowPlan, WorkflowStepPlan } from "./types/workflow-plan.js";
|
|
41
|
+
export type { BaseExecutionContext, InvokeChild } from "./types/execution-context.js";
|
|
42
|
+
|
|
43
|
+
// Request context — per-run typed bag (tenant identity + freeform).
|
|
44
|
+
export {
|
|
45
|
+
RequestContext,
|
|
46
|
+
ReservedKeyError,
|
|
47
|
+
NonSerialisableValueError,
|
|
48
|
+
AC_RESERVED_PREFIX,
|
|
49
|
+
AC_TEAM_ID,
|
|
50
|
+
AC_RUN_ID,
|
|
51
|
+
AC_WORKFLOW_ID,
|
|
52
|
+
AC_FACTORY_ID,
|
|
53
|
+
AC_API_KEY_SCOPES,
|
|
54
|
+
AC_PARENT_RUN_ID,
|
|
55
|
+
AC_ABORT_SIGNAL,
|
|
56
|
+
} from "./request-context/index.js";
|
|
57
|
+
export type {
|
|
58
|
+
RequestContextReserved,
|
|
59
|
+
RequestContextWire,
|
|
60
|
+
} from "./request-context/index.js";
|
|
61
|
+
|
|
62
|
+
// Processors — typed pre/post pipeline around the agent loop.
|
|
63
|
+
export {
|
|
64
|
+
Verdict,
|
|
65
|
+
runProcessorChain,
|
|
66
|
+
denyTools,
|
|
67
|
+
requireScope,
|
|
68
|
+
redactPattern,
|
|
69
|
+
} from "./processors/index.js";
|
|
70
|
+
export type {
|
|
71
|
+
Processor,
|
|
72
|
+
ProcessorContext,
|
|
73
|
+
ProcessorVerdict,
|
|
74
|
+
ToolCall,
|
|
75
|
+
} from "./processors/index.js";
|
|
39
76
|
|
|
40
77
|
// Protocol types (agent-loop input/output shapes)
|
|
41
78
|
export type {
|
|
@@ -60,7 +97,15 @@ export type {
|
|
|
60
97
|
// HTTP client
|
|
61
98
|
export { AgentComposeClient } from "./client.js";
|
|
62
99
|
export type {
|
|
63
|
-
RegisterResult,
|
|
100
|
+
RegisterResult, RegisterWorkflowInput, RuntimeSourceInput,
|
|
101
|
+
InvokeWorkflowOptions, InvokeAndWaitOptions, InvokeResult,
|
|
102
|
+
ListSnapshotsOptions, TemplateRow, ListTemplatesOptions,
|
|
103
|
+
CreateFactoryInput, UpdateFactoryInput,
|
|
104
|
+
SecretOptions, SetSecretResult, SecretListEntry,
|
|
105
|
+
CreateApiKeyInput, StreamRunLogsOptions,
|
|
106
|
+
EventSubjectType, EventRow, ReportEventInput, ListEventsOptions, ListEventsResult,
|
|
107
|
+
RunLogLine, ListRunLogsOptions,
|
|
108
|
+
RegisteredRuntime, RunState, RunStatus, FactoryRow, SnapshotListEntry,
|
|
64
109
|
ApiKey, ApiKeyCreated,
|
|
65
110
|
UsageRollupRow, UsageResponse,
|
|
66
111
|
CancelRunResponse,
|
|
@@ -75,8 +120,13 @@ export { formatError } from "./utils/errors.js";
|
|
|
75
120
|
|
|
76
121
|
// Source discovery + bundling utilities
|
|
77
122
|
export { discoverRuntimeName } from "./utils/discovery.js";
|
|
78
|
-
export {
|
|
79
|
-
|
|
123
|
+
export {
|
|
124
|
+
bundleWorkflow,
|
|
125
|
+
BUNDLER_VERSION,
|
|
126
|
+
WorkflowSourceValidationError,
|
|
127
|
+
assertDefaultExportIsDefineWorkflow,
|
|
128
|
+
} from "./utils/bundler.js";
|
|
129
|
+
export type { BundledWorkflow, WorkflowManifest } from "./utils/bundler.js";
|
|
80
130
|
|
|
81
131
|
// Zod schemas
|
|
82
132
|
export { AgentStatusSchema } from "./utils/schemas.js";
|
|
@@ -87,6 +137,12 @@ export { AgentStatusSchema } from "./utils/schemas.js";
|
|
|
87
137
|
export { createClaudeRuntime, ClaudeRunner } from "./runtimes/claude.js";
|
|
88
138
|
export type { ClaudeRuntimeConfig } from "./runtimes/claude.js";
|
|
89
139
|
export { default as claudeRuntime } from "./runtimes/claude.js";
|
|
140
|
+
export { createVercelRuntime, VercelRunner } from "./runtimes/vercel.js";
|
|
141
|
+
export type { VercelRuntimeConfig } from "./runtimes/vercel.js";
|
|
142
|
+
|
|
143
|
+
// Built-in coding tools for Vercel AI SDK runtime.
|
|
144
|
+
export { bashTool, codingTools, editTool, readTool, writeTool } from "./tools/index.js";
|
|
145
|
+
export type { CodingTool } from "./tools/index.js";
|
|
90
146
|
|
|
91
147
|
// Streaming event contract
|
|
92
148
|
export type { RunEvent } from "./types/events.js";
|
|
@@ -96,16 +152,74 @@ export { createSandbox, reconnectSandbox, killAllSandboxes, killSandboxById,
|
|
|
96
152
|
getSandboxQuotas, listOwnedSandboxes, deleteSandboxSnapshot,
|
|
97
153
|
makeSandboxProvider, makeDesktopSandboxProvider,
|
|
98
154
|
parseSseExecStream, AGENT_COMPOSE_TAG } from "./sandbox.js";
|
|
99
|
-
export type {
|
|
155
|
+
export type {
|
|
156
|
+
SandboxCreateOpts, SandboxNetworkPolicy, SandboxNetworkHeaderTransform,
|
|
157
|
+
SandboxNetworkAllowRule, SandboxNetworkSubnetPolicy, SandboxProviderName,
|
|
158
|
+
SandboxQuotaResult, OwnedSandboxResult, OwnedSandbox,
|
|
159
|
+
ParseSseExecStreamOptions, SandboxCommandRunOptions, SandboxCommandResult,
|
|
160
|
+
} from "./sandbox.js";
|
|
100
161
|
|
|
101
162
|
// Workflow engine
|
|
102
163
|
export { runWorkflow, WorkflowError, EngineError, classifyError, parseNameVersion } from "./workflows/engine.js";
|
|
103
|
-
export type { WorkflowResult, EngineSubsystem } from "./workflows/engine.js";
|
|
164
|
+
export type { WorkflowResult, RunWorkflowOptions, EngineSubsystem } from "./workflows/engine.js";
|
|
165
|
+
export { buildInvokeChild } from "./workflows/invoke-child.js";
|
|
166
|
+
|
|
167
|
+
// Step-based workflows — use `defineWorkflow({ id, inputSchema,
|
|
168
|
+
// outputSchema }).step(...).build()` for durable, replayable execution.
|
|
169
|
+
export {
|
|
170
|
+
defineStep,
|
|
171
|
+
isWorkflow,
|
|
172
|
+
runWorkflowSteps,
|
|
173
|
+
runWorkflowSingleStep,
|
|
174
|
+
StepValidationError,
|
|
175
|
+
WorkflowInputValidationError,
|
|
176
|
+
WorkflowOutputValidationError,
|
|
177
|
+
} from "./workflow-steps/index.js";
|
|
178
|
+
export type {
|
|
179
|
+
Step,
|
|
180
|
+
StepContext,
|
|
181
|
+
StepRunResult,
|
|
182
|
+
Workflow,
|
|
183
|
+
DefineStepOpts,
|
|
184
|
+
StepWorkflowDefinition,
|
|
185
|
+
WorkflowBuilder,
|
|
186
|
+
RunWorkflowStepsOpts,
|
|
187
|
+
RunWorkflowStepsResult,
|
|
188
|
+
RunWorkflowSingleStepOpts,
|
|
189
|
+
RunWorkflowSingleStepResult,
|
|
190
|
+
StepObservability,
|
|
191
|
+
SubStepEvent,
|
|
192
|
+
} from "./workflow-steps/index.js";
|
|
193
|
+
|
|
194
|
+
// StepInvocation — wire protocol that lets a server-side activity drive
|
|
195
|
+
// one workflow step inside an existing runner sandbox. Two halves:
|
|
196
|
+
// `invokeStep` (server) and `serveStep` (runner).
|
|
197
|
+
export {
|
|
198
|
+
invokeStep,
|
|
199
|
+
serveStep,
|
|
200
|
+
parseStepResult,
|
|
201
|
+
buildStepEnvs,
|
|
202
|
+
StepExecutionError,
|
|
203
|
+
STEP_RESULT_PREFIX,
|
|
204
|
+
STEP_ENV,
|
|
205
|
+
RUNNER_BUNDLE_PATH,
|
|
206
|
+
RUNNER_COMMAND,
|
|
207
|
+
stepInputPath,
|
|
208
|
+
requestContextPath,
|
|
209
|
+
} from "./step-invocation/index.js";
|
|
210
|
+
export type {
|
|
211
|
+
StepRequest,
|
|
212
|
+
StepResult,
|
|
213
|
+
StepInvocationError,
|
|
214
|
+
StepHandler,
|
|
215
|
+
StepHandlerResult,
|
|
216
|
+
ServeStepRequest,
|
|
217
|
+
} from "./step-invocation/index.js";
|
|
104
218
|
|
|
105
219
|
// Agent loop — for workflows that embed an LLM agent in their run() body.
|
|
106
220
|
export { agentLoop, parseAgentStatus, DEFAULT_CLAUDE_MODEL } from "./agent/agent-loop.js";
|
|
107
|
-
export type { AgentLoopResult } from "./agent/agent-loop.js";
|
|
108
|
-
export {
|
|
109
|
-
export type {
|
|
221
|
+
export type { AgentLifecycleEvent, AgentLoopOpts, AgentLoopResult } from "./agent/agent-loop.js";
|
|
222
|
+
export { agent } from "./agent/run-agent.js";
|
|
223
|
+
export type { AgentOpts } from "./agent/run-agent.js";
|
|
110
224
|
export { AgentMessageSchema, parseAgentResponse } from "./agent/protocol.js";
|
|
111
225
|
export { importSourceModule, TMP_DIR, LATEST_VERSION } from "./utils/source-loader.js";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in processors — minimal set that exercises all three hooks and
|
|
3
|
+
* covers the most common gating needs. More can be authored by users; these
|
|
4
|
+
* exist as load-bearing examples and as defaults for common policies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Processor } from "./processor.js";
|
|
8
|
+
import { Verdict } from "./processor.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Reject any tool call whose name appears in `names`. The reason is returned
|
|
12
|
+
* to the model as the tool result, so the model can react and try a
|
|
13
|
+
* different approach.
|
|
14
|
+
*
|
|
15
|
+
* Dormant in runtimes that don't support pre-tool gating (current Claude CLI
|
|
16
|
+
* runtime). Becomes active when a runtime that wires `processToolCall` lands
|
|
17
|
+
* (candidate #1).
|
|
18
|
+
*/
|
|
19
|
+
export function denyTools(names: readonly string[]): Processor {
|
|
20
|
+
const banned = new Set(names);
|
|
21
|
+
return {
|
|
22
|
+
name: "denyTools",
|
|
23
|
+
processToolCall: (call) =>
|
|
24
|
+
banned.has(call.toolName)
|
|
25
|
+
? Verdict.deny(`tool "${call.toolName}" is denied by policy`)
|
|
26
|
+
: Verdict.continue(call),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Require the calling API key to carry every scope in `required`. Aborts the
|
|
32
|
+
* agent loop with a clear reason if any are missing — defence-in-depth on
|
|
33
|
+
* top of the server's per-call scope checks.
|
|
34
|
+
*
|
|
35
|
+
* Runs as `processInput` so the violation is caught before the model is
|
|
36
|
+
* invoked, not after work has happened.
|
|
37
|
+
*/
|
|
38
|
+
export function requireScope(required: readonly string[]): Processor {
|
|
39
|
+
return {
|
|
40
|
+
name: "requireScope",
|
|
41
|
+
processInput: (prompt, ctx) => {
|
|
42
|
+
const missing = required.filter((s) => !ctx.requestContext.hasScope(s));
|
|
43
|
+
return missing.length === 0
|
|
44
|
+
? Verdict.continue(prompt)
|
|
45
|
+
: Verdict.abort(`API key is missing required scopes: ${missing.join(", ")}`);
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Redact substrings matching `pattern` from each emitted text/thinking
|
|
52
|
+
* message before downstream observability sees it. Useful for stripping
|
|
53
|
+
* accidental secret echoes (e.g. a model that pasted an env var into its
|
|
54
|
+
* reasoning).
|
|
55
|
+
*
|
|
56
|
+
* Tool result and tool use messages are passed through unchanged — those
|
|
57
|
+
* paths have their own redaction story (network policy + secret brokering).
|
|
58
|
+
*/
|
|
59
|
+
export function redactPattern(pattern: RegExp, replacement = "[REDACTED]"): Processor {
|
|
60
|
+
return {
|
|
61
|
+
name: "redactPattern",
|
|
62
|
+
processOutput: (message) => {
|
|
63
|
+
if (message.type === "text" || message.type === "thinking") {
|
|
64
|
+
const redacted = message.text.replace(pattern, replacement);
|
|
65
|
+
if (redacted !== message.text) {
|
|
66
|
+
return Verdict.continue({ ...message, text: redacted });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return Verdict.continue(message);
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
Processor,
|
|
3
|
+
ProcessorContext,
|
|
4
|
+
ProcessorVerdict,
|
|
5
|
+
ToolCall,
|
|
6
|
+
} from "./processor.js";
|
|
7
|
+
export { Verdict } from "./processor.js";
|
|
8
|
+
|
|
9
|
+
export { runProcessorChain } from "./runner.js";
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
denyTools,
|
|
13
|
+
requireScope,
|
|
14
|
+
redactPattern,
|
|
15
|
+
} from "./builtins.js";
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Processor — typed pre/post pipeline around the agent loop.
|
|
3
|
+
*
|
|
4
|
+
* One generic shape across three hook points:
|
|
5
|
+
*
|
|
6
|
+
* - processInput(prompt, ctx) → before each iteration's model call
|
|
7
|
+
* - processOutput(message, ctx) → after each emitted message
|
|
8
|
+
* - processToolCall(call, ctx) → before each tool call (runtime-driven)
|
|
9
|
+
*
|
|
10
|
+
* Why this exists: the user's "pre-tool-use hook", "policy", "falsifier", and
|
|
11
|
+
* "classifier" requirements are all the same shape — a typed step around the
|
|
12
|
+
* agent loop with access to RequestContext, an abort channel, and the
|
|
13
|
+
* ability to mutate or reject. Inventing four parallel APIs is the smell;
|
|
14
|
+
* one Processor interface is the cure.
|
|
15
|
+
*
|
|
16
|
+
* Verdict semantics differ by hook:
|
|
17
|
+
*
|
|
18
|
+
* processInput deny → agent loop ends with WorkflowError(reason)
|
|
19
|
+
* processOutput deny → message dropped; loop continues
|
|
20
|
+
* processToolCall deny → tool short-circuited; reason returned to the
|
|
21
|
+
* model as the tool result; loop continues
|
|
22
|
+
*
|
|
23
|
+
* abort (any hook) → whole agent loop ends with WorkflowError(reason)
|
|
24
|
+
*
|
|
25
|
+
* Composition: workflow-level processors run first, then agent-level. First
|
|
26
|
+
* non-`continue` verdict short-circuits the chain for that hook target.
|
|
27
|
+
*
|
|
28
|
+
* Built-ins live in ./builtins.ts; chain executor lives in ./runner.ts.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import type { AgentMessage } from "../types/protocol.js";
|
|
32
|
+
import type { RequestContext } from "../request-context/request-context.js";
|
|
33
|
+
|
|
34
|
+
/** Proposed tool call. Mirrors the relevant fields of AgentMessageToolUse but
|
|
35
|
+
* lives as its own type so runtime adapters (candidate #1) can populate it
|
|
36
|
+
* from their internal call shape without coupling to the agent message protocol. */
|
|
37
|
+
export interface ToolCall {
|
|
38
|
+
toolName: string;
|
|
39
|
+
toolInput: Record<string, unknown>;
|
|
40
|
+
toolUseId: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Per-hook context. Minimal by design — observability sinks and stream
|
|
44
|
+
* writers are NOT shipped in v1; add when concrete need shows up. */
|
|
45
|
+
export interface ProcessorContext {
|
|
46
|
+
/** Per-run typed bag (tenant identity + freeform). */
|
|
47
|
+
requestContext: RequestContext;
|
|
48
|
+
/** Parent-loop cancellation — long-running processors should pass to fetch/etc. */
|
|
49
|
+
abortSignal: AbortSignal;
|
|
50
|
+
/** How many times processors have triggered retry for this generation. */
|
|
51
|
+
retryCount: number;
|
|
52
|
+
/** Which agent loop triggered this hook. */
|
|
53
|
+
agentId: string;
|
|
54
|
+
/** Iteration of the agent loop (1-based). */
|
|
55
|
+
iteration: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Verdict returned by every processor method.
|
|
60
|
+
* `continue` carries the (possibly mutated) value forward.
|
|
61
|
+
* `deny` and `abort` short-circuit the chain; their loop-level effect is
|
|
62
|
+
* defined per hook (see file header).
|
|
63
|
+
*/
|
|
64
|
+
export type ProcessorVerdict<T> =
|
|
65
|
+
| { kind: "continue"; value: T }
|
|
66
|
+
| { kind: "deny"; reason: string }
|
|
67
|
+
| { kind: "abort"; reason: string };
|
|
68
|
+
|
|
69
|
+
/** Construction helpers — keep call sites readable. */
|
|
70
|
+
export const Verdict = {
|
|
71
|
+
continue: <T>(value: T): ProcessorVerdict<T> => ({ kind: "continue", value }),
|
|
72
|
+
deny: <T = never>(reason: string): ProcessorVerdict<T> => ({ kind: "deny", reason }),
|
|
73
|
+
abort: <T = never>(reason: string): ProcessorVerdict<T> => ({ kind: "abort", reason }),
|
|
74
|
+
} as const;
|
|
75
|
+
|
|
76
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* A Processor implements zero or more of the three hook methods. Methods
|
|
80
|
+
* may be sync or async. Omit a method to opt out of that hook.
|
|
81
|
+
*
|
|
82
|
+
* Processors should be cheap and deterministic where possible — the chain
|
|
83
|
+
* runs sequentially and gating is order-sensitive.
|
|
84
|
+
*/
|
|
85
|
+
export interface Processor {
|
|
86
|
+
/** Stable name for logging / metrics. Defaults to constructor / class name. */
|
|
87
|
+
readonly name?: string;
|
|
88
|
+
|
|
89
|
+
processInput?(
|
|
90
|
+
prompt: string,
|
|
91
|
+
ctx: ProcessorContext,
|
|
92
|
+
): MaybePromise<ProcessorVerdict<string>>;
|
|
93
|
+
|
|
94
|
+
processOutput?(
|
|
95
|
+
message: AgentMessage,
|
|
96
|
+
ctx: ProcessorContext,
|
|
97
|
+
): MaybePromise<ProcessorVerdict<AgentMessage>>;
|
|
98
|
+
|
|
99
|
+
processToolCall?(
|
|
100
|
+
call: ToolCall,
|
|
101
|
+
ctx: ProcessorContext,
|
|
102
|
+
): MaybePromise<ProcessorVerdict<ToolCall>>;
|
|
103
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Processor chain runner — sequentially applies a list of processors to a
|
|
3
|
+
* value at one hook point, threading the (possibly mutated) value through
|
|
4
|
+
* each step. First non-`continue` verdict short-circuits the rest of the
|
|
5
|
+
* chain for that target.
|
|
6
|
+
*
|
|
7
|
+
* The chain is hook-agnostic: caller passes a `select` function that picks
|
|
8
|
+
* the relevant method off each Processor. Returns the final verdict — the
|
|
9
|
+
* agent loop interprets it per-hook semantics.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
Processor,
|
|
14
|
+
ProcessorContext,
|
|
15
|
+
ProcessorVerdict,
|
|
16
|
+
} from "./processor.js";
|
|
17
|
+
|
|
18
|
+
type HookSelector<T> = (
|
|
19
|
+
p: Processor,
|
|
20
|
+
) => ((value: T, ctx: ProcessorContext) => ProcessorVerdict<T> | Promise<ProcessorVerdict<T>>) | undefined;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Run a chain of processors against `initial`. Skips processors that don't
|
|
24
|
+
* implement the selected hook. Returns the final verdict; for `continue`
|
|
25
|
+
* the `value` is the threaded-through (possibly mutated) result.
|
|
26
|
+
*/
|
|
27
|
+
export async function runProcessorChain<T>(
|
|
28
|
+
processors: readonly Processor[],
|
|
29
|
+
selectHook: HookSelector<T>,
|
|
30
|
+
initial: T,
|
|
31
|
+
ctx: ProcessorContext,
|
|
32
|
+
): Promise<ProcessorVerdict<T>> {
|
|
33
|
+
let current = initial;
|
|
34
|
+
for (const p of processors) {
|
|
35
|
+
const fn = selectHook(p);
|
|
36
|
+
if (!fn) continue;
|
|
37
|
+
const verdict = await fn.call(p, current, ctx);
|
|
38
|
+
if (verdict.kind !== "continue") return verdict;
|
|
39
|
+
current = verdict.value;
|
|
40
|
+
}
|
|
41
|
+
return { kind: "continue", value: current };
|
|
42
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export {
|
|
2
|
+
RequestContext,
|
|
3
|
+
ReservedKeyError,
|
|
4
|
+
NonSerialisableValueError,
|
|
5
|
+
AC_RESERVED_PREFIX,
|
|
6
|
+
AC_TEAM_ID,
|
|
7
|
+
AC_RUN_ID,
|
|
8
|
+
AC_WORKFLOW_ID,
|
|
9
|
+
AC_FACTORY_ID,
|
|
10
|
+
AC_API_KEY_SCOPES,
|
|
11
|
+
AC_PARENT_RUN_ID,
|
|
12
|
+
AC_ABORT_SIGNAL,
|
|
13
|
+
} from "./request-context.js";
|
|
14
|
+
export type {
|
|
15
|
+
RequestContextReserved,
|
|
16
|
+
RequestContextWire,
|
|
17
|
+
} from "./request-context.js";
|