@orkestrel/tool 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1180 @@
1
+ import { AgentInterface } from '@orkestrel/agent';
2
+ import { AgentRegistryInterface } from '@orkestrel/agent';
3
+ import { ArrayShape } from '@orkestrel/contract';
4
+ import { BooleanShape } from '@orkestrel/contract';
5
+ import { ContractInterface } from '@orkestrel/contract';
6
+ import { ConversationStoreInterface } from '@orkestrel/agent';
7
+ import { LiteralShape } from '@orkestrel/contract';
8
+ import { NumberShape } from '@orkestrel/contract';
9
+ import { ObjectShape } from '@orkestrel/contract';
10
+ import { OptionalShape } from '@orkestrel/contract';
11
+ import { StringShape } from '@orkestrel/contract';
12
+ import { ToolInterface } from '@orkestrel/agent';
13
+ import { ToolManagerInterface } from '@orkestrel/agent';
14
+ import { UnionShape } from '@orkestrel/contract';
15
+ import { WorkflowDefinition } from '@orkestrel/workflow';
16
+ import { WorkflowFunction } from '@orkestrel/workflow';
17
+ import { WorkflowResult } from '@orkestrel/workflow';
18
+ import { WorkflowRunnerInterface } from '@orkestrel/workflow';
19
+ import { WorkflowStatus } from '@orkestrel/workflow';
20
+ import { WorkflowStoreInterface } from '@orkestrel/workflow';
21
+ import { WorkspaceManagerInterface } from '@orkestrel/agent';
22
+ import { WorkspaceStoreInterface } from '@orkestrel/agent';
23
+
24
+ /**
25
+ * The maximum nesting depth a delegation chain (agent tool → sub-agent → agent tool → …) may
26
+ * reach — the bound {@link import('./factories.js').createAgentTool}'s depth/cycle guard
27
+ * enforces.
28
+ *
29
+ * @remarks
30
+ * Deliberately a SEPARATE constant from {@link MAX_WORKFLOW_DEPTH} (rather than the two guards
31
+ * sharing one reference): the two guards bound DIFFERENT chains (workflow nesting vs. agent
32
+ * delegation) that happen to share a value today, and keeping this bound decoupled means a
33
+ * future change to one never silently shifts the other. Same numeric value by convention, not
34
+ * by shared reference.
35
+ */
36
+ export declare const AGENT_TOOL_DEPTH = 8;
37
+
38
+ export declare const AGENT_TOOL_DESCRIPTION: string;
39
+
40
+ /**
41
+ * The name {@link import('./factories.js').createAgentTool} advertises by default — the key a
42
+ * model calls and the `ToolManagerInterface` (`@orkestrel/agent`) registers under.
43
+ */
44
+ export declare const AGENT_TOOL_NAME = "agent";
45
+
46
+ /**
47
+ * The lean {@link import('@orkestrel/agent').ToolInterface.summary} {@link import('./factories.js').createAgentTool}
48
+ * advertises in place of {@link AGENT_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
49
+ * (`@orkestrel/agent`) advertises `summary ?? description`, so this one-sentence text stands in
50
+ * for the full teaching description; the full text stays retrievable via
51
+ * {@link import('./factories.js').createDescribeTool}.
52
+ */
53
+ export declare const AGENT_TOOL_SUMMARY = "Delegate a task to a sub-agent and return its result; each call runs one sub-agent turn to completion. Call describe('agent') for the optional provider/tools/system overrides.";
54
+
55
+ /**
56
+ * Options for {@link import('./factories.js').createAgentFunction} — the OPT-IN adapter that
57
+ * wraps a live `AgentInterface` (`@orkestrel/agent`) as a `WorkflowFunction`
58
+ * (`@orkestrel/workflow`), folding a nested workflow-authoring depth / cycle guard into its
59
+ * closure.
60
+ *
61
+ * @remarks
62
+ * All fields are optional: omitted entirely, the adapter runs the agent with no nested workflow
63
+ * tool bound and no depth/cycle bound (depth `0`, empty ancestry).
64
+ * - `runner` — when supplied, the adapter BINDS a depth/cycle-aware
65
+ * {@link import('./factories.js').createWorkflowTool} onto the agent's `context.tools` (the
66
+ * propagation seam), so the agent can author + run a NESTED workflow through it. Omitted ⇒ the
67
+ * agent runs with no workflow tool bound.
68
+ * - `depth` — this invocation's nesting depth (default `0`); the bound workflow tool runs its
69
+ * nested workflow at `depth + 1`, bounded by
70
+ * {@link import('./constants.js').MAX_WORKFLOW_DEPTH}.
71
+ * - `ancestry` — the workflow / agent identifiers already in this run chain (default empty); a
72
+ * cycle (this agent already present) is rejected with a typed `DEPTH` `WorkflowError`
73
+ * (`@orkestrel/workflow`).
74
+ */
75
+ export declare interface AgentFunctionOptions {
76
+ readonly runner?: WorkflowRunnerInterface;
77
+ readonly depth?: number;
78
+ readonly ancestry?: readonly string[];
79
+ }
80
+
81
+ /**
82
+ * The ancestry identifier of an agent in a run chain — `agent:<name>`.
83
+ *
84
+ * @remarks
85
+ * The agent counterpart of {@link workflowTag}: {@link import('./factories.js').createAgentFunction}
86
+ * / {@link import('./factories.js').createWorkflowTool} guard against re-entering an agent or
87
+ * workflow already in the chain (a typed `DEPTH` `WorkflowError`, `@orkestrel/workflow`). The
88
+ * `agent:` namespace keeps it distinct from a same-string workflow id.
89
+ *
90
+ * @param name - The agent's identifier / registry name
91
+ * @returns The namespaced ancestry tag (`agent:<name>`)
92
+ */
93
+ export declare function agentTag(name: string): string;
94
+
95
+ /**
96
+ * The FLAT args {@link import('./factories.js').createAgentTool} accepts — a delegated `task`
97
+ * plus the minimal optional `AgentJobInput` (`@orkestrel/agent`) fields a caller may override
98
+ * per-call.
99
+ *
100
+ * @remarks
101
+ * `task` becomes the seed user message in the sub-agent's rehydrated conversation
102
+ * (`AgentJobInput.messages`). `provider` / `tools` / `system` shadow the tool's own
103
+ * {@link AgentToolOptions} defaults for this ONE call when supplied.
104
+ */
105
+ export declare interface AgentToolArguments {
106
+ readonly task: string;
107
+ readonly provider?: string;
108
+ readonly tools?: readonly string[];
109
+ readonly system?: string;
110
+ }
111
+
112
+ /**
113
+ * Thrown by {@link import('./factories.js').createAgentTool}'s and
114
+ * {@link import('./factories.js').createDescribeTool}'s handlers on every failure path — a
115
+ * malformed / unresolvable call or an unknown tool name (`TOOL`), or a delegation that would
116
+ * exceed the configured depth bound or re-enter an ancestor (`DEPTH`).
117
+ *
118
+ * @remarks
119
+ * Carries a machine-readable `code` (see {@link import('./types.js').AgentToolErrorCode}) and
120
+ * an optional `context` bag for structured diagnostics. The `ToolManagerInterface`
121
+ * (`@orkestrel/agent`) isolates every throw into the canonical tool result's top-level `error`
122
+ * (AGENTS §14) — nothing escapes the run.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * import { AgentToolError, isAgentToolError } from '@src/core'
127
+ *
128
+ * try {
129
+ * throw new AgentToolError('TOOL', 'task is required')
130
+ * } catch (error) {
131
+ * if (isAgentToolError(error)) console.log(error.code) // 'TOOL'
132
+ * }
133
+ * ```
134
+ */
135
+ export declare class AgentToolError extends Error {
136
+ readonly code: AgentToolErrorCode;
137
+ readonly context?: Readonly<Record<string, unknown>>;
138
+ constructor(code: AgentToolErrorCode, message: string, context?: Readonly<Record<string, unknown>>);
139
+ }
140
+
141
+ /**
142
+ * The error CODE a thrown {@link import('./errors.js').AgentToolError} carries — the SAME
143
+ * two-code shape `@orkestrel/workflow`'s `WorkflowError` uses for its own tool guard, kept
144
+ * distinct per package (AGENTS §14: a thrown, typed, code-bearing error, never a `{ error }`
145
+ * return).
146
+ *
147
+ * @remarks
148
+ * `TOOL` — malformed / unresolvable call args (a missing `task`, no resolvable `provider`).
149
+ * `DEPTH` — the delegation would exceed {@link import('./constants.js').AGENT_TOOL_DEPTH}, or
150
+ * the resolved agent is already an ancestor (a cycle).
151
+ */
152
+ export declare type AgentToolErrorCode = 'TOOL' | 'DEPTH';
153
+
154
+ /**
155
+ * Options for {@link import('./factories.js').createAgentTool} — the sub-agent delegation
156
+ * defaults, the nesting-depth / cycle guard bookkeeping, and the advertised tool overrides.
157
+ *
158
+ * @remarks
159
+ * - `name` / `description` — advertised tool overrides; default to
160
+ * {@link import('./constants.js').AGENT_TOOL_NAME} / {@link import('./constants.js').AGENT_TOOL_DESCRIPTION}.
161
+ * - `provider` — the DEFAULT registry provider key used when a call omits `provider`; a call
162
+ * that supplies its own `provider` overrides this. One of `provider` (here or per-call) MUST
163
+ * resolve, or the handler throws a typed `TOOL` {@link import('./errors.js').AgentToolError}.
164
+ * - `tools` — the DEFAULT registry tool-name list loaded into the delegated sub-agent; a
165
+ * per-call `tools` list overrides (never merges with) this default.
166
+ * - `system` — the DEFAULT system prompt seeding the sub-agent's context; a per-call `system`
167
+ * overrides this.
168
+ * - `depth` — this invocation's nesting depth (default `0`); a delegated sub-agent that itself
169
+ * calls this tool again runs at `depth + 1`, bounded by
170
+ * {@link import('./constants.js').AGENT_TOOL_DEPTH}.
171
+ * - `ancestry` — the sub-agent identifiers already in this delegation chain (default empty); a
172
+ * cycle (the resolved agent already present) is rejected with a typed `DEPTH`
173
+ * {@link import('./errors.js').AgentToolError}.
174
+ * - `store` — this package's ADDITION: when supplied, the handler persists the delegated
175
+ * sub-agent's active conversation snapshot (`store.set(agent.context.conversations.active.snapshot())`)
176
+ * once `agent.generate()` settles successfully, before returning — one snapshot per delegation
177
+ * (each `registry.build` mints a fresh conversation id, so a shared store accumulates an
178
+ * audit log rather than colliding). Omitted ⇒ no persistence from this tool.
179
+ *
180
+ * Conversation persistence for a delegated sub-agent has TWO independent seams, composable
181
+ * together: this `store` slot persists EACH delegation's conversation individually, and/or an
182
+ * `AgentRegistryInterface` built with `AgentRegistryOptions.store` (`@orkestrel/agent`) backs
183
+ * EVERY agent it builds — including ones built through this tool — with a store-backed
184
+ * `ConversationManagerInterface` of its own. Neither is required; either or both may be used.
185
+ */
186
+ export declare interface AgentToolOptions {
187
+ readonly name?: string;
188
+ readonly description?: string;
189
+ readonly provider?: string;
190
+ readonly tools?: readonly string[];
191
+ readonly system?: string;
192
+ readonly depth?: number;
193
+ readonly ancestry?: readonly string[];
194
+ readonly store?: ConversationStoreInterface;
195
+ }
196
+
197
+ /**
198
+ * The shape of {@link import('./types.js').AgentToolArguments} —
199
+ * {@link import('./factories.js').createAgentTool}'s advertised `parameters`.
200
+ *
201
+ * @remarks
202
+ * `task` is the only required field (a non-empty string); `provider` / `tools` / `system`
203
+ * are per-call overrides of the tool's own configured defaults.
204
+ */
205
+ export declare const agentToolShape: ObjectShape<{
206
+ task: StringShape;
207
+ provider: OptionalShape<StringShape>;
208
+ tools: OptionalShape<ArrayShape<StringShape>>;
209
+ system: OptionalShape<StringShape>;
210
+ }>;
211
+
212
+ /**
213
+ * Complete a {@link WorkflowDraft} into a strict {@link WorkflowDefinition} — synthesize any
214
+ * MISSING `id` deterministically + positionally, and default any MISSING `name` to its
215
+ * (now-resolved) `id`.
216
+ *
217
+ * @remarks
218
+ * The positional id scheme is stable and human-legible: the workflow is `wf`, phase `i` is
219
+ * `phase-<i>`, and task `j` of that phase is `<phaseId>-task-<j>` (so a provided phase id flows
220
+ * into its tasks' synthesized ids). A PROVIDED `id` / `name` at any level is kept VERBATIM —
221
+ * synthesis touches only the omitted ones. A missing `name` defaults to the resolved `id` (never
222
+ * the other way round), so the result always has both. `run`, `description`, the per-phase
223
+ * `concurrency` / `bail`, the per-task `retries` / `timeout`, and the workflow `bail` carry over
224
+ * unchanged. The result is a complete {@link WorkflowDefinition}; the caller still validates it
225
+ * against the STRICT contract.
226
+ *
227
+ * @param draft - The draft workflow (id/name optional at all three levels)
228
+ * @returns A complete {@link WorkflowDefinition} with every id/name filled
229
+ */
230
+ export declare function completeDraft(draft: WorkflowDraft): WorkflowDefinition;
231
+
232
+ /**
233
+ * Complete one {@link PhaseDraft} into a strict phase definition — the per-phase step of
234
+ * {@link completeDraft} (phase `index` → `phase-<index>` when its id is omitted).
235
+ *
236
+ * @param phase - The draft phase
237
+ * @param index - The phase's positional index in the workflow
238
+ * @returns A complete phase definition
239
+ */
240
+ export declare function completePhaseDraft(phase: PhaseDraft, index: number): WorkflowDefinition['phases'][number];
241
+
242
+ /**
243
+ * Complete one {@link TaskDraft} into a strict task definition — the per-task leaf step of
244
+ * {@link completeDraft} (task `index` of phase `<phaseId>` → `<phaseId>-task-<index>` when its id
245
+ * is omitted).
246
+ *
247
+ * @param task - The draft task
248
+ * @param phaseId - The (resolved) parent phase id, so the synthesized task id nests under it
249
+ * @param index - The task's positional index within its phase
250
+ * @returns A complete task definition
251
+ */
252
+ export declare function completeTaskDraft(task: TaskDraft, phaseId: string, index: number): WorkflowDefinition['phases'][number]['tasks'][number];
253
+
254
+ /**
255
+ * Wrap a live `AgentInterface` (`@orkestrel/agent`) as a {@link WorkflowFunction}
256
+ * (`@orkestrel/workflow`) — the OPT-IN adapter that runs the agent to a settled result, folding
257
+ * a nested workflow-authoring depth / cycle guard into its own closure.
258
+ *
259
+ * @remarks
260
+ * OWNED here now (ported from `@orkestrel/workflow`). Composes into a caller's
261
+ * `WorkflowOptions.functions` registry like any other behavior; the pure workflow runner has no
262
+ * knowledge of agents itself. Before running the agent, the depth/cycle guard REJECTS the call
263
+ * (a THROWN typed `DEPTH` `WorkflowError`, which the leaf `fail`s) when running it would push a
264
+ * nested chain past {@link import('./constants.js').MAX_WORKFLOW_DEPTH}, OR when this agent is
265
+ * already an ancestor (a cycle). When {@link import('./types.js').AgentFunctionOptions.runner}
266
+ * is supplied, the adapter BINDS a depth/cycle-aware {@link createWorkflowTool} onto the agent's
267
+ * `context.tools` (the propagation seam) — closed over `depth` and the extended ancestry (the
268
+ * tool itself computes `depth + 1` internally) — so the agent can author + run a NESTED workflow
269
+ * through it; the wrapped default is the CURRENT task's own workflow id (used only on a no-args
270
+ * tool call). The task's cancellation folds into the agent run: an already-aborted
271
+ * `controller.signal` cancels the agent up front; otherwise a one-shot listener fires
272
+ * `agent.abort(reason)` when the task cancels, removed in `finally`. `agent.generate()` resolves
273
+ * a partial `AgentResult` on a cancel (never rejects), returned as the task's completed value.
274
+ *
275
+ * A bound agent is effectively SINGLE-RUN: `context.tools.add` binds one `ToolInterface` under
276
+ * the fixed {@link import('./constants.js').WORKFLOW_TOOL_NAME}, and `agent.generate()` /
277
+ * `agent.abort()` are per-agent state. Two CONCURRENT tasks sharing the SAME `agent` instance
278
+ * race on that one tool binding (last-write-wins) and on generate/abort — give each concurrent
279
+ * task its OWN agent instance.
280
+ *
281
+ * @param agent - The live `AgentInterface` to run
282
+ * @param options - The nested-workflow binding + depth/cycle bookkeeping (see {@link import('./types.js').AgentFunctionOptions})
283
+ * @returns A {@link WorkflowFunction} that runs `agent` to its settled result
284
+ *
285
+ * @example
286
+ * ```ts
287
+ * import { createAgentFunction } from '@src/core'
288
+ * import { createWorkflowRunner } from '@orkestrel/workflow'
289
+ *
290
+ * const runner = createWorkflowRunner()
291
+ * const review = createAgentFunction(myAgent, { runner })
292
+ * await runner.execute(definition, { functions: { review } })
293
+ * ```
294
+ */
295
+ export declare function createAgentFunction(agent: AgentInterface, options?: AgentFunctionOptions): WorkflowFunction;
296
+
297
+ /**
298
+ * Build an LLM-callable sub-agent delegation tool — resolves a live, seeded `AgentInterface`
299
+ * from `registry` and runs it to completion for ONE delegated `task`.
300
+ *
301
+ * @remarks
302
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
303
+ * {@link import('./shapers.js').agentToolShape}, assembles an `AgentJobInput` (`task` seeds the
304
+ * sub-agent's conversation as a single `user` message; `provider` / `tools` / `system` fall
305
+ * back to the tool's own {@link import('./types.js').AgentToolOptions} defaults), rehydrates the sub-agent via
306
+ * `registry.build`, runs it with `agent.generate()`, and returns the settled
307
+ * `AgentResult.content` string (the sub-agent's final text). A missing / unresolvable `provider`, or a malformed call, THROWS a typed `TOOL`
308
+ * {@link import('./errors.js').AgentToolError}; a delegation that would exceed
309
+ * {@link import('./constants.js').AGENT_TOOL_DEPTH}, or re-enter an already-delegated agent (a
310
+ * cycle), THROWS a typed `DEPTH` {@link import('./errors.js').AgentToolError} — both isolated
311
+ * by the `ToolManagerInterface` into the canonical tool result's top-level `error`.
312
+ *
313
+ * `AgentInterface` (`@orkestrel/agent`) exposes no teardown method — a bound sub-agent's
314
+ * lifetime is the single `generate()` call this handler awaits; there is nothing to release
315
+ * afterwards (unlike a store-backed resource, its state lives entirely in the resolved
316
+ * `AgentContextInterface`, owned by the caller's registry).
317
+ *
318
+ * @param registry - The `AgentRegistryInterface` a delegated job resolves against (providers,
319
+ * tools, authorities, schedulers, and the `build` rehydration seam)
320
+ * @param options - Delegation defaults, depth/ancestry bookkeeping, and advertised overrides
321
+ * (see {@link import('./types.js').AgentToolOptions})
322
+ * @returns A `ToolInterface` (named {@link import('./constants.js').AGENT_TOOL_NAME} by default)
323
+ *
324
+ * @example
325
+ * ```ts
326
+ * import { createAgentTool } from '@src/core'
327
+ * import { createAgentRegistry, createToolManager } from '@orkestrel/agent'
328
+ *
329
+ * const registry = createAgentRegistry({ providers: { openai: myProvider } })
330
+ * const tool = createAgentTool(registry, { provider: 'openai' })
331
+ * const tools = createToolManager()
332
+ * tools.add(tool) // a model can now delegate a task to a sub-agent
333
+ * ```
334
+ */
335
+ export declare function createAgentTool(registry: AgentRegistryInterface, options?: AgentToolOptions): ToolInterface;
336
+
337
+ /**
338
+ * Build an LLM-callable tool that returns the FULL `description` of another registered tool by
339
+ * name — the counterpart to the lean `summary` the other tools in this package advertise
340
+ * (`AGENT_TOOL_SUMMARY` / `WORKFLOW_TOOL_SUMMARY` / `WORKSPACE_TOOL_SUMMARY`).
341
+ *
342
+ * @remarks
343
+ * `ToolManagerInterface.definitions()` (`@orkestrel/agent`) advertises `tool.summary ??
344
+ * tool.description` — a lean one-sentence summary stands in for a tool's full teaching
345
+ * description when `summary` is set, keeping the advertised tool list compact for a small model.
346
+ * This tool is the on-demand expansion seam: given a registered tool's `name`, it looks the tool
347
+ * up via `tools.tool(name)` and returns its full `description` (falling back to `summary` when a
348
+ * tool has no `description` of its own, then a placeholder when it has neither).
349
+ *
350
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
351
+ * {@link import('./shapers.js').describeToolShape}, RETURNS the plain description string on
352
+ * success, THROWS a typed `TOOL` {@link import('./errors.js').AgentToolError} on a malformed call
353
+ * or an unknown tool name.
354
+ *
355
+ * @param tools - The `ToolManagerInterface` (`@orkestrel/agent`) whose registered tools this
356
+ * tool can describe
357
+ * @returns A `ToolInterface` (named {@link import('./constants.js').DESCRIBE_TOOL_NAME})
358
+ *
359
+ * @example
360
+ * ```ts
361
+ * import { createDescribeTool, createWorkflowTool } from '@src/core'
362
+ * import { createToolManager } from '@orkestrel/agent'
363
+ *
364
+ * const tools = createToolManager()
365
+ * tools.add(createWorkflowTool(definition, runner))
366
+ * tools.add(createDescribeTool(tools))
367
+ * const full = await tools.execute({ id: '1', name: 'describe', arguments: { name: 'workflow' } })
368
+ * full.value // the workflow tool's full teaching description
369
+ * ```
370
+ */
371
+ export declare function createDescribeTool(tools: ToolManagerInterface): ToolInterface;
372
+
373
+ /**
374
+ * Wrap a registered tool as a {@link WorkflowFunction} (`@orkestrel/workflow`) — the OPT-IN
375
+ * adapter that lets a `function`-form task run a `@orkestrel/agent` tool BY NAME.
376
+ *
377
+ * @remarks
378
+ * OWNED here now (ported from `@orkestrel/workflow`). Composes into a caller's
379
+ * `WorkflowOptions.functions` registry like any other behavior
380
+ * (`{ publish: createToolFunction(tools, 'publish') }`); the pure workflow runner has no
381
+ * knowledge of tools itself. The returned function executes `name` against `tools` with the
382
+ * task's `controller.input` as the call arguments, id-correlated to the task's own id. A
383
+ * `ToolManagerInterface.execute` (`@orkestrel/agent`) NEVER throws (a handler throw is isolated
384
+ * into `result.error`), so a failing tool is surfaced here as a THROWN `Error` carrying the
385
+ * original message as `cause` — the leaf `fail`s, honouring `bail`. An UNREGISTERED tool name is
386
+ * a programmer error (an explicit binding to a name that doesn't exist) — unlike the engine's
387
+ * own silent auto-complete of an unresolved task handler, this THROWS a typed `TOOL`
388
+ * `WorkflowError` (`@orkestrel/workflow`).
389
+ *
390
+ * @param tools - The `ToolManagerInterface` (`@orkestrel/agent`) the named tool is registered on
391
+ * @param name - The registered tool's name
392
+ * @returns A {@link WorkflowFunction} that runs the named tool
393
+ *
394
+ * @example
395
+ * ```ts
396
+ * import { createToolFunction } from '@src/core'
397
+ * import { createToolManager } from '@orkestrel/agent'
398
+ * import { createWorkflowRunner } from '@orkestrel/workflow'
399
+ *
400
+ * const tools = createToolManager()
401
+ * tools.add(myPublishTool)
402
+ * const runner = createWorkflowRunner()
403
+ * await runner.execute(definition, { functions: { publish: createToolFunction(tools, 'publish') } })
404
+ * ```
405
+ */
406
+ export declare function createToolFunction(tools: ToolManagerInterface, name: string): WorkflowFunction;
407
+
408
+ /**
409
+ * Compile the LENIENT workflow DRAFT contract — identical to `createWorkflowContract`
410
+ * (`@orkestrel/workflow`) EXCEPT `id` and `name` are OPTIONAL at all three levels (workflow /
411
+ * phase / task), so a small model can omit the six identity strings.
412
+ *
413
+ * @remarks
414
+ * The widened authoring surface {@link createWorkflowTool} parses an authored blob through
415
+ * before {@link import('./helpers.js').completeDraft} fills the missing ids/names. It does NOT
416
+ * relax the canonical contract — `createWorkflowContract` (`@orkestrel/workflow`) stays
417
+ * byte-for-byte unchanged and STRICT, and the completed draft is re-validated against THAT
418
+ * strict gate before running (soundness preserved). A PROVIDED `id` / `name` still carries
419
+ * `minLength: 1`, so an explicitly-empty `id: ''` is REJECTED (parses to `undefined`), never
420
+ * auto-filled — keeping "garbage" distinct from "omitted". `run` stays optional (a plain name
421
+ * string).
422
+ *
423
+ * @returns The compiled {@link import('./types.js').WorkflowDraft} contract
424
+ *
425
+ * @example
426
+ * ```ts
427
+ * import { createWorkflowDraftContract, completeDraft } from '@src/core'
428
+ *
429
+ * const draft = createWorkflowDraftContract()
430
+ * const parsed = draft.parse({ phases: [{ tasks: [{ run: 'compile' }] }] })
431
+ * const definition = parsed && completeDraft(parsed) // ids/names filled positionally
432
+ * draft.parse({ id: '', phases: [] }) // undefined — an explicit empty id is rejected
433
+ * ```
434
+ */
435
+ export declare function createWorkflowDraftContract(): ContractInterface<WorkflowDraft>;
436
+
437
+ /**
438
+ * Wrap a {@link WorkflowDefinition} as an LLM-callable tool — it ADVERTISES the SIMPLE flat
439
+ * authoring shape (`{ name?, steps: [{ name }] }`) as its `parameters` so even a small model can
440
+ * author a complete tree, and its handler EXPANDS / COMPLETES the authored blob, validates it
441
+ * against the STRICT contract, runs it through `runner`, and, when
442
+ * {@link import('./types.js').WorkflowToolOptions.store} is supplied, PERSISTS each executed
443
+ * workflow's final snapshot after the run settles.
444
+ *
445
+ * @remarks
446
+ * A plain `ToolManagerInterface`-compatible tool (`@orkestrel/agent`), reproducing
447
+ * `@orkestrel/workflow`'s former call contract exactly (flat / draft / full authoring forms, the
448
+ * strict soundness gate, the depth/cycle guard). It is ALSO the propagation carrier
449
+ * {@link createAgentFunction} binds onto a wrapped agent's `context.tools`: because a tool
450
+ * handler receives ONLY the model-supplied `args` (no ambient context, no signal), the run's
451
+ * depth + ancestry are CLOSED OVER at bind time via {@link import('./types.js').WorkflowToolOptions},
452
+ * and the handler enforces the SAME depth / cycle guard itself before running the nested
453
+ * workflow at `depth + 1` with the extended ancestry.
454
+ *
455
+ * **Widened authoring surface (additive — the canonical contract + runner stay STRICT and
456
+ * unchanged).** A 2B model reliably CALLS the tool but cannot reliably emit the full four-level
457
+ * nested {@link WorkflowDefinition} (six required `id`/`name` strings, an all-or-nothing tree).
458
+ * So the tool ACCEPTS three authoring forms and converges them on the SAME strict
459
+ * `createWorkflowContract` gate before running (soundness preserved):
460
+ * - the FLAT shape `{ name?, steps: [{ name }] }` — the ADVERTISED `parameters` (the simplest
461
+ * form, {@link import('./helpers.js').expandSteps}'d into one one-task phase per step);
462
+ * - a nested DRAFT with any `id`/`name` OMITTED — {@link createWorkflowDraftContract}-parsed then
463
+ * {@link import('./helpers.js').completeDraft}'d (missing ids synthesized positionally);
464
+ * - the full nested {@link WorkflowDefinition} — the advanced escape-hatch, accepted as the draft
465
+ * super-set.
466
+ *
467
+ * The universal tool-handler contract (AGENTS §14): returns the plain run summary
468
+ * (`{ status, count }`) on success, THROWS a typed `WorkflowError` (`@orkestrel/workflow`) on
469
+ * every failure path — malformed authored args (`TOOL`), or an over-deep / cyclic nested run
470
+ * (`DEPTH`). The `ToolManagerInterface` isolates every throw into the canonical tool result's
471
+ * top-level `error`, so nothing escapes the run. `options.depth` / `options.ancestry` are the
472
+ * propagation carrier across a workflow → agent → workflow chain; `options.store` is this
473
+ * package's ADDITION — the persisted snapshot is retrievable via the store afterwards (a caller
474
+ * restores it through `@orkestrel/workflow`'s own `Workflow.restore` / store-backed factories).
475
+ *
476
+ * @param definition - The workflow the tool runs when called with no authored args
477
+ * @param runner - The `WorkflowRunnerInterface` (`@orkestrel/workflow`) that executes the (nested) workflow
478
+ * @param options - Depth/ancestry bookkeeping plus the optional durable store (see {@link import('./types.js').WorkflowToolOptions})
479
+ * @returns A `ToolInterface` (named {@link import('./constants.js').WORKFLOW_TOOL_NAME}) whose
480
+ * `parameters` advertise the flat authoring schema
481
+ *
482
+ * @example
483
+ * ```ts
484
+ * import { createWorkflowTool } from '@src/core'
485
+ * import { createWorkflowRunner, createMemoryWorkflowStore } from '@orkestrel/workflow'
486
+ * import { createToolManager } from '@orkestrel/agent'
487
+ *
488
+ * const runner = createWorkflowRunner()
489
+ * const store = createMemoryWorkflowStore()
490
+ * const tool = createWorkflowTool(definition, runner, { store })
491
+ * const tools = createToolManager()
492
+ * tools.add(tool) // authored runs are now persisted to `store` on settle
493
+ * ```
494
+ */
495
+ export declare function createWorkflowTool(definition: WorkflowDefinition, runner: WorkflowRunnerInterface, options?: WorkflowToolOptions): ToolInterface;
496
+
497
+ /**
498
+ * Build an LLM-callable workspace-editing tool — it ADVERTISES the `operation`-discriminated
499
+ * 13-op union ({@link import('./shapers.js').workspaceToolShape}) as its `parameters`, and its
500
+ * handler PARSES the model-supplied args against that contract and DISPATCHES the matched
501
+ * operation against the manager's ACTIVE workspace (the registry ops drive the manager itself),
502
+ * returning the plain result (throwing a typed `WorkspaceError`, `@orkestrel/agent`, on
503
+ * failure). EITHER drives a caller-supplied {@link WorkspaceToolOptions.manager} directly, OR
504
+ * constructs a fresh `WorkspaceManagerInterface` (`@orkestrel/agent`) over
505
+ * {@link import('./types.js').WorkspaceToolOptions.store} (via `@orkestrel/agent`'s
506
+ * `createWorkspaceManager`); neither given constructs a manager backed by `@orkestrel/agent`'s
507
+ * in-memory store default.
508
+ *
509
+ * @remarks
510
+ * MANAGER-DRIVEN: every edit / read op (read / list / has / search / replace / write / splice /
511
+ * prepend / append / move / remove) targets `manager.active`, so the model edits whichever
512
+ * workspace is active and a host can re-point it (`WorkspaceManagerInterface.switch`) between
513
+ * turns. Two REGISTRY ops make the model self-sufficient: `workspaces` LISTS the registered
514
+ * workspaces (each `{ id, files, active }`) so it can discover an id, and `switch` re-points the
515
+ * active workspace by id (lenient — an unknown id is a no-op reporting `switched: false`, never a
516
+ * throw).
517
+ *
518
+ * NO-ACTIVE RULE (the ergonomic seam): a WRITING op (write / splice / prepend / append / move /
519
+ * remove / replace) run when `manager.active` is `undefined` AUTO-CREATES + activates a default
520
+ * workspace (`manager.add()`) so the model can just start writing; a pure-READ op (read / list /
521
+ * has / search) against no active workspace returns the EMPTY result (`undefined` / `[]` /
522
+ * `false`), never creating one and never throwing.
523
+ *
524
+ * The handler conforms to the universal tool-handler contract (AGENTS §14): it `contract.parse`s
525
+ * the args, THROWS a `TOOL` `WorkspaceError` when no operation arm matched (a malformed / unknown
526
+ * operation), else `switch`es on `op.operation` and RETURNS the plain result — letting a
527
+ * `WorkspaceError` raised by the live workspace (`MODALITY` / `PATTERN` / `RANGE`) PROPAGATE
528
+ * uncaught. The range edit is the FLAT `'splice'` op: its four flat caret integers are
529
+ * reassembled into a `Range` (`@orkestrel/agent`) by `rangeOf` and fed to the workspace's ranged
530
+ * `write`.
531
+ *
532
+ * @param options - `manager` (drive directly) OR `store` (build a manager over it); neither ⇒
533
+ * an in-memory-backed manager (see {@link import('./types.js').WorkspaceToolOptions})
534
+ * @returns A `ToolInterface` (named {@link import('./constants.js').WORKSPACE_TOOL_NAME} by default)
535
+ *
536
+ * @example
537
+ * ```ts
538
+ * import { createWorkspaceTool } from '@src/core'
539
+ * import { createToolManager } from '@orkestrel/agent'
540
+ *
541
+ * const tool = createWorkspaceTool() // in-memory workspace, no persistence
542
+ * const tools = createToolManager()
543
+ * tools.add(tool)
544
+ * ```
545
+ */
546
+ export declare function createWorkspaceTool(options?: WorkspaceToolOptions): ToolInterface;
547
+
548
+ /**
549
+ * The DESCRIPTION {@link import('./factories.js').createDescribeTool} advertises.
550
+ *
551
+ * @remarks
552
+ * Deliberately short — unlike the workflow / workspace / agent tools, this one has no authoring
553
+ * schema or multi-step protocol to teach.
554
+ */
555
+ export declare const DESCRIBE_TOOL_DESCRIPTION = "Return the full description of a registered tool by its name. Required: name - the registered tool name (see another tool listing for available names).";
556
+
557
+ /**
558
+ * The name {@link import('./factories.js').createDescribeTool} advertises by default — the key a
559
+ * model calls and the `ToolManagerInterface` (`@orkestrel/agent`) registers under.
560
+ *
561
+ * @remarks
562
+ * Net-new: pairs with the other three tools' lean {@link AGENT_TOOL_SUMMARY} /
563
+ * {@link WORKFLOW_TOOL_SUMMARY} / {@link WORKSPACE_TOOL_SUMMARY} — a model that reads only the
564
+ * advertised summary can call `describe` with that tool's registered name to get its full
565
+ * teaching description back.
566
+ */
567
+ export declare const DESCRIBE_TOOL_NAME = "describe";
568
+
569
+ /**
570
+ * The lean {@link import('@orkestrel/agent').ToolInterface.summary} {@link import('./factories.js').createDescribeTool}
571
+ * advertises — this tool needs no teaching of its own, so its summary and description are both
572
+ * short.
573
+ */
574
+ export declare const DESCRIBE_TOOL_SUMMARY = "Return the full description of a named registered tool.";
575
+
576
+ /**
577
+ * The FLAT args {@link import('./factories.js').createDescribeTool} accepts — the registered
578
+ * tool `name` whose full `description` a model wants back.
579
+ *
580
+ * @remarks
581
+ * `name` must match a tool registered on the {@link import('@orkestrel/agent').ToolManagerInterface}
582
+ * the describe tool was built over — it is looked up via `tools.tool(name)`.
583
+ */
584
+ export declare interface DescribeToolArguments {
585
+ readonly name: string;
586
+ }
587
+
588
+ /**
589
+ * The shape of {@link import('./types.js').DescribeToolArguments} —
590
+ * {@link import('./factories.js').createDescribeTool}'s advertised `parameters`.
591
+ *
592
+ * @remarks
593
+ * `name` is the only field (a non-empty string) — the registered tool name to look up.
594
+ */
595
+ export declare const describeToolShape: ObjectShape<{
596
+ name: StringShape;
597
+ }>;
598
+
599
+ /**
600
+ * Expand a flat {@link WorkflowSteps} blob into a strict {@link WorkflowDefinition} — each step
601
+ * becomes a one-task phase, IN ORDER.
602
+ *
603
+ * @remarks
604
+ * The expansion of the tool's ADVERTISED surface: the deliberately-reduced flat form. Each
605
+ * {@link import('./types.js').WorkflowStep} maps to a phase holding exactly one task: the step's
606
+ * `name` becomes the task's `run` (the behavior-registry key). Ids/names are auto-filled
607
+ * positionally — it builds an ids-omitted {@link WorkflowDraft} and delegates to
608
+ * {@link completeDraft}, so the two lenient surfaces share ONE synthesis path (step `i` → phase
609
+ * `phase-<i>`, its task `phase-<i>-task-0`). The optional `name` becomes the workflow's `name`.
610
+ * The result is a complete definition the caller validates against the STRICT contract before
611
+ * running.
612
+ *
613
+ * @param flat - The flat steps blob (`{ name?, steps: [{ name }] }`)
614
+ * @returns A complete {@link WorkflowDefinition} (one one-task phase per step)
615
+ */
616
+ export declare function expandSteps(flat: WorkflowSteps): WorkflowDefinition;
617
+
618
+ /**
619
+ * Type guard narrowing an unknown caught value to an {@link AgentToolError}.
620
+ *
621
+ * @param value - The value to test (typically a `catch` binding)
622
+ * @returns `true` when `value` is an {@link AgentToolError}
623
+ *
624
+ * @example
625
+ * ```ts
626
+ * import { isAgentToolError } from '@src/core'
627
+ *
628
+ * try {
629
+ * // ...
630
+ * } catch (error) {
631
+ * if (isAgentToolError(error)) console.log(error.code)
632
+ * }
633
+ * ```
634
+ */
635
+ export declare function isAgentToolError(value: unknown): value is AgentToolError;
636
+
637
+ /**
638
+ * The maximum nesting depth a workflow → agent → workflow chain may reach — the bound
639
+ * {@link import('./factories.js').createAgentFunction} and
640
+ * {@link import('./factories.js').createWorkflowTool}'s depth/cycle guards enforce.
641
+ *
642
+ * @remarks
643
+ * OWNED here now (ported from `@orkestrel/workflow`, whose engine no longer uses it — only the
644
+ * tool-authoring guards this package now owns consume it). The limit lives in ONE place: an
645
+ * agent-function-wrapped agent running at this depth can no longer author + run a NESTED
646
+ * workflow through its bound workflow tool (that would be depth `MAX_WORKFLOW_DEPTH + 1`), so
647
+ * the over-deep invocation is REJECTED (a typed `DEPTH` `WorkflowError` throw, `@orkestrel/workflow`).
648
+ */
649
+ export declare const MAX_WORKFLOW_DEPTH = 8;
650
+
651
+ /** A draft phase — a `PhaseDefinition` (`@orkestrel/workflow`) with OPTIONAL `id` / `name` and {@link TaskDraft} tasks. */
652
+ export declare interface PhaseDraft {
653
+ readonly id?: string;
654
+ readonly name?: string;
655
+ readonly description?: string;
656
+ readonly tasks: readonly TaskDraft[];
657
+ /** Max tasks in flight at once (a resource throttle); omitted ⇒ unbounded. */
658
+ readonly concurrency?: number;
659
+ /** The per-phase failure-policy OVERRIDE; omitted ⇒ inherits the workflow `bail`. */
660
+ readonly bail?: boolean;
661
+ }
662
+
663
+ /**
664
+ * The shape of a PHASE in a draft workflow — identical to a strict phase shape EXCEPT `id` and
665
+ * `name` are OPTIONAL, and its tasks are {@link taskDraftShape}s.
666
+ */
667
+ export declare const phaseDraftShape: ObjectShape<{
668
+ id: OptionalShape<StringShape>;
669
+ name: OptionalShape<StringShape>;
670
+ description: OptionalShape<StringShape>;
671
+ tasks: ArrayShape<ObjectShape<{
672
+ id: OptionalShape<StringShape>;
673
+ name: OptionalShape<StringShape>;
674
+ description: OptionalShape<StringShape>;
675
+ run: OptionalShape<StringShape>;
676
+ retries: OptionalShape<NumberShape>;
677
+ timeout: OptionalShape<NumberShape>;
678
+ }>>;
679
+ concurrency: OptionalShape<NumberShape>;
680
+ bail: OptionalShape<LiteralShape<readonly [true, false]>>;
681
+ }>;
682
+
683
+ /**
684
+ * The shape of ONE flat step — `{ name }` — the building block of {@link workflowStepsShape}.
685
+ *
686
+ * @remarks
687
+ * `name` is the REGISTERED behavior name the step runs (it becomes the task's `run`). The tool
688
+ * expands each step into a one-task phase, in order ({@link import('./helpers.js').expandSteps}).
689
+ */
690
+ export declare const stepShape: ObjectShape<{
691
+ name: StringShape;
692
+ }>;
693
+
694
+ /**
695
+ * A draft task — a `TaskDefinition` (`@orkestrel/workflow`) with OPTIONAL `id` / `name`.
696
+ *
697
+ * @remarks
698
+ * The tool synthesizes a missing `id` positionally and defaults a missing `name` to its `id`
699
+ * ({@link import('./helpers.js').completeDraft}). A PROVIDED `id` / `name` is preserved verbatim
700
+ * (and must be non-empty — the draft contract's `minLength: 1`).
701
+ */
702
+ export declare interface TaskDraft {
703
+ readonly id?: string;
704
+ readonly name?: string;
705
+ readonly description?: string;
706
+ /** The behavior reference — a registry key resolved against a workflow's functions registry at construction; omitted ⇒ no handler. */
707
+ readonly run?: string;
708
+ /** Extra attempts after the first on failure (a non-negative integer); overrides the phase Runner default. Execution-only. */
709
+ readonly retries?: number;
710
+ /** The per-attempt deadline in milliseconds (a non-negative integer); overrides the phase Runner default. Execution-only. */
711
+ readonly timeout?: number;
712
+ }
713
+
714
+ /**
715
+ * The shape of a {@link import('./types.js').TaskDraft} — identical to a strict task shape
716
+ * EXCEPT `id` and `name` are OPTIONAL.
717
+ */
718
+ export declare const taskDraftShape: ObjectShape<{
719
+ id: OptionalShape<StringShape>;
720
+ name: OptionalShape<StringShape>;
721
+ description: OptionalShape<StringShape>;
722
+ run: OptionalShape<StringShape>;
723
+ retries: OptionalShape<NumberShape>;
724
+ timeout: OptionalShape<NumberShape>;
725
+ }>;
726
+
727
+ export declare const WORKFLOW_TOOL_DESCRIPTION: string;
728
+
729
+ /**
730
+ * A complete FLAT authoring example — the PRIMARY way a small model authors a workflow through
731
+ * {@link import('./factories.js').createWorkflowTool}: `{ name, steps: [{ name }] }`.
732
+ *
733
+ * @remarks
734
+ * OWNED here now (ported from `@orkestrel/workflow`). Each step becomes a one-task phase, in
735
+ * order; a step's `name` is a REGISTERED behavior name (not a label) — the registry key its
736
+ * task's `run` resolves against. The tool expands this
737
+ * ({@link import('./helpers.js').expandSteps}) into a valid `WorkflowDefinition`
738
+ * (`@orkestrel/workflow`). It is embedded VERBATIM in {@link WORKFLOW_TOOL_DESCRIPTION}.
739
+ */
740
+ export declare const WORKFLOW_TOOL_FLAT_EXAMPLE: WorkflowSteps;
741
+
742
+ /**
743
+ * The name {@link import('./factories.js').createWorkflowTool} advertises by default — the key a
744
+ * model calls and the `ToolManagerInterface` (`@orkestrel/agent`) registers under, and the name
745
+ * {@link import('./factories.js').createAgentFunction} binds the depth/cycle-aware workflow tool
746
+ * under onto a wrapped agent's `context.tools`.
747
+ *
748
+ * @remarks
749
+ * OWNED here now (ported from `@orkestrel/workflow`). The propagation seam's well-known key: when
750
+ * `createAgentFunction`'s `runner` option is supplied, it adds a `createWorkflowTool`-built tool
751
+ * under this name to the agent's `context.tools`, so it can author + run a NESTED workflow
752
+ * (bounded by {@link MAX_WORKFLOW_DEPTH}).
753
+ */
754
+ export declare const WORKFLOW_TOOL_NAME = "workflow";
755
+
756
+ /**
757
+ * A minimal NESTED authoring example — the ADVANCED escape-hatch form a model may use instead of
758
+ * the flat shape: a full `WorkflowDefinition` (`@orkestrel/workflow`).
759
+ *
760
+ * @remarks
761
+ * OWNED here now (ported from `@orkestrel/workflow`). The full four-level form, documented in
762
+ * {@link WORKFLOW_TOOL_DESCRIPTION} as the advanced alternative. It is embedded VERBATIM.
763
+ */
764
+ export declare const WORKFLOW_TOOL_NESTED_EXAMPLE: WorkflowDefinition;
765
+
766
+ /**
767
+ * The lean {@link import('@orkestrel/agent').ToolInterface.summary} {@link import('./factories.js').createWorkflowTool}
768
+ * advertises in place of {@link WORKFLOW_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
769
+ * (`@orkestrel/agent`) advertises `summary ?? description`, so this one-sentence text stands in
770
+ * for the full teaching description; the full text stays retrievable via
771
+ * {@link import('./factories.js').createDescribeTool}.
772
+ */
773
+ export declare const WORKFLOW_TOOL_SUMMARY = "Author and run a multi-phase workflow in one call \u2014 phases run in sequence, tasks within a phase run concurrently. Call describe('workflow') for the full authoring schema and examples.";
774
+
775
+ /**
776
+ * A draft workflow — a `WorkflowDefinition` (`@orkestrel/workflow`) with OPTIONAL `id` / `name`
777
+ * at all three levels (workflow / phase / task).
778
+ *
779
+ * @remarks
780
+ * The lenient authoring form {@link import('./factories.js').createWorkflowDraftContract}
781
+ * validates and {@link import('./helpers.js').completeDraft} completes into a strict
782
+ * `WorkflowDefinition`. `run` stays optional (a plain name string); the `bail` policy carries
783
+ * over.
784
+ */
785
+ export declare interface WorkflowDraft {
786
+ readonly id?: string;
787
+ readonly name?: string;
788
+ readonly description?: string;
789
+ readonly phases: readonly PhaseDraft[];
790
+ /** Failure policy: `false` (default) continues gracefully, `true` halts on the first failure. */
791
+ readonly bail?: boolean;
792
+ }
793
+
794
+ /**
795
+ * The shape of a DRAFT workflow — identical to a strict workflow shape EXCEPT `id` and `name`
796
+ * are OPTIONAL at all three levels (workflow / phase / task), so a small model can omit the six
797
+ * identity strings and let the tool synthesize them positionally.
798
+ *
799
+ * @remarks
800
+ * The lenient counterpart {@link import('./factories.js').createWorkflowDraftContract} compiles.
801
+ * `run` stays required on the strict form; a provided `id` / `name` still has `minLength: 1` (so
802
+ * an explicitly-empty `id: ''` is REJECTED, not auto-filled). After
803
+ * {@link import('./helpers.js').completeDraft} fills the missing ids/names, the result is
804
+ * validated against the STRICT `createWorkflowContract` (`@orkestrel/workflow`) gate before
805
+ * running.
806
+ */
807
+ export declare const workflowDraftShape: ObjectShape<{
808
+ id: OptionalShape<StringShape>;
809
+ name: OptionalShape<StringShape>;
810
+ description: OptionalShape<StringShape>;
811
+ phases: ArrayShape<ObjectShape<{
812
+ id: OptionalShape<StringShape>;
813
+ name: OptionalShape<StringShape>;
814
+ description: OptionalShape<StringShape>;
815
+ tasks: ArrayShape<ObjectShape<{
816
+ id: OptionalShape<StringShape>;
817
+ name: OptionalShape<StringShape>;
818
+ description: OptionalShape<StringShape>;
819
+ run: OptionalShape<StringShape>;
820
+ retries: OptionalShape<NumberShape>;
821
+ timeout: OptionalShape<NumberShape>;
822
+ }>>;
823
+ concurrency: OptionalShape<NumberShape>;
824
+ bail: OptionalShape<LiteralShape<readonly [true, false]>>;
825
+ }>>;
826
+ bail: OptionalShape<LiteralShape<readonly [true, false]>>;
827
+ }>;
828
+
829
+ /**
830
+ * One flat step — `{ name }` — the building block of a {@link WorkflowSteps} blob.
831
+ *
832
+ * @remarks
833
+ * `name` is the REGISTERED behavior name the step runs (it becomes the task's `run`, NOT a
834
+ * human label) — resolved against a workflow-level functions registry at construction.
835
+ */
836
+ export declare interface WorkflowStep {
837
+ /** The registered behavior name this step runs (becomes the task's `run`). */
838
+ readonly name: string;
839
+ }
840
+
841
+ /**
842
+ * The FLAT authoring blob {@link import('./factories.js').createWorkflowTool} advertises —
843
+ * `{ name?, steps }` — the simplest surface a small model can fill.
844
+ *
845
+ * @remarks
846
+ * Each {@link WorkflowStep} becomes a one-task phase, in order
847
+ * ({@link import('./helpers.js').expandSteps}); `name` is the optional workflow name (defaulted
848
+ * when omitted).
849
+ */
850
+ export declare interface WorkflowSteps {
851
+ readonly name?: string;
852
+ readonly steps: readonly WorkflowStep[];
853
+ }
854
+
855
+ /**
856
+ * The FLAT authoring shape {@link import('./factories.js').createWorkflowTool} advertises as its
857
+ * `parameters` — the simplest surface a small model can fill: `{ name?, steps: [{ name }] }`.
858
+ *
859
+ * @remarks
860
+ * A deliberately-reduced surface: a flat ordered list of steps, each a `{ name }`. The tool
861
+ * EXPANDS it ({@link import('./helpers.js').expandSteps}) into a full
862
+ * {@link import('./types.js').WorkflowDefinition} — one one-task phase per step, in order —
863
+ * then validates against the STRICT `createWorkflowContract` (`@orkestrel/workflow`) gate. The
864
+ * full nested form is STILL accepted by the tool (it branches on the args' shape) and is
865
+ * documented as the advanced escape-hatch in the tool's description — but THIS is what
866
+ * `parameters` advertises.
867
+ */
868
+ export declare const workflowStepsShape: ObjectShape<{
869
+ name: OptionalShape<StringShape>;
870
+ steps: ArrayShape<ObjectShape<{
871
+ name: StringShape;
872
+ }>>;
873
+ }>;
874
+
875
+ /**
876
+ * The ancestry identifier of a workflow in a run chain — `workflow:<id>`.
877
+ *
878
+ * @remarks
879
+ * Namespacing keeps a workflow id and an {@link agentTag} agent name in ONE set without
880
+ * collision, so re-entering a workflow OR an agent already in the chain is a single `includes`
881
+ * check.
882
+ *
883
+ * @param id - The workflow definition's `id`
884
+ * @returns The namespaced ancestry tag (`workflow:<id>`)
885
+ */
886
+ export declare function workflowTag(id: string): string;
887
+
888
+ /**
889
+ * Options for {@link import('./factories.js').createWorkflowTool} — the depth + ancestry a
890
+ * nested workflow run is bound at, plus the optional durable {@link WorkflowStoreInterface}
891
+ * (`@orkestrel/workflow`) this package layers on top of the ported handler logic.
892
+ *
893
+ * @remarks
894
+ * This is the PROPAGATION carrier across the agent/tool boundary. A `Tool`'s handler receives
895
+ * ONLY the model-supplied `args` (no ambient context, no signal — see `@orkestrel/agent`'s
896
+ * `ToolOptions`), so the run's position in the workflow→agent→workflow chain CANNOT be threaded
897
+ * through a tool call at runtime. Instead {@link import('./factories.js').createAgentFunction}
898
+ * CLOSES `depth` / `ancestry` over the tool at BIND time. Both are OPTIONAL: a workflow tool
899
+ * built for a TOP-LEVEL caller omits them — its nested run starts the chain at depth `1` with
900
+ * the bare `workflow:<id>` ancestry.
901
+ *
902
+ * `store` is this package's ADDITION: when supplied, the tool's handler persists the run's final
903
+ * snapshot (`store.set(result.workflow.snapshot())`) once the run settles, so a workflow
904
+ * authored + run through the tool is retrievable / restorable afterwards. Omitted ⇒ no
905
+ * persistence.
906
+ */
907
+ export declare interface WorkflowToolOptions {
908
+ /** The depth the INVOKING agent runs at; the nested workflow runs at `depth + 1`. Default `0`. */
909
+ readonly depth?: number;
910
+ /** The ancestry of the invoking run; the nested run extends it with its own `workflow:<id>`. Default empty. */
911
+ readonly ancestry?: readonly string[];
912
+ readonly store?: WorkflowStoreInterface;
913
+ }
914
+
915
+ /**
916
+ * Build the plain success summary {@link import('./factories.js').createWorkflowTool} returns on
917
+ * a completed run — the universal tool-handler contract (AGENTS §14): return a plain value on
918
+ * success, appearing identically over BOTH the agent loop and MCP.
919
+ *
920
+ * @remarks
921
+ * The summary is LEAN: the workflow's terminal `status` and the COUNT of settled task results —
922
+ * enough for a caller / model to react without serializing the whole live tree. (It carries no
923
+ * synthetic `id` / `name`: a tool handler has no call id; the `ToolManagerInterface`
924
+ * (`@orkestrel/agent`) supplies the canonical envelope's identity.)
925
+ *
926
+ * @param result - The terminal `WorkflowResult` (`@orkestrel/workflow`) the run produced
927
+ * @returns The plain success summary — `{ status, count }`
928
+ */
929
+ export declare function workflowToolSummary(result: WorkflowResult): Readonly<{
930
+ status: WorkflowStatus;
931
+ count: number;
932
+ }>;
933
+
934
+ export declare const WORKSPACE_TOOL_DESCRIPTION: string;
935
+
936
+ /**
937
+ * A valid `WorkspaceOperation` (`@orkestrel/agent`) object — the canonical example embedded
938
+ * VERBATIM in {@link WORKSPACE_TOOL_DESCRIPTION}.
939
+ *
940
+ * @remarks
941
+ * OWNED here now (ported from `@orkestrel/agent`). A `'write'` op (the most common authoring
942
+ * action): create or overwrite `notes.txt` with `hello`. Frozen so it cannot be mutated in
943
+ * place.
944
+ */
945
+ export declare const WORKSPACE_TOOL_EXAMPLE: WorkspaceOperation;
946
+
947
+ /**
948
+ * The name {@link import('./factories.js').createWorkspaceTool} advertises by default — the key a
949
+ * model calls and the `ToolManagerInterface` (`@orkestrel/agent`) registers under.
950
+ *
951
+ * @remarks
952
+ * OWNED here now (ported from `@orkestrel/agent`).
953
+ */
954
+ export declare const WORKSPACE_TOOL_NAME = "workspace";
955
+
956
+ /**
957
+ * The lean {@link import('@orkestrel/agent').ToolInterface.summary} {@link import('./factories.js').createWorkspaceTool}
958
+ * advertises in place of {@link WORKSPACE_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
959
+ * (`@orkestrel/agent`) advertises `summary ?? description`, so this one-sentence text stands in
960
+ * for the full teaching description; the full text stays retrievable via
961
+ * {@link import('./factories.js').createDescribeTool}.
962
+ */
963
+ export declare const WORKSPACE_TOOL_SUMMARY = "Read and edit files in a workspace \u2014 one operation per call (read, write, list, search, replace, splice, move, remove, plus workspace switching), chosen by the 'operation' field. Call describe('workspace') for the full operation list and fields.";
964
+
965
+ /**
966
+ * One operation an agent invokes through {@link import('./factories.js').createWorkspaceTool} — a
967
+ * FLAT, descriptive tagged union over the 13 workspace edit / read / navigation actions,
968
+ * discriminated by the `operation` literal (AGENTS §4.8: a discriminant is named for its axis —
969
+ * the action being performed — NEVER `kind`).
970
+ *
971
+ * @remarks
972
+ * This is the SOURCE OF TRUTH the tool contract is typed to
973
+ * ({@link import('./shapers.js').workspaceToolShape} compiles to a structurally-identical guard /
974
+ * parser / JSON Schema). Every field is FLAT (no nested objects) — the small-model ergonomic
975
+ * lever: a range edit is the four flat integers of the `'splice'` arm (`fromLine` /
976
+ * `fromColumn` / `toLine` / `toColumn`), reassembled into a 1-based `Range` (`@orkestrel/agent`)
977
+ * by `rangeOf`, never a nested `{ start, end }`. Each EDIT / READ arm maps onto exactly one
978
+ * `WorkspaceInterface` call against the manager's ACTIVE workspace; the two REGISTRY arms
979
+ * (`switch` / `workspaces`) drive the {@link WorkspaceManagerInterface} pointer instead —
980
+ * `workspaces` LISTS the workspaces the model can move between, and `switch` re-points which one
981
+ * the edit / read arms target.
982
+ */
983
+ export declare type WorkspaceOperation =
984
+ /** Read a whole text file's text by `path` from the ACTIVE workspace (a binary / absent path — or no active workspace — yields no content). */
985
+ {
986
+ readonly operation: 'read';
987
+ readonly path: string;
988
+ }
989
+ /** List every file in the ACTIVE workspace (path / state / size / lines / kind summaries); `[]` when no workspace is active. */
990
+ | {
991
+ readonly operation: 'list';
992
+ }
993
+ /** Whether a file exists at `path` in the ACTIVE workspace (`false` when no workspace is active). */
994
+ | {
995
+ readonly operation: 'has';
996
+ readonly path: string;
997
+ }
998
+ /**
999
+ * Scan every text file for `query`, returning each hit (path + 1-based line / column + the line).
1000
+ *
1001
+ * @remarks
1002
+ * `regex` treats `query` as a regular-expression source (default `false` — a literal substring);
1003
+ * `exact` matches case-sensitively (default `true`); `limit` caps the total hits returned.
1004
+ */
1005
+ | {
1006
+ readonly operation: 'search';
1007
+ readonly query: string;
1008
+ readonly regex?: boolean;
1009
+ readonly exact?: boolean;
1010
+ readonly limit?: number;
1011
+ }
1012
+ /**
1013
+ * Replace `query` with `replacement` across every text file, returning the tally.
1014
+ *
1015
+ * @remarks
1016
+ * Same matching axes as `search`: `regex` (default `false`), `exact` (default `true`), `limit`
1017
+ * (cap the total replacements).
1018
+ */
1019
+ | {
1020
+ readonly operation: 'replace';
1021
+ readonly query: string;
1022
+ readonly replacement: string;
1023
+ readonly regex?: boolean;
1024
+ readonly exact?: boolean;
1025
+ readonly limit?: number;
1026
+ }
1027
+ /** Write (create or overwrite) the whole file at `path` with `content`. */
1028
+ | {
1029
+ readonly operation: 'write';
1030
+ readonly path: string;
1031
+ readonly content: string;
1032
+ }
1033
+ /**
1034
+ * Splice `content` into an existing text file, replacing the 1-based range
1035
+ * `(fromLine, fromColumn)` (INCLUSIVE) → `(toLine, toColumn)` (EXCLUSIVE).
1036
+ *
1037
+ * @remarks
1038
+ * The FLAT range edit — the four positive-integer caret components reassemble into a `Range`
1039
+ * (`@orkestrel/agent`) via `rangeOf`. An empty span (`from === to`) inserts; a span past the
1040
+ * end is clamped. An inverted / sub-1 range throws `RANGE`; a binary target throws
1041
+ * `MODALITY`.
1042
+ */
1043
+ | {
1044
+ readonly operation: 'splice';
1045
+ readonly path: string;
1046
+ readonly content: string;
1047
+ readonly fromLine: number;
1048
+ readonly fromColumn: number;
1049
+ readonly toLine: number;
1050
+ readonly toColumn: number;
1051
+ }
1052
+ /** Prepend `content` to the start of the file at `path` (creating it when absent). */
1053
+ | {
1054
+ readonly operation: 'prepend';
1055
+ readonly path: string;
1056
+ readonly content: string;
1057
+ }
1058
+ /** Append `content` to the end of the file at `path` (creating it when absent). */
1059
+ | {
1060
+ readonly operation: 'append';
1061
+ readonly path: string;
1062
+ readonly content: string;
1063
+ }
1064
+ /** Re-key the file `from` → `to` (overwriting an occupied target). */
1065
+ | {
1066
+ readonly operation: 'move';
1067
+ readonly from: string;
1068
+ readonly to: string;
1069
+ }
1070
+ /** Remove the file at `path` from the workspace. */
1071
+ | {
1072
+ readonly operation: 'remove';
1073
+ readonly path: string;
1074
+ }
1075
+ /** List the workspaces the model can move between — each `{ id, files, active }` — so it can choose an `id` to `switch` to. */
1076
+ | {
1077
+ readonly operation: 'workspaces';
1078
+ }
1079
+ /** Re-point the manager's ACTIVE workspace to the one with `id` (an unknown `id` is a lenient no-op). The edit / read arms target the active workspace from then on. */
1080
+ | {
1081
+ readonly operation: 'switch';
1082
+ readonly id: string;
1083
+ };
1084
+
1085
+ /**
1086
+ * Options for {@link import('./factories.js').createWorkspaceTool} — EITHER a caller-built
1087
+ * {@link WorkspaceManagerInterface} to drive directly, OR a {@link WorkspaceStoreInterface} the
1088
+ * tool constructs a fresh manager over; neither given constructs a manager over
1089
+ * `@orkestrel/agent`'s in-memory store.
1090
+ *
1091
+ * @remarks
1092
+ * - `manager` — drive THIS manager directly (its `active` workspace is what every edit / read
1093
+ * operation targets). Takes priority over `store` when both are supplied.
1094
+ * - `store` — construct a manager over this durable {@link WorkspaceStoreInterface} (via
1095
+ * `@orkestrel/agent`'s `createWorkspaceManager`) — used only when `manager` is omitted.
1096
+ * The store only backs the manager's own `open` / `save` operations: the tool's edits are
1097
+ * NOT auto-persisted — durability requires an explicit caller `save` on the manager
1098
+ * (unlike the workflow tool's `store`, which persists each executed snapshot on settle).
1099
+ * - `name` / `description` — advertised tool overrides; default to
1100
+ * {@link import('./constants.js').WORKSPACE_TOOL_NAME} / {@link import('./constants.js').WORKSPACE_TOOL_DESCRIPTION}.
1101
+ */
1102
+ export declare interface WorkspaceToolOptions {
1103
+ readonly name?: string;
1104
+ readonly description?: string;
1105
+ readonly manager?: WorkspaceManagerInterface;
1106
+ readonly store?: WorkspaceStoreInterface;
1107
+ }
1108
+
1109
+ /**
1110
+ * The shape of a {@link import('./types.js').WorkspaceOperation} — a descriptive tagged union
1111
+ * over the 13 workspace edit / read / navigation operations, discriminated by the `operation`
1112
+ * literal (never a bare `kind`; AGENTS §4.4). Each variant leads with its `operation`
1113
+ * discriminant then its FLAT fields, every field via `stringShape` / `optionalShape` /
1114
+ * `integerShape({ min: 1 })` / `booleanShape`, each carrying a strong field-level `description`.
1115
+ *
1116
+ * @remarks
1117
+ * The union compiles to an `anyOf` JSON Schema + a `unionOf` guard + a first-match parser
1118
+ * automatically ({@link import('./factories.js').createWorkspaceTool} types the result to the
1119
+ * hand-written {@link import('./types.js').WorkspaceOperation}). `limit` and the four `'splice'`
1120
+ * caret components are POSITIVE integers (`integerShape({ min: 1 })`); `regex` / `exact` are
1121
+ * `optionalShape(booleanShape(...))`. The two REGISTRY arms — `workspaces` (list the workspaces
1122
+ * the model can move between) and `switch` (re-point the active one by `id`) — let a model
1123
+ * DISCOVER then CHOOSE which workspace the edit / read arms target.
1124
+ */
1125
+ export declare const workspaceToolShape: UnionShape<[ ObjectShape<{
1126
+ operation: LiteralShape<readonly ["read"]>;
1127
+ path: StringShape;
1128
+ }>, ObjectShape<{
1129
+ operation: LiteralShape<readonly ["list"]>;
1130
+ }>, ObjectShape<{
1131
+ operation: LiteralShape<readonly ["has"]>;
1132
+ path: StringShape;
1133
+ }>, ObjectShape<{
1134
+ operation: LiteralShape<readonly ["search"]>;
1135
+ query: StringShape;
1136
+ regex: OptionalShape<BooleanShape>;
1137
+ exact: OptionalShape<BooleanShape>;
1138
+ limit: OptionalShape<NumberShape>;
1139
+ }>, ObjectShape<{
1140
+ operation: LiteralShape<readonly ["replace"]>;
1141
+ query: StringShape;
1142
+ replacement: StringShape;
1143
+ regex: OptionalShape<BooleanShape>;
1144
+ exact: OptionalShape<BooleanShape>;
1145
+ limit: OptionalShape<NumberShape>;
1146
+ }>, ObjectShape<{
1147
+ operation: LiteralShape<readonly ["write"]>;
1148
+ path: StringShape;
1149
+ content: StringShape;
1150
+ }>, ObjectShape<{
1151
+ operation: LiteralShape<readonly ["splice"]>;
1152
+ path: StringShape;
1153
+ content: StringShape;
1154
+ fromLine: NumberShape;
1155
+ fromColumn: NumberShape;
1156
+ toLine: NumberShape;
1157
+ toColumn: NumberShape;
1158
+ }>, ObjectShape<{
1159
+ operation: LiteralShape<readonly ["prepend"]>;
1160
+ path: StringShape;
1161
+ content: StringShape;
1162
+ }>, ObjectShape<{
1163
+ operation: LiteralShape<readonly ["append"]>;
1164
+ path: StringShape;
1165
+ content: StringShape;
1166
+ }>, ObjectShape<{
1167
+ operation: LiteralShape<readonly ["move"]>;
1168
+ from: StringShape;
1169
+ to: StringShape;
1170
+ }>, ObjectShape<{
1171
+ operation: LiteralShape<readonly ["remove"]>;
1172
+ path: StringShape;
1173
+ }>, ObjectShape<{
1174
+ operation: LiteralShape<readonly ["workspaces"]>;
1175
+ }>, ObjectShape<{
1176
+ operation: LiteralShape<readonly ["switch"]>;
1177
+ id: StringShape;
1178
+ }>]>;
1179
+
1180
+ export { }