@orkestrel/toolbox 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,2651 @@
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 { ColumnSchema } from '@orkestrel/database';
6
+ import { Condition } from '@orkestrel/database';
7
+ import { Connector } from '@orkestrel/database';
8
+ import { ContractInterface } from '@orkestrel/contract';
9
+ import { ContractShape } from '@orkestrel/contract';
10
+ import { ConversationStoreInterface } from '@orkestrel/agent';
11
+ import { Criteria } from '@orkestrel/database';
12
+ import { DatabaseErrorCode } from '@orkestrel/database';
13
+ import { DatabaseInterface } from '@orkestrel/database';
14
+ import { Direction } from '@orkestrel/database';
15
+ import { DriverInterface } from '@orkestrel/database';
16
+ import { Include } from '@orkestrel/relation';
17
+ import { JSONShape } from '@orkestrel/contract';
18
+ import { KeyFunction } from '@orkestrel/database';
19
+ import { LiteralShape } from '@orkestrel/contract';
20
+ import { ModelInterface } from '@orkestrel/relation';
21
+ import { NumberShape } from '@orkestrel/contract';
22
+ import { ObjectShape } from '@orkestrel/contract';
23
+ import { OptionalShape } from '@orkestrel/contract';
24
+ import { PromptType } from '@orkestrel/terminal';
25
+ import { RelationErrorCode } from '@orkestrel/relation';
26
+ import { RelationManagerInterface } from '@orkestrel/relation';
27
+ import { StringShape } from '@orkestrel/contract';
28
+ import { TableInterface } from '@orkestrel/database';
29
+ import { TableSchema } from '@orkestrel/database';
30
+ import { TablesShape } from '@orkestrel/database';
31
+ import { TerminalManagerInterface } from '@orkestrel/terminal';
32
+ import { ToolInterface } from '@orkestrel/tool';
33
+ import { ToolManagerInterface } from '@orkestrel/tool';
34
+ import { UnionShape } from '@orkestrel/contract';
35
+ import { WorkflowDefinition } from '@orkestrel/workflow';
36
+ import { WorkflowFunction } from '@orkestrel/workflow';
37
+ import { WorkflowResult } from '@orkestrel/workflow';
38
+ import { WorkflowRunnerInterface } from '@orkestrel/workflow';
39
+ import { WorkflowStatus } from '@orkestrel/workflow';
40
+ import { WorkflowStoreInterface } from '@orkestrel/workflow';
41
+ import { WorkspaceManagerInterface } from '@orkestrel/agent';
42
+ import { WorkspaceStoreInterface } from '@orkestrel/agent';
43
+
44
+ /**
45
+ * The maximum nesting depth a delegation chain (agent tool → sub-agent → agent tool → …) may
46
+ * reach — the bound {@link import('./factories.js').createAgentTool}'s depth/cycle guard
47
+ * enforces.
48
+ *
49
+ * @remarks
50
+ * Deliberately a SEPARATE constant from {@link MAX_WORKFLOW_DEPTH} (rather than the two guards
51
+ * sharing one reference): the two guards bound DIFFERENT chains (workflow nesting vs. agent
52
+ * delegation) that happen to share a value today, and keeping this bound decoupled means a
53
+ * future change to one never silently shifts the other. Same numeric value by convention, not
54
+ * by shared reference.
55
+ */
56
+ export declare const AGENT_TOOL_DEPTH = 8;
57
+
58
+ export declare const AGENT_TOOL_DESCRIPTION: string;
59
+
60
+ /**
61
+ * The name {@link import('./factories.js').createAgentTool} advertises by default — the key a
62
+ * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
63
+ */
64
+ export declare const AGENT_TOOL_NAME = "agent";
65
+
66
+ /**
67
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createAgentTool}
68
+ * advertises in place of {@link AGENT_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
69
+ * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
70
+ * for the full teaching description; the full text stays retrievable via
71
+ * {@link import('./factories.js').createDescribeTool}.
72
+ */
73
+ 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.";
74
+
75
+ /**
76
+ * Options for {@link import('./factories.js').createAgentFunction} — the OPT-IN adapter that
77
+ * wraps a live `AgentInterface` (`@orkestrel/agent`) as a `WorkflowFunction`
78
+ * (`@orkestrel/workflow`), folding a nested workflow-authoring depth / cycle guard into its
79
+ * closure.
80
+ *
81
+ * @remarks
82
+ * All fields are optional: omitted entirely, the adapter runs the agent with no nested workflow
83
+ * tool bound and no depth/cycle bound (depth `0`, empty ancestry).
84
+ * - `runner` — when supplied, the adapter BINDS a depth/cycle-aware
85
+ * {@link import('./factories.js').createWorkflowTool} onto the agent's `context.tools` (the
86
+ * propagation seam), so the agent can author + run a NESTED workflow through it. Omitted ⇒ the
87
+ * agent runs with no workflow tool bound.
88
+ * - `depth` — this invocation's nesting depth (default `0`); the bound workflow tool runs its
89
+ * nested workflow at `depth + 1`, bounded by
90
+ * {@link import('./constants.js').MAX_WORKFLOW_DEPTH}.
91
+ * - `ancestry` — the workflow / agent identifiers already in this run chain (default empty); a
92
+ * cycle (this agent already present) is rejected with a typed `DEPTH` `WorkflowError`
93
+ * (`@orkestrel/workflow`).
94
+ */
95
+ export declare interface AgentFunctionOptions {
96
+ readonly runner?: WorkflowRunnerInterface;
97
+ readonly depth?: number;
98
+ readonly ancestry?: readonly string[];
99
+ }
100
+
101
+ /**
102
+ * The ancestry identifier of an agent in a run chain — `agent:<name>`.
103
+ *
104
+ * @remarks
105
+ * The agent counterpart of {@link workflowTag}: {@link import('./factories.js').createAgentFunction}
106
+ * / {@link import('./factories.js').createWorkflowTool} guard against re-entering an agent or
107
+ * workflow already in the chain (a typed `DEPTH` `WorkflowError`, `@orkestrel/workflow`). The
108
+ * `agent:` namespace keeps it distinct from a same-string workflow id.
109
+ *
110
+ * @param name - The agent's identifier / registry name
111
+ * @returns The namespaced ancestry tag (`agent:<name>`)
112
+ */
113
+ export declare function agentTag(name: string): string;
114
+
115
+ /**
116
+ * The FLAT args {@link import('./factories.js').createAgentTool} accepts — a delegated `task`
117
+ * plus the minimal optional `AgentJobInput` (`@orkestrel/agent`) fields a caller may override
118
+ * per-call.
119
+ *
120
+ * @remarks
121
+ * `task` becomes the seed user message in the sub-agent's rehydrated conversation
122
+ * (`AgentJobInput.messages`). `provider` / `tools` / `system` shadow the tool's own
123
+ * {@link AgentToolOptions} defaults for this ONE call when supplied.
124
+ */
125
+ export declare interface AgentToolArguments {
126
+ readonly task: string;
127
+ readonly provider?: string;
128
+ readonly tools?: readonly string[];
129
+ readonly system?: string;
130
+ }
131
+
132
+ /**
133
+ * Options for {@link import('./factories.js').createAgentTool} — the sub-agent delegation
134
+ * defaults, the nesting-depth / cycle guard bookkeeping, and the advertised tool overrides.
135
+ *
136
+ * @remarks
137
+ * - `name` / `description` — advertised tool overrides; default to
138
+ * {@link import('./constants.js').AGENT_TOOL_NAME} / {@link import('./constants.js').AGENT_TOOL_DESCRIPTION}.
139
+ * - `provider` — the DEFAULT registry provider key used when a call omits `provider`; a call
140
+ * that supplies its own `provider` overrides this. One of `provider` (here or per-call) MUST
141
+ * resolve, or the handler throws a typed `TOOL` {@link import('./errors.js').ToolboxError}.
142
+ * - `tools` — the DEFAULT registry tool-name list loaded into the delegated sub-agent; a
143
+ * per-call `tools` list overrides (never merges with) this default.
144
+ * - `system` — the DEFAULT system prompt seeding the sub-agent's context; a per-call `system`
145
+ * overrides this.
146
+ * - `depth` — this invocation's nesting depth (default `0`); a delegated sub-agent that itself
147
+ * calls this tool again runs at `depth + 1`, bounded by
148
+ * {@link import('./constants.js').AGENT_TOOL_DEPTH}.
149
+ * - `ancestry` — the sub-agent identifiers already in this delegation chain (default empty); a
150
+ * cycle (the resolved agent already present) is rejected with a typed `DEPTH`
151
+ * {@link import('./errors.js').ToolboxError}.
152
+ * - `store` — this package's ADDITION: when supplied, the handler persists the delegated
153
+ * sub-agent's active conversation snapshot (`store.set(agent.context.conversations.active.snapshot())`)
154
+ * once `agent.generate()` settles successfully, before returning — one snapshot per delegation
155
+ * (each `registry.build` mints a fresh conversation id, so a shared store accumulates an
156
+ * audit log rather than colliding). Omitted ⇒ no persistence from this tool.
157
+ *
158
+ * Conversation persistence for a delegated sub-agent has TWO independent seams, composable
159
+ * together: this `store` slot persists EACH delegation's conversation individually, and/or an
160
+ * `AgentRegistryInterface` built with `AgentRegistryOptions.store` (`@orkestrel/agent`) backs
161
+ * EVERY agent it builds — including ones built through this tool — with a store-backed
162
+ * `ConversationManagerInterface` of its own. Neither is required; either or both may be used.
163
+ */
164
+ export declare interface AgentToolOptions {
165
+ readonly name?: string;
166
+ readonly description?: string;
167
+ readonly provider?: string;
168
+ readonly tools?: readonly string[];
169
+ readonly system?: string;
170
+ readonly depth?: number;
171
+ readonly ancestry?: readonly string[];
172
+ readonly store?: ConversationStoreInterface;
173
+ }
174
+
175
+ /**
176
+ * The shape of {@link import('./types.js').AgentToolArguments} —
177
+ * {@link import('./factories.js').createAgentTool}'s advertised `parameters`.
178
+ *
179
+ * @remarks
180
+ * `task` is the only required field (a non-empty string); `provider` / `tools` / `system`
181
+ * are per-call overrides of the tool's own configured defaults.
182
+ */
183
+ export declare const agentToolShape: ObjectShape<{
184
+ task: StringShape;
185
+ provider: OptionalShape<StringShape>;
186
+ tools: OptionalShape<ArrayShape<StringShape>>;
187
+ system: OptionalShape<StringShape>;
188
+ }, false>;
189
+
190
+ export declare const ANSWER_TOOL_DESCRIPTION: string;
191
+
192
+ /**
193
+ * The name {@link import('./factories.js').createAnswerTool} advertises by default — the key a
194
+ * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
195
+ */
196
+ export declare const ANSWER_TOOL_NAME = "answer";
197
+
198
+ /**
199
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createAnswerTool}
200
+ * advertises in place of {@link ANSWER_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
201
+ * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
202
+ * for the full teaching description; the full text stays retrievable via
203
+ * {@link import('./factories.js').createDescribeTool}.
204
+ */
205
+ export declare const ANSWER_TOOL_SUMMARY = "List prompts addressed to this terminal, or answer one by id. Call describe('answer') for the required fields.";
206
+
207
+ /**
208
+ * Options for {@link import('./factories.js').createAnswerTool} — the live
209
+ * {@link TerminalManagerInterface} (`@orkestrel/terminal`) to list / answer prompts through, the
210
+ * terminal name `to`, and the advertised tool overrides.
211
+ *
212
+ * @remarks
213
+ * - `manager` — the terminal manager whose `pending(to)` / `answer(to, id, value)` the tool's
214
+ * handler calls — `pending` lists the prompts currently addressed to `to`, `answer` resolves
215
+ * one by `id`. A failed `answer` (`TerminalAnswerResult.error`) re-surfaces as a typed
216
+ * `ANSWER` {@link import('./errors.js').ToolboxError}.
217
+ * - `to` — the terminal identity this tool lists / answers prompts FOR.
218
+ * - `name` / `description` — advertised tool overrides; default to
219
+ * {@link import('./constants.js').ANSWER_TOOL_NAME} / {@link import('./constants.js').ANSWER_TOOL_DESCRIPTION}.
220
+ */
221
+ export declare interface AnswerToolOptions {
222
+ readonly manager: TerminalManagerInterface;
223
+ readonly to: string;
224
+ readonly name?: string;
225
+ readonly description?: string;
226
+ }
227
+
228
+ /**
229
+ * The shape of {@link import('./factories.js').createAnswerTool}'s call arguments — discriminated
230
+ * by `operation`: `'pending'` lists the prompts addressed to this tool's terminal, `'answer'`
231
+ * resolves one by `id` with a `value`.
232
+ *
233
+ * @remarks
234
+ * `value`'s type varies by the ORIGINAL prompt's form (`string` for `'input'` / `'password'` /
235
+ * `'select'` / `'editor'`, `boolean` for `'confirm'`, `readonly string[]` for `'checkbox'`) —
236
+ * `unionShape(stringShape(), booleanShape(), arrayShape(stringShape()))` expresses that
237
+ * union directly, so `value` is typed as the full `string | boolean | readonly string[]` union
238
+ * here (no lossy string-only fallback needed).
239
+ */
240
+ export declare const answerToolShape: UnionShape<readonly [ ObjectShape<{
241
+ operation: LiteralShape<readonly ["pending"]>;
242
+ }, false>, ObjectShape<{
243
+ operation: LiteralShape<readonly ["answer"]>;
244
+ id: StringShape;
245
+ value: UnionShape<readonly [ StringShape, BooleanShape, ArrayShape<StringShape>]>;
246
+ }, false>]>;
247
+
248
+ /**
249
+ * Clamp a `'records'` call's criteria to a row cap, and build the PROBE criteria the caller reads
250
+ * with — the pure leaf {@link import('./factories.js').createDatabaseTool}'s `'records'` operation
251
+ * uses to detect truncation without a separate `count` round trip.
252
+ *
253
+ * @remarks
254
+ * The effective limit is `min(criteria?.limit ?? cap, cap)`, floored at `0` (so a caller can never
255
+ * exceed the configured cap by supplying a larger `criteria.limit`). The returned probe criteria
256
+ * requests ONE MORE row than the effective limit (`limit: effective + 1`) — if storage returns
257
+ * that many, the caller knows the true result was truncated (`rows.length > effective`) and slices
258
+ * back down to `effective` before returning.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * import { clampCriteria } from '@src/core'
263
+ *
264
+ * const { criteria, limit } = clampCriteria(undefined, 100)
265
+ * // limit === 100, criteria.limit === 101 — a probe fetching one extra row
266
+ * const rows = await table.records(criteria)
267
+ * const truncated = rows.length > limit // true when storage had more than `limit` rows
268
+ * ```
269
+ *
270
+ * @param criteria - The live criteria to clamp (or `undefined`)
271
+ * @param cap - The row-count ceiling
272
+ * @returns The PROBE criteria (`limit` bumped by one) and the effective `limit`
273
+ */
274
+ export declare function clampCriteria(criteria: Criteria | undefined, cap: number): Readonly<{
275
+ criteria: Criteria;
276
+ limit: number;
277
+ }>;
278
+
279
+ /**
280
+ * Normalize an LLM-supplied answer `value` to the type {@link PromptType} `form` expects, so a
281
+ * caller that only ever emits strings can still answer a typed prompt.
282
+ *
283
+ * @remarks
284
+ * `'confirm'` coerces to a `boolean` — a `boolean` passes through, and the strings `'true'` /
285
+ * `'false'` (case-insensitively) map to it; any other string is truthy-coerced via
286
+ * `Boolean(value)`. `'checkbox'` coerces to `readonly string[]` — an array passes through
287
+ * (stringifying each entry), a comma-separated string splits + trims into one, and any other
288
+ * single (non-comma) string becomes a one-item array. Every other form (`'input'` / `'password'`
289
+ * / `'select'` / `'editor'`) coerces to a plain `string` — a string passes through verbatim; a
290
+ * non-string, non-object scalar (`number` / `boolean`) stringifies via `String(value)`; an
291
+ * object or array (no lossless string form) falls back to `''` rather than serializing garbage.
292
+ * Pure and total — never throws.
293
+ *
294
+ * @param form - The {@link PromptType} the answer is being coerced FOR
295
+ * @param value - The raw, LLM-supplied answer value
296
+ * @returns The coerced answer — `boolean` for `'confirm'`, `readonly string[]` for `'checkbox'`,
297
+ * `string` otherwise
298
+ */
299
+ export declare function coerceAnswer(form: PromptType, value: unknown): string | boolean | readonly string[];
300
+
301
+ /** One column's declared type — a primitive shorthand, or `integer` for a whole-number `number`. */
302
+ export declare type ColumnKind = 'string' | 'integer' | 'number' | 'boolean';
303
+
304
+ /** A {@link import('./types.js').ColumnKind} literal — the leaf {@link columnSpecShape} wraps. */
305
+ export declare const columnKindShape: LiteralShape<readonly ["string", "integer", "number", "boolean"]>;
306
+
307
+ /** Map a column NAME + its live `@orkestrel/database` `ContractShape` to a {@link ColumnSchema} — the leaf {@link tableSchema} maps over. */
308
+ export declare function columnSchema(name: string, shape: ContractShape): ColumnSchema;
309
+
310
+ /** Compile one {@link ColumnSpec} into its `@orkestrel/database` column shape — the per-column leaf {@link expandTables} maps over. */
311
+ export declare function columnShape(spec: ColumnSpec): ContractShape;
312
+
313
+ /**
314
+ * One table column's spec — either a bare {@link ColumnKind} shorthand, or `{ type, optional }`
315
+ * when the column may be absent from a row.
316
+ */
317
+ export declare type ColumnSpec = ColumnKind | Readonly<{
318
+ type: ColumnKind;
319
+ optional?: boolean;
320
+ }>;
321
+
322
+ /** A {@link import('./types.js').ColumnSpec} — a bare {@link columnKindShape}, or `{ type, optional }`. */
323
+ export declare const columnSpecShape: UnionShape<readonly [ LiteralShape<readonly ["string", "integer", "number", "boolean"]>, ObjectShape<{
324
+ type: LiteralShape<readonly ["string", "integer", "number", "boolean"]>;
325
+ optional: OptionalShape<BooleanShape>;
326
+ }, false>]>;
327
+
328
+ /**
329
+ * Complete a {@link WorkflowDraft} into a strict {@link WorkflowDefinition} — synthesize any
330
+ * MISSING `id` deterministically + positionally, and default any MISSING `name` to its
331
+ * (now-resolved) `id`.
332
+ *
333
+ * @remarks
334
+ * The positional id scheme is stable and human-legible: the workflow is `wf`, phase `i` is
335
+ * `phase-<i>`, and task `j` of that phase is `<phaseId>-task-<j>` (so a provided phase id flows
336
+ * into its tasks' synthesized ids). A PROVIDED `id` / `name` at any level is kept VERBATIM —
337
+ * synthesis touches only the omitted ones. A missing `name` defaults to the resolved `id` (never
338
+ * the other way round), so the result always has both. `run`, `description`, the per-phase
339
+ * `concurrency` / `bail`, the per-task `retries` / `timeout`, and the workflow `bail` carry over
340
+ * unchanged. The result is a complete {@link WorkflowDefinition}; the caller still validates it
341
+ * against the STRICT contract.
342
+ *
343
+ * @param draft - The draft workflow (id/name optional at all three levels)
344
+ * @returns A complete {@link WorkflowDefinition} with every id/name filled
345
+ */
346
+ export declare function completeDraft(draft: WorkflowDraft): WorkflowDefinition;
347
+
348
+ /**
349
+ * Complete one {@link PhaseDraft} into a strict phase definition — the per-phase step of
350
+ * {@link completeDraft} (phase `index` → `phase-<index>` when its id is omitted).
351
+ *
352
+ * @param phase - The draft phase
353
+ * @param index - The phase's positional index in the workflow
354
+ * @returns A complete phase definition
355
+ */
356
+ export declare function completePhaseDraft(phase: PhaseDraft, index: number): WorkflowDefinition['phases'][number];
357
+
358
+ /**
359
+ * Complete one {@link TaskDraft} into a strict task definition — the per-task leaf step of
360
+ * {@link completeDraft} (task `index` of phase `<phaseId>` → `<phaseId>-task-<index>` when its id
361
+ * is omitted).
362
+ *
363
+ * @param task - The draft task
364
+ * @param phaseId - The (resolved) parent phase id, so the synthesized task id nests under it
365
+ * @param index - The task's positional index within its phase
366
+ * @returns A complete task definition
367
+ */
368
+ export declare function completeTaskDraft(task: TaskDraft, phaseId: string, index: number): WorkflowDefinition['phases'][number]['tasks'][number];
369
+
370
+ /** One SERIALIZED WHERE condition — `values` is ALWAYS an array, even for a single-value operator. */
371
+ export declare const conditionShape: ObjectShape<{
372
+ column: StringShape;
373
+ operator: LiteralShape<readonly ["equals", "not", "above", "below", "from", "to", "between", "like", "glob", "starts", "ends", "any", "none", "absent", "present"]>;
374
+ values: ArrayShape<JSONShape>;
375
+ connector: OptionalShape<LiteralShape<readonly ["and", "or"]>>;
376
+ }, false>;
377
+
378
+ /**
379
+ * Wrap a live `AgentInterface` (`@orkestrel/agent`) as a {@link WorkflowFunction}
380
+ * (`@orkestrel/workflow`) — the OPT-IN adapter that runs the agent to a settled result, folding
381
+ * a nested workflow-authoring depth / cycle guard into its own closure.
382
+ *
383
+ * @remarks
384
+ * OWNED here now (ported from `@orkestrel/workflow`). Composes into a caller's
385
+ * `WorkflowOptions.functions` registry like any other behavior; the pure workflow runner has no
386
+ * knowledge of agents itself. Before running the agent, the depth/cycle guard REJECTS the call
387
+ * (a THROWN typed `DEPTH` `WorkflowError`, which the leaf `fail`s) when running it would push a
388
+ * nested chain past {@link import('./constants.js').MAX_WORKFLOW_DEPTH}, OR when this agent is
389
+ * already an ancestor (a cycle). When {@link import('./types.js').AgentFunctionOptions.runner}
390
+ * is supplied, the adapter BINDS a depth/cycle-aware {@link createWorkflowTool} onto the agent's
391
+ * `context.tools` (the propagation seam) — closed over `depth` and the extended ancestry (the
392
+ * tool itself computes `depth + 1` internally) — so the agent can author + run a NESTED workflow
393
+ * through it; the wrapped default is the CURRENT task's own workflow id (used only on a no-args
394
+ * tool call). The task's cancellation folds into the agent run: an already-aborted
395
+ * `controller.signal` cancels the agent up front; otherwise a one-shot listener fires
396
+ * `agent.abort(reason)` when the task cancels, removed in `finally`. `agent.generate()` resolves
397
+ * a partial `AgentResult` on a cancel (never rejects), returned as the task's completed value.
398
+ *
399
+ * A bound agent is effectively SINGLE-RUN: `context.tools.add` binds one `ToolInterface` under
400
+ * the fixed {@link import('./constants.js').WORKFLOW_TOOL_NAME}, and `agent.generate()` /
401
+ * `agent.abort()` are per-agent state. Two CONCURRENT tasks sharing the SAME `agent` instance
402
+ * race on that one tool binding (last-write-wins) and on generate/abort — give each concurrent
403
+ * task its OWN agent instance.
404
+ *
405
+ * @param agent - The live `AgentInterface` to run
406
+ * @param options - The nested-workflow binding + depth/cycle bookkeeping (see {@link import('./types.js').AgentFunctionOptions})
407
+ * @returns A {@link WorkflowFunction} that runs `agent` to its settled result
408
+ *
409
+ * @example
410
+ * ```ts
411
+ * import { createAgentFunction } from '@src/core'
412
+ * import { createWorkflowRunner } from '@orkestrel/workflow'
413
+ *
414
+ * const runner = createWorkflowRunner()
415
+ * const review = createAgentFunction(myAgent, { runner })
416
+ * await runner.execute(definition, { functions: { review } })
417
+ * ```
418
+ */
419
+ export declare function createAgentFunction(agent: AgentInterface, options?: AgentFunctionOptions): WorkflowFunction;
420
+
421
+ /**
422
+ * Build an LLM-callable sub-agent delegation tool — resolves a live, seeded `AgentInterface`
423
+ * from `registry` and runs it to completion for ONE delegated `task`.
424
+ *
425
+ * @remarks
426
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
427
+ * {@link import('./shapers.js').agentToolShape}, assembles an `AgentJobInput` (`task` seeds the
428
+ * sub-agent's conversation as a single `user` message; `provider` / `tools` / `system` fall
429
+ * back to the tool's own {@link import('./types.js').AgentToolOptions} defaults), rehydrates the sub-agent via
430
+ * `registry.build`, runs it with `agent.generate()`, and returns the settled
431
+ * `AgentResult.content` string (the sub-agent's final text). A missing / unresolvable `provider`, or a malformed call, THROWS a typed `TOOL`
432
+ * {@link import('./errors.js').ToolboxError}; a delegation that would exceed
433
+ * {@link import('./constants.js').AGENT_TOOL_DEPTH}, or re-enter an already-delegated agent (a
434
+ * cycle), THROWS a typed `DEPTH` {@link import('./errors.js').ToolboxError} — both isolated
435
+ * by the `ToolManagerInterface` into the canonical tool result's top-level `error`.
436
+ *
437
+ * `AgentInterface` (`@orkestrel/agent`) exposes no teardown method — a bound sub-agent's
438
+ * lifetime is the single `generate()` call this handler awaits; there is nothing to release
439
+ * afterwards (unlike a store-backed resource, its state lives entirely in the resolved
440
+ * `AgentContextInterface`, owned by the caller's registry).
441
+ *
442
+ * @param registry - The `AgentRegistryInterface` a delegated job resolves against (providers,
443
+ * tools, authorities, schedulers, and the `build` rehydration seam)
444
+ * @param options - Delegation defaults, depth/ancestry bookkeeping, and advertised overrides
445
+ * (see {@link import('./types.js').AgentToolOptions})
446
+ * @returns A `ToolInterface` (named {@link import('./constants.js').AGENT_TOOL_NAME} by default)
447
+ *
448
+ * @example
449
+ * ```ts
450
+ * import { createAgentTool } from '@src/core'
451
+ * import { createAgentRegistry } from '@orkestrel/agent'
452
+ * import { createToolManager } from '@orkestrel/tool'
453
+ *
454
+ * const registry = createAgentRegistry({ providers: { openai: myProvider } })
455
+ * const tool = createAgentTool(registry, { provider: 'openai' })
456
+ * const tools = createToolManager()
457
+ * tools.add(tool) // a model can now delegate a task to a sub-agent
458
+ * ```
459
+ */
460
+ export declare function createAgentTool(registry: AgentRegistryInterface, options?: AgentToolOptions): ToolInterface;
461
+
462
+ /**
463
+ * Build an LLM-callable answer tool — the ANSWER side of the terminal seam. Lists the prompts
464
+ * currently addressed to {@link import('./types.js').AnswerToolOptions.to}, or answers one of
465
+ * them by id.
466
+ *
467
+ * @remarks
468
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
469
+ * {@link import('./shapers.js').answerToolShape} (discriminated by `operation`). `'pending'`
470
+ * returns a compact list (`{ id, from, form, message }`) of every prompt currently addressed to
471
+ * `to` (`TerminalManagerInterface.pending`, `@orkestrel/terminal`). `'answer'` looks the prompt
472
+ * up by `id` (an unknown id throws a typed `ANSWER` {@link import('./errors.js').ToolboxError}),
473
+ * normalizes the model-supplied `value` to the prompt's own form
474
+ * ({@link import('./helpers.js').coerceAnswer}), and applies it via
475
+ * `TerminalManagerInterface.answer` — a rejected / unknown / unresolvable outcome
476
+ * (`TerminalAnswerResult.error`) re-surfaces as a typed `ANSWER` `ToolboxError`; success returns
477
+ * `{ answered: id }`. `to` is FIXED at construction
478
+ * ({@link import('./types.js').AnswerToolOptions.to}) — never read from the model-supplied args —
479
+ * so a model cannot spoof which terminal it is answering for. Concurrent answerers racing on one
480
+ * endpoint are FIRST-WRITE-WINS — a late answer to an already-settled prompt returns a typed
481
+ * `ANSWER` `ToolboxError` (surfaced as a 422 over HTTP).
482
+ *
483
+ * @param options - The live manager, the fixed `to` identity, and advertised overrides (see
484
+ * {@link import('./types.js').AnswerToolOptions})
485
+ * @returns A `ToolInterface` (named {@link import('./constants.js').ANSWER_TOOL_NAME} by default)
486
+ *
487
+ * @example
488
+ * ```ts
489
+ * import { createAnswerTool } from '@src/core'
490
+ * import { createToolManager } from '@orkestrel/tool'
491
+ * import { createTerminalManager } from '@orkestrel/terminal'
492
+ *
493
+ * const manager = createTerminalManager()
494
+ * manager.add('reviewer')
495
+ * const tool = createAnswerTool({ manager, to: 'reviewer' })
496
+ * const tools = createToolManager()
497
+ * tools.add(tool) // the reviewer terminal can now list/answer prompts addressed to it
498
+ * ```
499
+ */
500
+ export declare function createAnswerTool(options: AnswerToolOptions): ToolInterface;
501
+
502
+ /**
503
+ * Create a {@link DefinitionStoreInterface} backed by one table of the `@orkestrel/database`
504
+ * layer — the driver-pluggable twin of {@link createMemoryDefinitionStore}, storing each
505
+ * database's definition as one opaque JSON column.
506
+ *
507
+ * @param driver - The {@link DriverInterface} backing the table (default an in-memory driver)
508
+ * @returns A {@link DefinitionStoreInterface}
509
+ *
510
+ * @example
511
+ * ```ts
512
+ * import { createDatabaseDefinitionStore } from '@src/core'
513
+ *
514
+ * const store = createDatabaseDefinitionStore() // in-memory by default
515
+ * ```
516
+ */
517
+ export declare function createDatabaseDefinitionStore(driver?: DriverInterface): DefinitionStoreInterface;
518
+
519
+ /**
520
+ * Build an LLM-callable database tool — create, query, and mutate `@orkestrel/database`
521
+ * databases through one `operation`-discriminated call (AGENTS §14, matching
522
+ * {@link createWorkspaceTool}'s single-tool-many-operations shape).
523
+ *
524
+ * @remarks
525
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
526
+ * {@link import('./shapers.js').databaseToolShape}, dispatches to the matching operation, and
527
+ * RETURNS a plain result on success. A database is resolved lazily and cached for the tool's
528
+ * lifetime — `'create'` mints one from `tables` ({@link import('./helpers.js').expandTables}) and
529
+ * a registered `driver` key ({@link import('./types.js').DatabaseToolOptions.drivers}, default
530
+ * `{ memory: () => createMemoryDriver() }`); any other operation addressing an uncached id falls
531
+ * back to {@link import('./types.js').DatabaseToolOptions.store} (an unknown id throws a typed
532
+ * `TOOL` {@link import('./errors.js').ToolboxError}). When a `store` is configured, `'create'`
533
+ * persists the new {@link import('./types.js').DatabaseDefinition} and `'destroy'` deletes it.
534
+ *
535
+ * `'migrate'` re-declares a LIVE handle's tables via `DatabaseInterface.import` (the SAME driver
536
+ * and storage, a NEW typed view) and calls its `migrate` against the OLD deployed schema —
537
+ * derived from the handle's OWN `export()` (via {@link import('./helpers.js').tableSchema}), so it
538
+ * works for any handle, config-tracked or caller-supplied via
539
+ * {@link import('./types.js').DatabaseToolOptions.databases}. `'records'` clamps its `criteria` to
540
+ * {@link import('./types.js').DatabaseToolOptions.limit} (default
541
+ * {@link import('./constants.js').DATABASE_TOOL_LIMIT}) via
542
+ * {@link import('./helpers.js').clampCriteria}, reporting `truncated` when storage held more rows
543
+ * than the cap. Every operation's `criteria` is normalized via
544
+ * {@link import('./helpers.js').criteriaOf} (defaults an omitted condition `connector` to `'and'`).
545
+ * When {@link import('./types.js').DatabaseToolOptions.readonly} is `true`, every mutating
546
+ * operation throws a typed `TOOL` `ToolboxError` before doing anything. When
547
+ * {@link import('./types.js').DatabaseToolOptions.timeout} is set, every `@orkestrel/database` call
548
+ * this tool makes is given a fresh `AbortSignal.timeout(timeout)`. A typed `@orkestrel/database`
549
+ * failure (`DatabaseError`) re-surfaces as a typed `DATABASE` `ToolboxError` carrying the
550
+ * original {@link import('@orkestrel/database').DatabaseErrorCode} in `context.code`
551
+ * ({@link import('./helpers.js').databaseToolCode}); an `ToolboxError` thrown by this tool's own
552
+ * guards passes through unwrapped.
553
+ *
554
+ * A lazily re-minted database over the DEFAULT in-memory driver yields an EMPTY database — only
555
+ * the {@link import('./types.js').DatabaseDefinition} schema persists in `store`, never rows;
556
+ * durable rows need a persistent driver factory registered in
557
+ * {@link import('./types.js').DatabaseToolOptions.drivers}. `'destroy'` closes whatever handle is
558
+ * cached for the id, including an embedder-supplied
559
+ * {@link import('./types.js').DatabaseToolOptions.databases} handle — the embedder relinquishes
560
+ * that handle's lifecycle to this tool for any id it wires in. This tool assumes the
561
+ * single-writer, non-reentrant model `@orkestrel/database` itself assumes — concurrent calls
562
+ * against one id are NOT serialized by this tool. `'get'` is uncapped by
563
+ * {@link import('./types.js').DatabaseToolOptions.limit} (bounded only by the caller's `key` array
564
+ * size), unlike `'records'` / `'find'` / `'links'`.
565
+ *
566
+ * @param options - The tool's configuration (see {@link import('./types.js').DatabaseToolOptions})
567
+ * @returns A `ToolInterface` (named {@link import('./constants.js').DATABASE_TOOL_NAME} by default)
568
+ *
569
+ * @example
570
+ * ```ts
571
+ * import { createDatabaseTool } from '@src/core'
572
+ *
573
+ * const tool = createDatabaseTool()
574
+ * await tool.execute({
575
+ * operation: 'create',
576
+ * id: 'shop',
577
+ * tables: { products: { columns: { name: 'string', price: 'number' } } },
578
+ * })
579
+ * ```
580
+ */
581
+ export declare function createDatabaseTool(options?: DatabaseToolOptions): ToolInterface;
582
+
583
+ /**
584
+ * Build an LLM-callable tool that returns the FULL `description` of another registered tool by
585
+ * name — the counterpart to the lean `summary` the other tools in this package advertise
586
+ * (`AGENT_TOOL_SUMMARY` / `WORKFLOW_TOOL_SUMMARY` / `WORKSPACE_TOOL_SUMMARY`).
587
+ *
588
+ * @remarks
589
+ * `ToolManagerInterface.definitions()` (`@orkestrel/tool`) advertises `tool.summary ??
590
+ * tool.description` — a lean one-sentence summary stands in for a tool's full teaching
591
+ * description when `summary` is set, keeping the advertised tool list compact for a small model.
592
+ * This tool is the on-demand expansion seam: given a registered tool's `name`, it looks the tool
593
+ * up via `tools.tool(name)` and returns its full `description` (falling back to `summary` when a
594
+ * tool has no `description` of its own, then a placeholder when it has neither).
595
+ *
596
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
597
+ * {@link import('./shapers.js').describeToolShape}, RETURNS the plain description string on
598
+ * success, THROWS a typed `TOOL` {@link import('./errors.js').ToolboxError} on a malformed call
599
+ * or an unknown tool name.
600
+ *
601
+ * @param tools - The `ToolManagerInterface` (`@orkestrel/tool`) whose registered tools this
602
+ * tool can describe
603
+ * @returns A `ToolInterface` (named {@link import('./constants.js').DESCRIBE_TOOL_NAME})
604
+ *
605
+ * @example
606
+ * ```ts
607
+ * import { createDescribeTool, createWorkflowTool } from '@src/core'
608
+ * import { createToolManager } from '@orkestrel/tool'
609
+ *
610
+ * const tools = createToolManager()
611
+ * tools.add(createWorkflowTool(definition, runner))
612
+ * tools.add(createDescribeTool(tools))
613
+ * const full = await tools.execute({ id: '1', name: 'describe', arguments: { name: 'workflow' } })
614
+ * full.value // the workflow tool's full teaching description
615
+ * ```
616
+ */
617
+ export declare function createDescribeTool(tools: ToolManagerInterface): ToolInterface;
618
+
619
+ /**
620
+ * Wrap one CONCRETE endpoint ({@link import('./types.js').EndpointDefinition}) as an LLM-callable
621
+ * `ToolInterface` — the endpoint half of the "existing API/DB → MCP tool" bridge (the other half,
622
+ * {@link createInferTool}, is a standalone inference utility).
623
+ *
624
+ * @remarks
625
+ * `parameters` is inferred ONCE at construction from `definition.samples` via
626
+ * `@orkestrel/contract`'s `samplesToSchema` (tuned by {@link import('./types.js').EndpointToolOptions}'s
627
+ * `format` / `enum`), wrapping a non-object root as `{ value: <schema> }` via `schemaToObject` —
628
+ * the SAME object-rooted schema is both the ADVERTISED `parameters` and, by default
629
+ * ({@link import('./types.js').EndpointToolOptions.validate} `true`), the ENFORCED contract:
630
+ * `@orkestrel/contract` 0.0.7's `schemaToShape` compiles it ONCE (via `createContract`) into a
631
+ * `ContractInterface` whose `.parse` runs on every call's `args` before `definition.invoke` — a
632
+ * NORMALIZING parse, not a strict type check: a scalar is COERCED to its inferred type where the
633
+ * house parsers coerce (a number to/from a numeric string, a boolean from `'1'`/`'0'`/`'true'`/
634
+ * `'false'`/`1`/`0`), so `definition.invoke` receives the COERCED value (e.g. `7` sent for a
635
+ * string slot arrives as `'7'`), not the raw call value. A call whose `args` fails to parse into
636
+ * a record — a required key missing, or a value not coercible to its slot's type — THROWS a
637
+ * typed `TOOL` {@link import('./errors.js').ToolboxError} carrying the compiled contract's
638
+ * structured `explain` faults, and `definition.invoke` is never called. `format` annotations are
639
+ * NEVER asserted, and a key outside the closed inferred schema is SILENTLY DROPPED rather than
640
+ * rejected (see {@link import('./types.js').EndpointToolOptions.validate}). With
641
+ * `validate: false`, `execute` PASSES THROUGH the model-supplied `args` to `definition.invoke`
642
+ * WITHOUT re-validation — the pre-0.0.7 behavior, preserved as an explicit opt-out. Either way,
643
+ * `invoke`'s return flows back as the tool call's plain result; a throw PROPAGATES uncaught,
644
+ * isolated by the `ToolManagerInterface` (`@orkestrel/tool`) into the canonical error envelope
645
+ * (AGENTS §14) — never caught or re-wrapped here.
646
+ *
647
+ * @param definition - The endpoint's identity, non-empty samples, and local handler (see
648
+ * {@link import('./types.js').EndpointDefinition})
649
+ * @param options - Construction-time inference tuning + the validate opt-out (see
650
+ * {@link import('./types.js').EndpointToolOptions})
651
+ * @returns A `ToolInterface` named `definition.name`
652
+ *
653
+ * @example
654
+ * ```ts
655
+ * import { createEndpointTool } from '@src/core'
656
+ * import { createToolManager } from '@orkestrel/tool'
657
+ *
658
+ * const tool = createEndpointTool({
659
+ * name: 'lookupUser',
660
+ * description: 'Look up a user by id.',
661
+ * samples: [{ id: '1', name: 'Ada' }, { id: '2', name: 'Bob' }],
662
+ * invoke: (args) => ({ id: args.id, name: 'Ada' }),
663
+ * })
664
+ * const tools = createToolManager()
665
+ * tools.add(tool)
666
+ *
667
+ * // conforming args (all required keys present) parse and reach `invoke`
668
+ * const result = await tools.execute({
669
+ * id: 'call-1',
670
+ * name: 'lookupUser',
671
+ * arguments: { id: '1', name: 'Ada' },
672
+ * })
673
+ * // result.value -> { id: '1', name: 'Ada' }
674
+ *
675
+ * // a nonconforming call (id is not coercible to the required string) is rejected before
676
+ * // `invoke` runs
677
+ * const rejected = await tools.execute({
678
+ * id: 'call-2',
679
+ * name: 'lookupUser',
680
+ * arguments: { id: true, name: 'Ada' },
681
+ * })
682
+ * // rejected.error -> the TOOL ToolboxError message
683
+ * ```
684
+ */
685
+ export declare function createEndpointTool(definition: EndpointDefinition, options?: EndpointToolOptions): ToolInterface;
686
+
687
+ /**
688
+ * Build a standalone LLM-callable tool that infers a JSON Schema from example values — the
689
+ * utility half of the "existing API/DB → MCP tool" bridge (the other half,
690
+ * {@link createEndpointTool}, wraps one CONCRETE endpoint).
691
+ *
692
+ * @remarks
693
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
694
+ * {@link import('./shapers.js').inferToolShape} (`samples` non-empty, `format` / `enum` optional
695
+ * booleans, `candidates` an optional array), infers a schema via `@orkestrel/contract`'s
696
+ * `samplesToSchema`, wraps a non-object root as `{ value: <schema> }` via `schemaToObject` (mirrors
697
+ * the tool-parameters convention every other `create*Tool` factory advertises), and RETURNS the
698
+ * resulting parameters record. An empty `samples` array fails `inferToolShape`'s `min: 1` bound —
699
+ * `contract.parse` returns `undefined` and the handler throws a typed `TOOL`
700
+ * {@link import('./errors.js').ToolboxError}.
701
+ *
702
+ * When `candidates` is ABSENT, the return is the bare parameters record — unchanged from before
703
+ * this array existed. When `candidates` is PRESENT (any array, including empty), the handler
704
+ * compiles a SEPARATE per-call contract from the RAW inferred schema (via `@orkestrel/contract`'s
705
+ * `schemaToShape`, NOT the `schemaToObject`-wrapped parameters — a bare-value sample checks a
706
+ * bare-value candidate) and returns `{ parameters, checks }`, one check per candidate at the same
707
+ * index. Every entry has a UNIFORM shape — `{ index, valid, coercible }`, with `faults` added ONLY
708
+ * when `valid` is `false`: `valid` is the STRICT guard verdict (`checker.is(candidate)`), the
709
+ * OPPOSITE of {@link createEndpointTool}'s enforcement, which coerces (`7` becomes `'7'` for a
710
+ * string slot) — here a conformance report answers "does this value conform AS-IS": `7` against a
711
+ * string slot is `valid: false`, full stop. `coercible` answers a SEPARATE question — "would the
712
+ * NORMALIZING parse accept this value", i.e. would {@link createEndpointTool}'s default enforcement
713
+ * admit it (`checker.parse(candidate) !== undefined`) — computed for every candidate regardless of
714
+ * `valid`; by the house parse/guard round-trip guarantee (AGENTS §14), a `valid: true` entry is
715
+ * ALWAYS also `coercible: true`. `@orkestrel/contract` 0.0.7's `explain` mirrors the normalizing
716
+ * `parse`'s leniency, not `is`'s strictness — so a strictly-invalid but coercible candidate (`7`
717
+ * against a string slot) yields `{ valid: false, coercible: true, faults: [] }`: EMPTY faults, since
718
+ * the mismatch the normalizing parse would silently fix is not one `explain` reports. `faults`
719
+ * therefore only ever populates for a NON-coercible mismatch — a wrong type the parse can't coerce
720
+ * (a boolean in a string slot), a missing required key, or an out-of-enum value — where
721
+ * `coercible: false`. `checker.is` / `.parse` / `.explain` are all total over JSON-safe input — a
722
+ * JSON-safe hostile candidate (a `__proto__`-carrying object, deeply nested data) reaches all three
723
+ * and yields a bounded, non-throwing per-candidate verdict; a NON-JSON-safe candidate (e.g. a
724
+ * throwing-getter `Proxy`) never reaches the checker at all — it fails the OUTER `args` parse
725
+ * against {@link import('./shapers.js').inferToolShape} and rejects the WHOLE call with the same
726
+ * `TOOL` {@link import('./errors.js').ToolboxError} a malformed `samples`/`format`/`enum` throws,
727
+ * with no per-candidate verdict produced.
728
+ *
729
+ * @param options - Advertised `name` / `description` overrides (see
730
+ * {@link import('./types.js').InferToolOptions})
731
+ * @returns A `ToolInterface` (named {@link import('./constants.js').INFER_TOOL_NAME} by default)
732
+ *
733
+ * @example
734
+ * ```ts
735
+ * import { createInferTool } from '@src/core'
736
+ * import { createToolManager } from '@orkestrel/tool'
737
+ *
738
+ * const tool = createInferTool()
739
+ * const tools = createToolManager()
740
+ * tools.add(tool)
741
+ *
742
+ * const result = await tools.execute({
743
+ * id: 'call-1',
744
+ * name: 'infer',
745
+ * arguments: { samples: [{ id: 1, name: 'Ada' }, { id: 2, name: 'Bob' }] },
746
+ * })
747
+ * // result.value -> { type: 'object', properties: { id: {...}, name: {...} }, ... }
748
+ *
749
+ * // with candidates, the result is wrapped with per-candidate verdicts
750
+ * const checked = await tools.execute({
751
+ * id: 'call-2',
752
+ * name: 'infer',
753
+ * arguments: {
754
+ * samples: [{ id: 1, name: 'Ada' }],
755
+ * candidates: [{ id: 2, name: 'Bob' }, { id: 'x', name: 'Cy' }],
756
+ * },
757
+ * })
758
+ * // checked.value -> { parameters: {...}, checks: [
759
+ * // { index: 0, valid: true, coercible: true },
760
+ * // { index: 1, valid: false, coercible: false, faults: [...] },
761
+ * // ] }
762
+ * ```
763
+ */
764
+ export declare function createInferTool(options?: InferToolOptions): ToolInterface;
765
+
766
+ /**
767
+ * Create the in-memory {@link DefinitionStoreInterface} — a process-lifetime `Map` of database
768
+ * definitions, the DEFAULT store the upcoming database / relation tools will persist their
769
+ * `DatabaseDefinition` configs through.
770
+ *
771
+ * @returns A {@link DefinitionStoreInterface}
772
+ *
773
+ * @example
774
+ * ```ts
775
+ * import { createMemoryDefinitionStore } from '@src/core'
776
+ *
777
+ * const store = createMemoryDefinitionStore()
778
+ * ```
779
+ */
780
+ export declare function createMemoryDefinitionStore(): DefinitionStoreInterface;
781
+
782
+ /**
783
+ * Build an LLM-callable prompt tool — the ASK side of the terminal seam. Asks
784
+ * {@link import('./types.js').PromptToolOptions.to} a question and BLOCKS until it answers,
785
+ * returning the resolved answer value.
786
+ *
787
+ * @remarks
788
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
789
+ * {@link import('./shapers.js').promptToolShape}, dispatches to the matching
790
+ * `TerminalManagerInterface.ask` overload (`@orkestrel/terminal`) for the call's `form`, and
791
+ * RETURNS the resolved answer on success. `from` is FIXED at construction
792
+ * ({@link import('./types.js').PromptToolOptions.from}) — never read from the model-supplied
793
+ * args — so a model cannot spoof which terminal is asking. A prompt CYCLE rejects with
794
+ * `TerminalError('DEADLOCK')`, re-surfaced as a typed `DEADLOCK`
795
+ * {@link import('./errors.js').ToolboxError}; an expired prompt re-surfaces as `EXPIRE`; an
796
+ * unknown `to` (or any other `TerminalError`) re-surfaces as `TOOL`, naming the unknown terminal
797
+ * plus the known ones (`manager.terminals()`).
798
+ *
799
+ * @param options - The live manager, the fixed `from` identity, and advertised overrides (see
800
+ * {@link import('./types.js').PromptToolOptions})
801
+ * @returns A `ToolInterface` (named {@link import('./constants.js').PROMPT_TOOL_NAME} by default)
802
+ *
803
+ * @example
804
+ * ```ts
805
+ * import { createPromptTool } from '@src/core'
806
+ * import { createToolManager } from '@orkestrel/tool'
807
+ * import { createTerminalManager } from '@orkestrel/terminal'
808
+ *
809
+ * const manager = createTerminalManager()
810
+ * manager.add('agent')
811
+ * manager.add('reviewer')
812
+ * const tool = createPromptTool({ manager, from: 'agent' })
813
+ * const tools = createToolManager()
814
+ * tools.add(tool) // the agent can now ask 'reviewer' and block for the answer
815
+ * ```
816
+ */
817
+ export declare function createPromptTool(options: PromptToolOptions): ToolInterface;
818
+
819
+ /**
820
+ * Build an LLM-callable relation tool — traverse and edit `@orkestrel/relation` relationships
821
+ * through one `operation`-discriminated call (AGENTS §14, matching {@link createDatabaseTool}'s
822
+ * single-tool-many-operations shape).
823
+ *
824
+ * @remarks
825
+ * The universal tool-handler contract (AGENTS §14): validates the call args against
826
+ * {@link import('./shapers.js').relationToolShape}, resolves the addressed
827
+ * {@link import('@orkestrel/relation').RelationManagerInterface} — an explicit `manager` field
828
+ * must match a key of {@link import('./types.js').RelationToolOptions.managers}, an OMITTED one
829
+ * resolves to the SOLE registered manager, either miss throwing a typed `TOOL`
830
+ * {@link import('./errors.js').ToolboxError}
831
+ * ({@link import('./helpers.js').relationManagerOf}) — then resolves `model` against it
832
+ * ({@link import('./helpers.js').relationModelOf}, same typed-`TOOL`-on-miss shape), and
833
+ * dispatches to the matched operation, RETURNING a plain result on success.
834
+ *
835
+ * `'load'` / `'find'` expand the call's FLAT dot-path `include` list into a live
836
+ * `@orkestrel/relation` `Include` tree via {@link import('./helpers.js').expandInclude}, capped
837
+ * at {@link import('./types.js').RelationToolOptions.depth} (default
838
+ * {@link import('./constants.js').RELATION_TOOL_DEPTH}) — a path exceeding the cap, or carrying an
839
+ * empty segment, throws a typed `TOOL` error. `'load'` dispatches on whether `key` is an array
840
+ * (positional many-key form, AGENTS §9.2) or a single key. `'find'` and `'links'` clamp their
841
+ * result to {@link import('./types.js').RelationToolOptions.limit} (default
842
+ * {@link import('./constants.js').RELATION_TOOL_LIMIT}) — `'find'` probes one row past the
843
+ * effective limit (mirroring {@link import('./helpers.js').clampCriteria}'s idiom) to report
844
+ * `truncated`; `'links'` (which has no upstream pagination) fetches the FULL linked-key list and
845
+ * slices/truncates it the same way. `'link'` / `'unlink'` write / remove one `through` junction
846
+ * row.
847
+ *
848
+ * A typed `@orkestrel/relation` failure (`RelationError`) re-surfaces as a typed `RELATION`
849
+ * `ToolboxError` carrying the original {@link import('@orkestrel/relation').RelationErrorCode}
850
+ * in `context.code`; a typed `@orkestrel/database` failure underneath it (`DatabaseError`)
851
+ * re-surfaces as a typed `DATABASE` `ToolboxError`, mirroring {@link createDatabaseTool}'s error
852
+ * mapping; an `ToolboxError` thrown by this tool's own guards (malformed args, an unknown
853
+ * manager/model) passes through unwrapped.
854
+ *
855
+ * @param options - The tool's configuration (see {@link import('./types.js').RelationToolOptions})
856
+ * @returns A `ToolInterface` (named {@link import('./constants.js').RELATION_TOOL_NAME} by default)
857
+ *
858
+ * @example
859
+ * ```ts
860
+ * import { createRelationTool } from '@src/core'
861
+ *
862
+ * const tool = createRelationTool({ managers: { shop: manager } })
863
+ * await tool.execute({ operation: 'load', model: 'accounts', key: 'acc1', include: ['contacts'] })
864
+ * ```
865
+ */
866
+ export declare function createRelationTool(options: RelationToolOptions): ToolInterface;
867
+
868
+ /**
869
+ * Wrap a registered tool as a {@link WorkflowFunction} (`@orkestrel/workflow`) — the OPT-IN
870
+ * adapter that lets a `function`-form task run a `@orkestrel/tool` tool BY NAME.
871
+ *
872
+ * @remarks
873
+ * OWNED here now (ported from `@orkestrel/workflow`). Composes into a caller's
874
+ * `WorkflowOptions.functions` registry like any other behavior
875
+ * (`{ publish: createToolFunction(tools, 'publish') }`); the pure workflow runner has no
876
+ * knowledge of tools itself. The returned function executes `name` against `tools` with the
877
+ * task's `controller.input` as the call arguments, id-correlated to the task's own id. A
878
+ * `ToolManagerInterface.execute` (`@orkestrel/tool`) NEVER throws (a handler throw is isolated
879
+ * into `result.error`), so a failing tool is surfaced here as a THROWN `Error` carrying the
880
+ * original message as `cause` — the leaf `fail`s, honouring `bail`. An UNREGISTERED tool name is
881
+ * a programmer error (an explicit binding to a name that doesn't exist) — unlike the engine's
882
+ * own silent auto-complete of an unresolved task handler, this THROWS a typed `TOOL`
883
+ * `WorkflowError` (`@orkestrel/workflow`).
884
+ *
885
+ * @param tools - The `ToolManagerInterface` (`@orkestrel/tool`) the named tool is registered on
886
+ * @param name - The registered tool's name
887
+ * @returns A {@link WorkflowFunction} that runs the named tool
888
+ *
889
+ * @example
890
+ * ```ts
891
+ * import { createToolFunction } from '@src/core'
892
+ * import { createToolManager } from '@orkestrel/tool'
893
+ * import { createWorkflowRunner } from '@orkestrel/workflow'
894
+ *
895
+ * const tools = createToolManager()
896
+ * tools.add(myPublishTool)
897
+ * const runner = createWorkflowRunner()
898
+ * await runner.execute(definition, { functions: { publish: createToolFunction(tools, 'publish') } })
899
+ * ```
900
+ */
901
+ export declare function createToolFunction(tools: ToolManagerInterface, name: string): WorkflowFunction;
902
+
903
+ /**
904
+ * Compile the LENIENT workflow DRAFT contract — identical to `createWorkflowContract`
905
+ * (`@orkestrel/workflow`) EXCEPT `id` and `name` are OPTIONAL at all three levels (workflow /
906
+ * phase / task), so a small model can omit the six identity strings.
907
+ *
908
+ * @remarks
909
+ * The widened authoring surface {@link createWorkflowTool} parses an authored blob through
910
+ * before {@link import('./helpers.js').completeDraft} fills the missing ids/names. It does NOT
911
+ * relax the canonical contract — `createWorkflowContract` (`@orkestrel/workflow`) stays
912
+ * byte-for-byte unchanged and STRICT, and the completed draft is re-validated against THAT
913
+ * strict gate before running (soundness preserved). A PROVIDED `id` / `name` still carries
914
+ * `minLength: 1`, so an explicitly-empty `id: ''` is REJECTED (parses to `undefined`), never
915
+ * auto-filled — keeping "garbage" distinct from "omitted". `run` stays optional (a plain name
916
+ * string).
917
+ *
918
+ * @returns The compiled {@link import('./types.js').WorkflowDraft} contract
919
+ *
920
+ * @example
921
+ * ```ts
922
+ * import { createWorkflowDraftContract, completeDraft } from '@src/core'
923
+ *
924
+ * const draft = createWorkflowDraftContract()
925
+ * const parsed = draft.parse({ phases: [{ tasks: [{ run: 'compile' }] }] })
926
+ * const definition = parsed && completeDraft(parsed) // ids/names filled positionally
927
+ * draft.parse({ id: '', phases: [] }) // undefined — an explicit empty id is rejected
928
+ * ```
929
+ */
930
+ export declare function createWorkflowDraftContract(): ContractInterface<WorkflowDraft>;
931
+
932
+ /**
933
+ * Wrap a {@link WorkflowDefinition} as an LLM-callable tool — it ADVERTISES the SIMPLE flat
934
+ * authoring shape (`{ name?, steps: [{ name }] }`) as its `parameters` so even a small model can
935
+ * author a complete tree, and its handler EXPANDS / COMPLETES the authored blob, validates it
936
+ * against the STRICT contract, runs it through `runner`, and, when
937
+ * {@link import('./types.js').WorkflowToolOptions.store} is supplied, PERSISTS each executed
938
+ * workflow's final snapshot after the run settles.
939
+ *
940
+ * @remarks
941
+ * A plain `ToolManagerInterface`-compatible tool (`@orkestrel/tool`), reproducing
942
+ * `@orkestrel/workflow`'s former call contract exactly (flat / draft / full authoring forms, the
943
+ * strict soundness gate, the depth/cycle guard). It is ALSO the propagation carrier
944
+ * {@link createAgentFunction} binds onto a wrapped agent's `context.tools`: because a tool
945
+ * handler receives ONLY the model-supplied `args` (no ambient context, no signal), the run's
946
+ * depth + ancestry are CLOSED OVER at bind time via {@link import('./types.js').WorkflowToolOptions},
947
+ * and the handler enforces the SAME depth / cycle guard itself before running the nested
948
+ * workflow at `depth + 1` with the extended ancestry.
949
+ *
950
+ * **Widened authoring surface (additive — the canonical contract + runner stay STRICT and
951
+ * unchanged).** A 2B model reliably CALLS the tool but cannot reliably emit the full four-level
952
+ * nested {@link WorkflowDefinition} (six required `id`/`name` strings, an all-or-nothing tree).
953
+ * So the tool ACCEPTS three authoring forms and converges them on the SAME strict
954
+ * `createWorkflowContract` gate before running (soundness preserved):
955
+ * - the FLAT shape `{ name?, steps: [{ name }] }` — the ADVERTISED `parameters` (the simplest
956
+ * form, {@link import('./helpers.js').expandSteps}'d into one one-task phase per step);
957
+ * - a nested DRAFT with any `id`/`name` OMITTED — {@link createWorkflowDraftContract}-parsed then
958
+ * {@link import('./helpers.js').completeDraft}'d (missing ids synthesized positionally);
959
+ * - the full nested {@link WorkflowDefinition} — the advanced escape-hatch, accepted as the draft
960
+ * super-set.
961
+ *
962
+ * The universal tool-handler contract (AGENTS §14): returns the plain run summary
963
+ * (`{ status, count }`) on success, THROWS a typed `WorkflowError` (`@orkestrel/workflow`) on
964
+ * every failure path — malformed authored args (`TOOL`), or an over-deep / cyclic nested run
965
+ * (`DEPTH`). The `ToolManagerInterface` isolates every throw into the canonical tool result's
966
+ * top-level `error`, so nothing escapes the run. `options.depth` / `options.ancestry` are the
967
+ * propagation carrier across a workflow → agent → workflow chain; `options.store` is this
968
+ * package's ADDITION — the persisted snapshot is retrievable via the store afterwards (a caller
969
+ * restores it through `@orkestrel/workflow`'s own `Workflow.restore` / store-backed factories).
970
+ *
971
+ * @param definition - The workflow the tool runs when called with no authored args
972
+ * @param runner - The `WorkflowRunnerInterface` (`@orkestrel/workflow`) that executes the (nested) workflow
973
+ * @param options - Depth/ancestry bookkeeping plus the optional durable store (see {@link import('./types.js').WorkflowToolOptions})
974
+ * @returns A `ToolInterface` (named {@link import('./constants.js').WORKFLOW_TOOL_NAME}) whose
975
+ * `parameters` advertise the flat authoring schema
976
+ *
977
+ * @example
978
+ * ```ts
979
+ * import { createWorkflowTool } from '@src/core'
980
+ * import { createWorkflowRunner, createMemoryWorkflowStore } from '@orkestrel/workflow'
981
+ * import { createToolManager } from '@orkestrel/tool'
982
+ *
983
+ * const runner = createWorkflowRunner()
984
+ * const store = createMemoryWorkflowStore()
985
+ * const tool = createWorkflowTool(definition, runner, { store })
986
+ * const tools = createToolManager()
987
+ * tools.add(tool) // authored runs are now persisted to `store` on settle
988
+ * ```
989
+ */
990
+ export declare function createWorkflowTool(definition: WorkflowDefinition, runner: WorkflowRunnerInterface, options?: WorkflowToolOptions): ToolInterface;
991
+
992
+ /**
993
+ * Build an LLM-callable workspace-editing tool — it ADVERTISES the `operation`-discriminated
994
+ * 13-op union ({@link import('./shapers.js').workspaceToolShape}) as its `parameters`, and its
995
+ * handler PARSES the model-supplied args against that contract and DISPATCHES the matched
996
+ * operation against the manager's ACTIVE workspace (the registry ops drive the manager itself),
997
+ * returning the plain result (throwing a typed `WorkspaceError`, `@orkestrel/agent`, on
998
+ * failure). EITHER drives a caller-supplied {@link WorkspaceToolOptions.manager} directly, OR
999
+ * constructs a fresh `WorkspaceManagerInterface` (`@orkestrel/agent`) over
1000
+ * {@link import('./types.js').WorkspaceToolOptions.store} (via `@orkestrel/agent`'s
1001
+ * `createWorkspaceManager`); neither given constructs a manager backed by `@orkestrel/agent`'s
1002
+ * in-memory store default.
1003
+ *
1004
+ * @remarks
1005
+ * MANAGER-DRIVEN: every edit / read op (read / list / has / search / replace / write / splice /
1006
+ * prepend / append / move / remove) targets `manager.active`, so the model edits whichever
1007
+ * workspace is active and a host can re-point it (`WorkspaceManagerInterface.switch`) between
1008
+ * turns. Two REGISTRY ops make the model self-sufficient: `workspaces` LISTS the registered
1009
+ * workspaces (each `{ id, files, active }`) so it can discover an id, and `switch` re-points the
1010
+ * active workspace by id (lenient — an unknown id is a no-op reporting `switched: false`, never a
1011
+ * throw).
1012
+ *
1013
+ * NO-ACTIVE RULE (the ergonomic seam): a WRITING op (write / splice / prepend / append / move /
1014
+ * remove / replace) run when `manager.active` is `undefined` AUTO-CREATES + activates a default
1015
+ * workspace (`manager.add()`) so the model can just start writing; a pure-READ op (read / list /
1016
+ * has / search) against no active workspace returns the EMPTY result (`undefined` / `[]` /
1017
+ * `false`), never creating one and never throwing.
1018
+ *
1019
+ * The handler conforms to the universal tool-handler contract (AGENTS §14): it `contract.parse`s
1020
+ * the args, THROWS a `TOOL` `WorkspaceError` when no operation arm matched (a malformed / unknown
1021
+ * operation), else `switch`es on `op.operation` and RETURNS the plain result — letting a
1022
+ * `WorkspaceError` raised by the live workspace (`MODALITY` / `PATTERN` / `RANGE`) PROPAGATE
1023
+ * uncaught. The range edit is the FLAT `'splice'` op: its four flat caret integers are
1024
+ * reassembled into a `Range` (`@orkestrel/agent`) by `rangeOf` and fed to the workspace's ranged
1025
+ * `write`.
1026
+ *
1027
+ * @param options - `manager` (drive directly) OR `store` (build a manager over it); neither ⇒
1028
+ * an in-memory-backed manager (see {@link import('./types.js').WorkspaceToolOptions})
1029
+ * @returns A `ToolInterface` (named {@link import('./constants.js').WORKSPACE_TOOL_NAME} by default)
1030
+ *
1031
+ * @example
1032
+ * ```ts
1033
+ * import { createWorkspaceTool } from '@src/core'
1034
+ * import { createToolManager } from '@orkestrel/tool'
1035
+ *
1036
+ * const tool = createWorkspaceTool() // in-memory workspace, no persistence
1037
+ * const tools = createToolManager()
1038
+ * tools.add(tool)
1039
+ * ```
1040
+ */
1041
+ export declare function createWorkspaceTool(options?: WorkspaceToolOptions): ToolInterface;
1042
+
1043
+ /**
1044
+ * Normalize the database tool's parsed SERIALIZED criteria into a live `@orkestrel/database`
1045
+ * {@link Criteria} — default each condition's OMITTED `connector` to `'and'`.
1046
+ *
1047
+ * @remarks
1048
+ * The wire form ({@link import('./shapers.js').databaseToolShape}) lets a caller drop `connector`
1049
+ * on the last condition (it has nothing to join FORWARD to); the compiled `Condition` a live
1050
+ * `@orkestrel/database` table call accepts always carries one, so this fills the gap. `order` /
1051
+ * `limit` / `offset` pass through unchanged. Pure and total.
1052
+ *
1053
+ * @param criteria - The parsed criteria (or `undefined`)
1054
+ * @returns The equivalent live `Criteria`, or `undefined` when `criteria` is `undefined`
1055
+ */
1056
+ export declare function criteriaOf(criteria: Readonly<{
1057
+ conditions?: readonly Readonly<{
1058
+ column: string;
1059
+ operator: Condition['operator'];
1060
+ values: readonly unknown[];
1061
+ connector?: Connector;
1062
+ }>[];
1063
+ order?: readonly Readonly<{
1064
+ column: string;
1065
+ direction: Direction;
1066
+ }>[];
1067
+ limit?: number;
1068
+ offset?: number;
1069
+ }> | undefined): Criteria | undefined;
1070
+
1071
+ /** The SERIALIZED criteria form — conditions, order, and pagination. */
1072
+ export declare const criteriaShape: ObjectShape<{
1073
+ conditions: OptionalShape<ArrayShape<ObjectShape<{
1074
+ column: StringShape;
1075
+ operator: LiteralShape<readonly ["equals", "not", "above", "below", "from", "to", "between", "like", "glob", "starts", "ends", "any", "none", "absent", "present"]>;
1076
+ values: ArrayShape<JSONShape>;
1077
+ connector: OptionalShape<LiteralShape<readonly ["and", "or"]>>;
1078
+ }, false>>>;
1079
+ order: OptionalShape<ArrayShape<ObjectShape<{
1080
+ column: StringShape;
1081
+ direction: LiteralShape<readonly ["ascending", "descending"]>;
1082
+ }, false>>>;
1083
+ limit: OptionalShape<NumberShape>;
1084
+ offset: OptionalShape<NumberShape>;
1085
+ }, false>;
1086
+
1087
+ /**
1088
+ * The DESCRIPTION the upcoming database tool will advertise — a multi-line guide that teaches a
1089
+ * small model the operation list, the SERIALIZED criteria form, and the {@link import('./types.js').TableSpec}
1090
+ * column DSL.
1091
+ *
1092
+ * @remarks
1093
+ * The criteria form is deliberately SERIALIZED (never fluent) — every condition is a flat object
1094
+ * `{ column, operator, values, connector? }` where `values` is ALWAYS an array, even for a
1095
+ * single-value operator (`{ column: 'age', operator: 'from', values: [18] }`), so a small model
1096
+ * never has to chain method calls or guess whether a value is scalar or a list.
1097
+ */
1098
+ export declare const DATABASE_TOOL_DESCRIPTION: string;
1099
+
1100
+ /** The default cap on rows a `records` / `remove` call returns (or acts on) when the caller omits `criteria.limit` — the upcoming database tool's default row ceiling. */
1101
+ export declare const DATABASE_TOOL_LIMIT = 1000;
1102
+
1103
+ /** The database tool's mutating operations — disabled by `DatabaseToolOptions.readonly`. */
1104
+ export declare const DATABASE_TOOL_MUTATIONS: Set<string>;
1105
+
1106
+ /**
1107
+ * The name the upcoming `createDatabaseTool` factory will advertise by default — the key a model
1108
+ * calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
1109
+ *
1110
+ * @remarks
1111
+ * SRC-1 of a 3-unit spine: this unit lands the persistence + schema foundation
1112
+ * ({@link import('./types.js').DatabaseDefinition}, {@link import('./types.js').DefinitionStoreInterface},
1113
+ * {@link import('./helpers.js').expandTables}); `createDatabaseTool` itself is built in a later unit.
1114
+ */
1115
+ export declare const DATABASE_TOOL_NAME = "database";
1116
+
1117
+ /**
1118
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} the upcoming database tool
1119
+ * will advertise in place of {@link DATABASE_TOOL_DESCRIPTION}.
1120
+ */
1121
+ export declare const DATABASE_TOOL_SUMMARY = "Create and query a database \u2014 one operation per call (create, tables, get, records, count, aggregate, add, set, update, remove, migrate, destroy), chosen by the 'operation' field. Call describe('database') for the full operation list, the criteria form, and the column DSL.";
1122
+
1123
+ /**
1124
+ * One database's CONFIG-ONLY definition — `id` + `driver` + {@link TableSpec} (+ optional `keys`),
1125
+ * the pure-JSON blueprint the upcoming database / relation tools build a live database from.
1126
+ *
1127
+ * @remarks
1128
+ * A `DatabaseDefinition` is NEVER a live handle — it is the durable, serializable config a
1129
+ * {@link DefinitionStoreInterface} persists and a tool factory turns into a real
1130
+ * `@orkestrel/database` `DatabaseInterface` (via `createDatabase` + {@link import('./helpers.js').expandTables})
1131
+ * on demand. `keys`, when present, maps a table name to its primary-key column (omitted ⇒ the
1132
+ * driver's default primary key).
1133
+ */
1134
+ export declare interface DatabaseDefinition {
1135
+ readonly id: string;
1136
+ readonly driver: string;
1137
+ readonly tables: TableSpec;
1138
+ readonly keys?: Readonly<Record<string, string>>;
1139
+ }
1140
+
1141
+ /** One opaque persisted row — the shape a `TableInterface<DatabaseDefinitionRow>`-backed store reads/writes; `definition` is narrowed with {@link import('./helpers.js').isDatabaseDefinition} on read. */
1142
+ export declare interface DatabaseDefinitionRow {
1143
+ readonly id: string;
1144
+ readonly definition: unknown;
1145
+ }
1146
+
1147
+ /**
1148
+ * A {@link DefinitionStoreInterface} backed by one table of the `@orkestrel/database` layer — a
1149
+ * database's durable CONFIG state IS a row, so persistence reduces to keyed point-access
1150
+ * (`get` / `set` / `delete`) over a {@link TableInterface}, the driver-pluggable twin of the
1151
+ * plain-`Map` {@link import('./MemoryDefinitionStore.js').MemoryDefinitionStore}.
1152
+ *
1153
+ * @remarks
1154
+ * The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,
1155
+ * JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a JSON / SQLite /
1156
+ * IndexedDB backend swaps in WITHOUT touching a consumer — the same seam as
1157
+ * {@link import('./MemoryDefinitionStore.js').MemoryDefinitionStore}. The driver defaults to
1158
+ * memory ({@link import('../factories.js').createDatabaseDefinitionStore} passes
1159
+ * `createMemoryDriver()`), so it ALSO works in memory out of the box; you opt into the durable
1160
+ * plumbing by passing a JSON / SQLite / IndexedDB driver.
1161
+ *
1162
+ * The {@link DatabaseDefinition} is stored as ONE OPAQUE JSON COLUMN — the table is a row of
1163
+ * `{ id; definition }` ({@link DatabaseDefinitionRow}). The definition is already a COMPLETE,
1164
+ * self-contained, pure-JSON CONFIG payload (never a live handle), so storing it whole is lossless
1165
+ * AND keeps the row type flat (`definition` reads back as `unknown`).
1166
+ *
1167
+ * - **`set(definition)` upserts under the definition's OWN `id`** (no separate id param) — it
1168
+ * writes the row `{ id: definition.id, definition }`.
1169
+ * - **`get(id)` resolves the stored definition for an id**, narrowing the opaque JSON column back
1170
+ * to a {@link DatabaseDefinition} ({@link import('../helpers.js').isDatabaseDefinition} — the
1171
+ * AGENTS §14 boundary narrow for an untrusted storage read), or `undefined` if none is stored
1172
+ * or the stored blob is malformed.
1173
+ * - **`delete(id)` drops a definition by id**; an absent id is a no-op (no throw).
1174
+ *
1175
+ * The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the §22 method
1176
+ * bijection with {@link DefinitionStoreInterface}).
1177
+ *
1178
+ * @example
1179
+ * ```ts
1180
+ * import { createDatabaseDefinitionStore, createMemoryDriver } from '@src/core'
1181
+ *
1182
+ * const store = createDatabaseDefinitionStore(createMemoryDriver()) // a durable driver swaps in here
1183
+ * await store.set({ id: 'shop', driver: 'memory', tables: {} }) // persist the config (one JSON column)
1184
+ * const definition = await store.get('shop')
1185
+ * await store.delete('shop')
1186
+ * ```
1187
+ */
1188
+ export declare class DatabaseDefinitionStore implements DefinitionStoreInterface {
1189
+ #private;
1190
+ /**
1191
+ * Wrap a table as a definition store.
1192
+ *
1193
+ * @param table - The {@link TableInterface} holding the definitions — its row is the
1194
+ * {@link DatabaseDefinitionRow} `{ id; definition }` shape (the definition one opaque JSON column)
1195
+ */
1196
+ constructor(table: TableInterface<DatabaseDefinitionRow>);
1197
+ /** Resolve the persisted definition for `id`, narrowing the opaque JSON column back to a `DatabaseDefinition`. */
1198
+ get(id: string): Promise<DatabaseDefinition | undefined>;
1199
+ /** Insert or replace under the definition's OWN `id` (no separate id param) — the row is `{ id, definition }`. */
1200
+ set(definition: DatabaseDefinition): Promise<void>;
1201
+ /** Drop a definition by id; an absent id is a no-op (no throw). */
1202
+ delete(id: string): Promise<void>;
1203
+ }
1204
+
1205
+ /**
1206
+ * Resolve database definitions into cached live handles for database tools.
1207
+ *
1208
+ * @example
1209
+ * ```ts
1210
+ * import { DatabaseResolver } from '@orkestrel/toolbox'
1211
+ *
1212
+ * const resolver = new DatabaseResolver(handles, drivers, key, store)
1213
+ * const database = await resolver.resolve('shop')
1214
+ * ```
1215
+ */
1216
+ export declare class DatabaseResolver {
1217
+ #private;
1218
+ /**
1219
+ * Create a database resolver over the tool's live state and optional definition store.
1220
+ *
1221
+ * @param handles - Initial live database handles cached by id
1222
+ * @param drivers - Driver factories keyed by definition driver name
1223
+ * @param key - Key generator supplied to newly created databases
1224
+ * @param store - Optional persistent definition store
1225
+ */
1226
+ constructor(handles: ReadonlyMap<string, DatabaseInterface>, drivers: Readonly<Record<string, () => DriverInterface>>, key: KeyFunction, store?: DefinitionStoreInterface);
1227
+ /**
1228
+ * Determine whether a live database is cached by id.
1229
+ *
1230
+ * @param id - Database id
1231
+ * @returns Whether a live handle is cached
1232
+ */
1233
+ has(id: string): boolean;
1234
+ /**
1235
+ * Read a cached database without consulting the definition store.
1236
+ *
1237
+ * @param id - Database id
1238
+ * @returns The cached live database, or `undefined`
1239
+ */
1240
+ get(id: string): DatabaseInterface | undefined;
1241
+ /**
1242
+ * Cache a live database by id.
1243
+ *
1244
+ * @param id - Database id
1245
+ * @param database - Live database handle
1246
+ * @returns Nothing
1247
+ */
1248
+ set(id: string, database: DatabaseInterface): void;
1249
+ /**
1250
+ * Remove a cached live database by id.
1251
+ *
1252
+ * @param id - Database id
1253
+ * @returns Nothing
1254
+ */
1255
+ delete(id: string): void;
1256
+ /**
1257
+ * Resolve a cached or stored database by id.
1258
+ *
1259
+ * @param id - Database definition id
1260
+ * @returns The cached or newly constructed live database
1261
+ */
1262
+ resolve(id: string): Promise<DatabaseInterface>;
1263
+ }
1264
+
1265
+ /**
1266
+ * Map a caught error to the {@link ToolboxErrorCode} the upcoming database tool should throw
1267
+ * with — the pure classification step of that factory's error handling, mirroring
1268
+ * {@link terminalToolCode}'s idiom for `@orkestrel/database`.
1269
+ *
1270
+ * @param error - The value caught from a `@orkestrel/database` table operation
1271
+ * @returns The granular {@link DatabaseErrorCode}, or `undefined` if `error` is not a `DatabaseError`
1272
+ */
1273
+ export declare function databaseToolCode(error: unknown): DatabaseErrorCode | undefined;
1274
+
1275
+ /**
1276
+ * Options for {@link import('./factories.js').createDatabaseTool} — SRC-2 of the 3-unit database
1277
+ * / relation spine, built over the SRC-1 foundation ({@link DatabaseDefinition},
1278
+ * {@link DefinitionStoreInterface}, {@link import('./helpers.js').expandTables}).
1279
+ *
1280
+ * @remarks
1281
+ * - `databases` — live `DatabaseInterface` handles to seed the tool's cache with (e.g. a
1282
+ * caller-constructed database it should manage alongside store-backed ones); keyed by the id a
1283
+ * call's `id` field addresses.
1284
+ * - `store` — the {@link DefinitionStoreInterface} the `'create'` / `'migrate'` operations persist
1285
+ * their {@link DatabaseDefinition} CONFIG through, and `'destroy'` deletes from; also the source
1286
+ * `'get'`/every other operation resolves an id from when it isn't already cached. Omitted means
1287
+ * no persistence — a database created without a store lives only for the tool's lifetime.
1288
+ * - `drivers` — registry of driver-name to `() => DriverInterface` factories a `'create'` call's
1289
+ * `driver` field (or a persisted definition's `driver`) resolves against. Defaults to
1290
+ * `{ memory: () => createMemoryDriver() }` (`@orkestrel/database`).
1291
+ * - `key` — the `KeyFunction` (`@orkestrel/database`) every minted database is constructed with,
1292
+ * used when a written row lacks its primary key. Defaults to `generateUUID`.
1293
+ * - `limit` — the row cap `'records'` / `'remove'` — via {@link import('./helpers.js').clampCriteria}
1294
+ * — enforce when a call's `criteria.limit` is omitted or exceeds it. Defaults to
1295
+ * {@link import('./constants.js').DATABASE_TOOL_LIMIT}.
1296
+ * - `timeout` — milliseconds; when set, every `@orkestrel/database` call this tool makes is given
1297
+ * a fresh `AbortSignal.timeout(timeout)` per tool call.
1298
+ * - `readonly` — when `true`, every mutating operation (`'create'` / `'add'` / `'set'` /
1299
+ * `'update'` / `'remove'` / `'migrate'` / `'destroy'`) throws a typed `TOOL`
1300
+ * {@link import('./errors.js').ToolboxError} before doing anything.
1301
+ * - `name` / `description` — advertised tool overrides; default to
1302
+ * {@link import('./constants.js').DATABASE_TOOL_NAME} / {@link import('./constants.js').DATABASE_TOOL_DESCRIPTION}.
1303
+ */
1304
+ export declare interface DatabaseToolOptions {
1305
+ readonly name?: string;
1306
+ readonly description?: string;
1307
+ readonly databases?: Readonly<Record<string, DatabaseInterface>>;
1308
+ readonly store?: DefinitionStoreInterface;
1309
+ readonly drivers?: Readonly<Record<string, () => DriverInterface>>;
1310
+ readonly key?: KeyFunction;
1311
+ readonly limit?: number;
1312
+ readonly timeout?: number;
1313
+ readonly readonly?: boolean;
1314
+ }
1315
+
1316
+ /**
1317
+ * The shape of {@link import('./factories.js').createDatabaseTool}'s call arguments —
1318
+ * discriminated by `operation` into the 12 database operations (`'create'` / `'tables'` /
1319
+ * `'get'` / `'records'` / `'count'` / `'aggregate'` / `'add'` / `'set'` / `'update'` /
1320
+ * `'remove'` / `'migrate'` / `'destroy'`).
1321
+ *
1322
+ * @remarks
1323
+ * Every arm carries `id` (the database id). `'create'` / `'migrate'` carry `tables` (the
1324
+ * {@link import('./types.js').TableSpec} column DSL, compiled via
1325
+ * {@link import('./helpers.js').expandTables}); `'get'` / `'update'` / `'remove'` carry `key`
1326
+ * (one key or an array of keys, positional); `'add'` / `'set'` carry `row` (one row or an array of
1327
+ * rows); `'update'` also carries `changes` (a loose partial row); `'records'` / `'count'` /
1328
+ * `'aggregate'` carry an optional `criteria` (the SERIALIZED form — `values` is ALWAYS an array,
1329
+ * even for a single-value operator, so a caller never chains method calls or guesses arity).
1330
+ */
1331
+ export declare const databaseToolShape: UnionShape<readonly [ ObjectShape<{
1332
+ operation: LiteralShape<readonly ["create"]>;
1333
+ id: StringShape;
1334
+ tables: ObjectShape<Record<never, never>, ObjectShape<{
1335
+ columns: ObjectShape<Record<never, never>, UnionShape<readonly [ LiteralShape<readonly ["string", "integer", "number", "boolean"]>, ObjectShape<{
1336
+ type: LiteralShape<readonly ["string", "integer", "number", "boolean"]>;
1337
+ optional: OptionalShape<BooleanShape>;
1338
+ }, false>]>>;
1339
+ }, false>>;
1340
+ driver: OptionalShape<StringShape>;
1341
+ keys: OptionalShape<ObjectShape<Record<never, never>, StringShape>>;
1342
+ }, false>, ObjectShape<{
1343
+ operation: LiteralShape<readonly ["tables"]>;
1344
+ id: StringShape;
1345
+ }, false>, ObjectShape<{
1346
+ operation: LiteralShape<readonly ["get"]>;
1347
+ id: StringShape;
1348
+ table: StringShape;
1349
+ key: UnionShape<readonly [ ArrayShape<UnionShape<readonly [ StringShape, NumberShape]>>, StringShape, NumberShape]>;
1350
+ }, false>, ObjectShape<{
1351
+ operation: LiteralShape<readonly ["records"]>;
1352
+ id: StringShape;
1353
+ table: StringShape;
1354
+ criteria: OptionalShape<ObjectShape<{
1355
+ conditions: OptionalShape<ArrayShape<ObjectShape<{
1356
+ column: StringShape;
1357
+ operator: LiteralShape<readonly ["equals", "not", "above", "below", "from", "to", "between", "like", "glob", "starts", "ends", "any", "none", "absent", "present"]>;
1358
+ values: ArrayShape<JSONShape>;
1359
+ connector: OptionalShape<LiteralShape<readonly ["and", "or"]>>;
1360
+ }, false>>>;
1361
+ order: OptionalShape<ArrayShape<ObjectShape<{
1362
+ column: StringShape;
1363
+ direction: LiteralShape<readonly ["ascending", "descending"]>;
1364
+ }, false>>>;
1365
+ limit: OptionalShape<NumberShape>;
1366
+ offset: OptionalShape<NumberShape>;
1367
+ }, false>>;
1368
+ }, false>, ObjectShape<{
1369
+ operation: LiteralShape<readonly ["count"]>;
1370
+ id: StringShape;
1371
+ table: StringShape;
1372
+ criteria: OptionalShape<ObjectShape<{
1373
+ conditions: OptionalShape<ArrayShape<ObjectShape<{
1374
+ column: StringShape;
1375
+ operator: LiteralShape<readonly ["equals", "not", "above", "below", "from", "to", "between", "like", "glob", "starts", "ends", "any", "none", "absent", "present"]>;
1376
+ values: ArrayShape<JSONShape>;
1377
+ connector: OptionalShape<LiteralShape<readonly ["and", "or"]>>;
1378
+ }, false>>>;
1379
+ order: OptionalShape<ArrayShape<ObjectShape<{
1380
+ column: StringShape;
1381
+ direction: LiteralShape<readonly ["ascending", "descending"]>;
1382
+ }, false>>>;
1383
+ limit: OptionalShape<NumberShape>;
1384
+ offset: OptionalShape<NumberShape>;
1385
+ }, false>>;
1386
+ }, false>, ObjectShape<{
1387
+ operation: LiteralShape<readonly ["aggregate"]>;
1388
+ id: StringShape;
1389
+ table: StringShape;
1390
+ function: LiteralShape<readonly ["count", "sum", "average", "minimum", "maximum"]>;
1391
+ column: StringShape;
1392
+ criteria: OptionalShape<ObjectShape<{
1393
+ conditions: OptionalShape<ArrayShape<ObjectShape<{
1394
+ column: StringShape;
1395
+ operator: LiteralShape<readonly ["equals", "not", "above", "below", "from", "to", "between", "like", "glob", "starts", "ends", "any", "none", "absent", "present"]>;
1396
+ values: ArrayShape<JSONShape>;
1397
+ connector: OptionalShape<LiteralShape<readonly ["and", "or"]>>;
1398
+ }, false>>>;
1399
+ order: OptionalShape<ArrayShape<ObjectShape<{
1400
+ column: StringShape;
1401
+ direction: LiteralShape<readonly ["ascending", "descending"]>;
1402
+ }, false>>>;
1403
+ limit: OptionalShape<NumberShape>;
1404
+ offset: OptionalShape<NumberShape>;
1405
+ }, false>>;
1406
+ }, false>, ObjectShape<{
1407
+ operation: LiteralShape<readonly ["add"]>;
1408
+ id: StringShape;
1409
+ table: StringShape;
1410
+ row: UnionShape<readonly [ ArrayShape<ObjectShape<Record<never, never>, JSONShape>>, ObjectShape<Record<never, never>, JSONShape>]>;
1411
+ }, false>, ObjectShape<{
1412
+ operation: LiteralShape<readonly ["set"]>;
1413
+ id: StringShape;
1414
+ table: StringShape;
1415
+ row: UnionShape<readonly [ ArrayShape<ObjectShape<Record<never, never>, JSONShape>>, ObjectShape<Record<never, never>, JSONShape>]>;
1416
+ }, false>, ObjectShape<{
1417
+ operation: LiteralShape<readonly ["update"]>;
1418
+ id: StringShape;
1419
+ table: StringShape;
1420
+ key: UnionShape<readonly [ ArrayShape<UnionShape<readonly [ StringShape, NumberShape]>>, StringShape, NumberShape]>;
1421
+ changes: ObjectShape<Record<never, never>, JSONShape>;
1422
+ }, false>, ObjectShape<{
1423
+ operation: LiteralShape<readonly ["remove"]>;
1424
+ id: StringShape;
1425
+ table: StringShape;
1426
+ key: UnionShape<readonly [ ArrayShape<UnionShape<readonly [ StringShape, NumberShape]>>, StringShape, NumberShape]>;
1427
+ }, false>, ObjectShape<{
1428
+ operation: LiteralShape<readonly ["migrate"]>;
1429
+ id: StringShape;
1430
+ tables: ObjectShape<Record<never, never>, ObjectShape<{
1431
+ columns: ObjectShape<Record<never, never>, UnionShape<readonly [ LiteralShape<readonly ["string", "integer", "number", "boolean"]>, ObjectShape<{
1432
+ type: LiteralShape<readonly ["string", "integer", "number", "boolean"]>;
1433
+ optional: OptionalShape<BooleanShape>;
1434
+ }, false>]>>;
1435
+ }, false>>;
1436
+ }, false>, ObjectShape<{
1437
+ operation: LiteralShape<readonly ["destroy"]>;
1438
+ id: StringShape;
1439
+ }, false>]>;
1440
+
1441
+ /**
1442
+ * The point-access persistence seam (AGENTS §5 — Stores) for {@link DatabaseDefinition} configs —
1443
+ * the twin of `@orkestrel/terminal`'s `TerminalStoreInterface`, storing a database's CONFIG-ONLY
1444
+ * blueprint (never a live handle). Every primitive is async; `delete` of an absent id is a no-op.
1445
+ */
1446
+ export declare interface DefinitionStoreInterface {
1447
+ get(id: string): Promise<DatabaseDefinition | undefined>;
1448
+ set(definition: DatabaseDefinition): Promise<void>;
1449
+ delete(id: string): Promise<void>;
1450
+ }
1451
+
1452
+ /**
1453
+ * The DESCRIPTION {@link import('./factories.js').createDescribeTool} advertises.
1454
+ *
1455
+ * @remarks
1456
+ * Deliberately short — unlike the workflow / workspace / agent tools, this one has no authoring
1457
+ * schema or multi-step protocol to teach.
1458
+ */
1459
+ 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).";
1460
+
1461
+ /**
1462
+ * The name {@link import('./factories.js').createDescribeTool} advertises by default — the key a
1463
+ * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
1464
+ *
1465
+ * @remarks
1466
+ * Net-new: pairs with the other three tools' lean {@link AGENT_TOOL_SUMMARY} /
1467
+ * {@link WORKFLOW_TOOL_SUMMARY} / {@link WORKSPACE_TOOL_SUMMARY} — a model that reads only the
1468
+ * advertised summary can call `describe` with that tool's registered name to get its full
1469
+ * teaching description back.
1470
+ */
1471
+ export declare const DESCRIBE_TOOL_NAME = "describe";
1472
+
1473
+ /**
1474
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createDescribeTool}
1475
+ * advertises — this tool needs no teaching of its own, so its summary and description are both
1476
+ * short.
1477
+ */
1478
+ export declare const DESCRIBE_TOOL_SUMMARY = "Return the full description of a named registered tool.";
1479
+
1480
+ /**
1481
+ * The FLAT args {@link import('./factories.js').createDescribeTool} accepts — the registered
1482
+ * tool `name` whose full `description` a model wants back.
1483
+ *
1484
+ * @remarks
1485
+ * `name` must match a tool registered on the {@link import('@orkestrel/tool').ToolManagerInterface}
1486
+ * the describe tool was built over — it is looked up via `tools.tool(name)`.
1487
+ */
1488
+ export declare interface DescribeToolArguments {
1489
+ readonly name: string;
1490
+ }
1491
+
1492
+ /**
1493
+ * The shape of {@link import('./types.js').DescribeToolArguments} —
1494
+ * {@link import('./factories.js').createDescribeTool}'s advertised `parameters`.
1495
+ *
1496
+ * @remarks
1497
+ * `name` is the only field (a non-empty string) — the registered tool name to look up.
1498
+ */
1499
+ export declare const describeToolShape: ObjectShape<{
1500
+ name: StringShape;
1501
+ }, false>;
1502
+
1503
+ /**
1504
+ * One concrete endpoint {@link import('./factories.js').createEndpointTool} wraps as an
1505
+ * LLM-callable `ToolInterface` — the advertised identity, a non-empty set of example values its
1506
+ * `parameters` are inferred from, and the local handler that runs a call.
1507
+ *
1508
+ * @remarks
1509
+ * `samples` MUST be non-empty — {@link import('./factories.js').createEndpointTool} throws a
1510
+ * typed `TOOL` {@link import('./errors.js').ToolboxError} at CONSTRUCTION when it is empty,
1511
+ * since an empty sample set cannot infer a schema. By DEFAULT ({@link EndpointToolOptions.validate}
1512
+ * `true`) `invoke` receives the PARSED, NORMALIZED args record — a copy of the model-supplied
1513
+ * `args` with each scalar coerced to its inferred type (e.g. a number sent for a string slot
1514
+ * arrives coerced to a string), checked against the same schema advertised as `parameters` — and
1515
+ * a call with a missing required key or a non-coercible value never reaches `invoke` at all (see
1516
+ * {@link EndpointToolOptions.validate}). With
1517
+ * `validate: false`, `invoke` receives the model-supplied `args` VERBATIM (raw passthrough, never
1518
+ * checked against the inferred schema). Either way `invoke`'s return flows back as the tool
1519
+ * call's result; a throw PROPAGATES uncaught, isolated by the `ToolManagerInterface`
1520
+ * (`@orkestrel/tool`) into the canonical error envelope. When `samples` are non-object values,
1521
+ * the advertised schema wraps them under a single required `value` property, so `invoke` receives
1522
+ * an `args` record of the shape `{ value: ... }` — never the bare value.
1523
+ */
1524
+ export declare interface EndpointDefinition {
1525
+ readonly name: string;
1526
+ readonly description: string;
1527
+ readonly samples: readonly unknown[];
1528
+ readonly invoke: EndpointHandler;
1529
+ }
1530
+
1531
+ /**
1532
+ * The handler {@link import('./types.js').EndpointDefinition.invoke} implements — mirrors
1533
+ * `@orkestrel/tool`'s `ToolOptions.execute` signature EXACTLY (same `Readonly<Record<string,
1534
+ * unknown>>` argument, same `Promise<unknown> | unknown` return) so
1535
+ * `execute: (args) => definition.invoke(args)` typechecks with zero assertions in
1536
+ * {@link import('./factories.js').createEndpointTool}.
1537
+ */
1538
+ export declare type EndpointHandler = (args: Readonly<Record<string, unknown>>) => Promise<unknown> | unknown;
1539
+
1540
+ /**
1541
+ * Construction-time tuning for {@link import('./factories.js').createEndpointTool} — the
1542
+ * inferred `parameters` schema's `format` / `enum` constraints, and whether that same schema is
1543
+ * ENFORCED at `execute` time.
1544
+ *
1545
+ * @remarks
1546
+ * `format` / `enum` default to `false`, matching `@orkestrel/contract`'s own
1547
+ * `ValueToSchemaOptions` defaults. `validate` defaults to `true`: the schema
1548
+ * `createEndpointTool` advertises as `parameters` (`samplesToSchema` + `schemaToObject`) is
1549
+ * compiled ONCE at construction (via `@orkestrel/contract` 0.0.7's `schemaToShape`) into a
1550
+ * `ContractInterface` used to `parse` every call's `args` before `invoke` runs — a NORMALIZING
1551
+ * parse: a scalar value is COERCED to its inferred type where the house parsers coerce (a number
1552
+ * to/from a numeric string, a boolean from `'1'`/`'0'`/`'true'`/`'false'`/`1`/`0`), so `invoke`
1553
+ * receives the COERCED values (e.g. `7` sent for a string slot arrives at `invoke` as `'7'`), not
1554
+ * the raw call args. A call whose `args` fails to parse — a required key missing, or a value not
1555
+ * coercible to its slot's type — THROWS a typed `TOOL` {@link import('./errors.js').ToolboxError}
1556
+ * carrying the structured `explain` faults, and `invoke` is never called. Beyond that coercion,
1557
+ * enforcement is STRUCTURAL — required keys, `enum` membership, and numeric bounds — `format`
1558
+ * annotations (`email`, `date-time`, `uuid`, `uri`, ...) are NEVER asserted, mirroring
1559
+ * `@orkestrel/contract`'s own widening-only law for `schemaToShape`: a `format: true`-tuned
1560
+ * endpoint still ACCEPTS a non-conforming string in a format-tagged slot. A key NOT present in
1561
+ * the inferred (closed, `additionalProperties: false`) schema is NEVER a rejection either — it is
1562
+ * SILENTLY DROPPED before `invoke` runs (the same leniency `@orkestrel/contract`'s own `parse`
1563
+ * grants a closed object generally), so `invoke` may see fewer keys than the caller sent. Set
1564
+ * `validate: false` to restore the PRE-0.0.7 behavior exactly — `execute` passes the
1565
+ * model-supplied `args` straight to `invoke` UNCHANGED, unchecked and unstripped.
1566
+ */
1567
+ export declare interface EndpointToolOptions {
1568
+ readonly format?: boolean;
1569
+ readonly enum?: boolean;
1570
+ readonly validate?: boolean;
1571
+ }
1572
+
1573
+ /**
1574
+ * Expand the relation tool's FLAT dot-path `include` list into a live `@orkestrel/relation`
1575
+ * {@link Include} tree — the pure leaf {@link import('./factories.js').createRelationTool} calls
1576
+ * before a `'load'` / `'find'` call.
1577
+ *
1578
+ * @remarks
1579
+ * Each path splits on `'.'` into a chain of relation names, deep-merged into one nested
1580
+ * `Include` object with a leaf `true`. A longer path SUBSUMES a shorter sibling's bare `true` —
1581
+ * `'contacts'` followed by `'contacts.account'` yields `{ contacts: { account: true } }`, never
1582
+ * overwriting the deeper chain. An EMPTY segment (`''`, from a leading/trailing/doubled `.`) or a
1583
+ * path whose segment count exceeds `depth` throws a typed `TOOL` {@link ToolboxError}.
1584
+ *
1585
+ * @param paths - The flat dot-path `include` list (or `undefined` — yields `{}`)
1586
+ * @param depth - The max segment count a single path may reach
1587
+ * @returns The equivalent nested {@link Include}
1588
+ *
1589
+ * @example
1590
+ * ```ts
1591
+ * import { expandInclude } from '@src/core'
1592
+ *
1593
+ * expandInclude(['contacts', 'contacts.account'], 3)
1594
+ * // { contacts: { account: true } }
1595
+ * ```
1596
+ */
1597
+ export declare function expandInclude(paths: readonly string[] | undefined, depth: number): Include;
1598
+
1599
+ /**
1600
+ * Expand a flat {@link WorkflowSteps} blob into a strict {@link WorkflowDefinition} — each step
1601
+ * becomes a one-task phase, IN ORDER.
1602
+ *
1603
+ * @remarks
1604
+ * The expansion of the tool's ADVERTISED surface: the deliberately-reduced flat form. Each
1605
+ * {@link import('./types.js').WorkflowStep} maps to a phase holding exactly one task: the step's
1606
+ * `name` becomes the task's `run` (the behavior-registry key). Ids/names are auto-filled
1607
+ * positionally — it builds an ids-omitted {@link WorkflowDraft} and delegates to
1608
+ * {@link completeDraft}, so the two lenient surfaces share ONE synthesis path (step `i` → phase
1609
+ * `phase-<i>`, its task `phase-<i>-task-0`). The optional `name` becomes the workflow's `name`.
1610
+ * The result is a complete definition the caller validates against the STRICT contract before
1611
+ * running.
1612
+ *
1613
+ * @param flat - The flat steps blob (`{ name?, steps: [{ name }] }`)
1614
+ * @returns A complete {@link WorkflowDefinition} (one one-task phase per step)
1615
+ */
1616
+ export declare function expandSteps(flat: WorkflowSteps): WorkflowDefinition;
1617
+
1618
+ /**
1619
+ * Compile a {@link TableSpec} into the `@orkestrel/database` {@link TablesShape} it configures —
1620
+ * each {@link ColumnSpec} maps to the matching primitive shaper (`'string'` → `stringShape()`,
1621
+ * `'integer'` → `integerShape()`, `'number'` → `numberShape()`, `'boolean'` → `booleanShape()`),
1622
+ * wrapped in `optionalShape` when the column declares `optional: true`. Total, pure.
1623
+ *
1624
+ * @param spec - The small-model-facing table layout
1625
+ * @returns The compiled `TablesShape` a `@orkestrel/database` `createDatabase` call accepts
1626
+ */
1627
+ export declare function expandTables(spec: TableSpec): TablesShape;
1628
+
1629
+ /** Flat dot-path relation include list, expanded via {@link import('./helpers.js').expandInclude}. */
1630
+ export declare const includeShape: OptionalShape<ArrayShape<StringShape>>;
1631
+
1632
+ export declare const INFER_TOOL_DESCRIPTION: string;
1633
+
1634
+ /**
1635
+ * The name {@link import('./factories.js').createInferTool} advertises by default — the key a
1636
+ * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
1637
+ */
1638
+ export declare const INFER_TOOL_NAME = "infer";
1639
+
1640
+ /**
1641
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createInferTool}
1642
+ * advertises in place of {@link INFER_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
1643
+ * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
1644
+ * for the full teaching description; the full text stays retrievable via
1645
+ * {@link import('./factories.js').createDescribeTool}.
1646
+ */
1647
+ export declare const INFER_TOOL_SUMMARY = "Infer a JSON Schema (as advertised tool parameters) from one or more example values. Call describe('infer') for the required fields.";
1648
+
1649
+ /**
1650
+ * Options for {@link import('./factories.js').createInferTool} — advertised name/description
1651
+ * overrides only; `format` / `enum` are RUNTIME call arguments (see
1652
+ * {@link import('./shapers.js').inferToolShape}), not construction-time options, since a model
1653
+ * chooses them per call.
1654
+ */
1655
+ export declare interface InferToolOptions {
1656
+ readonly name?: string;
1657
+ readonly description?: string;
1658
+ }
1659
+
1660
+ /**
1661
+ * The shape of {@link import('./factories.js').createInferTool}'s call arguments — one or more
1662
+ * example `samples` to infer a JSON Schema from, plus per-call `format` / `enum` toggles and an
1663
+ * optional `candidates` array to check against the inferred schema.
1664
+ *
1665
+ * @remarks
1666
+ * `samples` requires at least one element (`min: 1`) — an empty array parses to `undefined`,
1667
+ * surfaced by the handler as a typed `TOOL` {@link import('./errors.js').ToolboxError}. When
1668
+ * `candidates` is present (any array, including empty), the handler compiles a contract from the
1669
+ * freshly inferred schema and checks each candidate against it with a STRICT guard (`.is`, no
1670
+ * coercion) — the opposite of {@link import('./factories.js').createEndpointTool}'s NORMALIZING
1671
+ * `.parse` enforcement.
1672
+ */
1673
+ export declare const inferToolShape: ObjectShape<{
1674
+ samples: ArrayShape<JSONShape>;
1675
+ format: OptionalShape<BooleanShape>;
1676
+ enum: OptionalShape<BooleanShape>;
1677
+ candidates: OptionalShape<ArrayShape<JSONShape>>;
1678
+ }, false>;
1679
+
1680
+ /** Narrow an unknown value to a {@link import('./types.js').ColumnKind}. */
1681
+ export declare function isColumnKind(value: unknown): value is ColumnKind;
1682
+
1683
+ /** Narrow an unknown value to a {@link ColumnSpec} — a valid {@link import('./types.js').ColumnKind} shorthand, or `{ type, optional }` with a valid `type`. */
1684
+ export declare function isColumnSpec(value: unknown): value is ColumnSpec;
1685
+
1686
+ /**
1687
+ * Narrow an unknown value to a {@link DatabaseDefinition} — a non-empty `id` + `driver`, a
1688
+ * `tables` record whose every value is `{ columns: record of valid ColumnSpec }`, and an optional
1689
+ * `keys` record of strings. The boundary guard a {@link import('./types.js').DefinitionStoreInterface}
1690
+ * applies to an untrusted persisted blob before trusting it as a definition (never an `as`).
1691
+ */
1692
+ export declare function isDatabaseDefinition(value: unknown): value is DatabaseDefinition;
1693
+
1694
+ /**
1695
+ * Type guard narrowing an unknown caught value to an {@link ToolboxError}.
1696
+ *
1697
+ * @param value - The value to test (typically a `catch` binding)
1698
+ * @returns `true` when `value` is an {@link ToolboxError}
1699
+ *
1700
+ * @example
1701
+ * ```ts
1702
+ * import { isToolboxError } from '@src/core'
1703
+ *
1704
+ * try {
1705
+ * // ...
1706
+ * } catch (error) {
1707
+ * if (isToolboxError(error)) console.log(error.code)
1708
+ * }
1709
+ * ```
1710
+ */
1711
+ export declare function isToolboxError(value: unknown): value is ToolboxError;
1712
+
1713
+ /** One key value — a string or number; the array form (multiple keys, positional) resolves FIRST per AGENTS §9.2. */
1714
+ export declare const keyShape: UnionShape<readonly [ ArrayShape<UnionShape<readonly [ StringShape, NumberShape]>>, StringShape, NumberShape]>;
1715
+
1716
+ /** Map one {@link import('./types.js').ColumnKind} to its primitive `@orkestrel/database` shape — the leaf {@link columnShape} wraps. */
1717
+ export declare function kindShape(kind: ColumnKind): ContractShape;
1718
+
1719
+ /** Which registered relation manager to address — omitted resolves to the sole registered manager. */
1720
+ export declare const managerShape: OptionalShape<StringShape>;
1721
+
1722
+ /**
1723
+ * The maximum nesting depth a workflow → agent → workflow chain may reach — the bound
1724
+ * {@link import('./factories.js').createAgentFunction} and
1725
+ * {@link import('./factories.js').createWorkflowTool}'s depth/cycle guards enforce.
1726
+ *
1727
+ * @remarks
1728
+ * OWNED here now (ported from `@orkestrel/workflow`, whose engine no longer uses it — only the
1729
+ * tool-authoring guards this package now owns consume it). The limit lives in ONE place: an
1730
+ * agent-function-wrapped agent running at this depth can no longer author + run a NESTED
1731
+ * workflow through its bound workflow tool (that would be depth `MAX_WORKFLOW_DEPTH + 1`), so
1732
+ * the over-deep invocation is REJECTED (a typed `DEPTH` `WorkflowError` throw, `@orkestrel/workflow`).
1733
+ */
1734
+ export declare const MAX_WORKFLOW_DEPTH = 8;
1735
+
1736
+ /**
1737
+ * The in-memory {@link DefinitionStoreInterface} — a process-lifetime `Map` of
1738
+ * {@link DatabaseDefinition}s keyed by database id, the DEFAULT store
1739
+ * {@link import('../factories.js').createMemoryDefinitionStore} builds. The EXACT twin of
1740
+ * {@link import('./DatabaseDefinitionStore.js').DatabaseDefinitionStore}.
1741
+ *
1742
+ * @remarks
1743
+ * A plain `Map<string, DatabaseDefinition>` (AGENTS §21 — the definition is already pure,
1744
+ * self-contained CONFIG-only JSON, so no encoding is needed for the memory tier). There is NO
1745
+ * idle-TTL and NO eviction: a persisted definition lives until an explicit `delete`. A durable
1746
+ * backend (JSON / SQLite / IndexedDB) swaps in through the SAME interface without touching a
1747
+ * consumer — its driver-pluggable twin is
1748
+ * {@link import('./DatabaseDefinitionStore.js').DatabaseDefinitionStore} (the definition as one
1749
+ * opaque JSON column).
1750
+ *
1751
+ * - **`get` resolves the persisted definition for an id**, or `undefined` if none is stored.
1752
+ * - **`set` inserts / replaces under the definition's OWN `id`** (no separate id param).
1753
+ * - **`delete` drops a definition by id**; an absent id is a no-op (no throw).
1754
+ *
1755
+ * The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the §22 method
1756
+ * bijection with {@link DefinitionStoreInterface}).
1757
+ *
1758
+ * @example
1759
+ * ```ts
1760
+ * import { createMemoryDefinitionStore } from '@src/core'
1761
+ *
1762
+ * const store = createMemoryDefinitionStore()
1763
+ * await store.set({ id: 'shop', driver: 'memory', tables: {} })
1764
+ * const definition = await store.get('shop')
1765
+ * await store.delete('shop')
1766
+ * ```
1767
+ */
1768
+ export declare class MemoryDefinitionStore implements DefinitionStoreInterface {
1769
+ #private;
1770
+ get(id: string): Promise<DatabaseDefinition | undefined>;
1771
+ set(definition: DatabaseDefinition): Promise<void>;
1772
+ delete(id: string): Promise<void>;
1773
+ }
1774
+
1775
+ /** One sort term. */
1776
+ export declare const orderShape: ObjectShape<{
1777
+ column: StringShape;
1778
+ direction: LiteralShape<readonly ["ascending", "descending"]>;
1779
+ }, false>;
1780
+
1781
+ /** A draft phase — a `PhaseDefinition` (`@orkestrel/workflow`) with OPTIONAL `id` / `name` and {@link TaskDraft} tasks. */
1782
+ export declare interface PhaseDraft {
1783
+ readonly id?: string;
1784
+ readonly name?: string;
1785
+ readonly description?: string;
1786
+ readonly tasks: readonly TaskDraft[];
1787
+ /** Max tasks in flight at once (a resource throttle); omitted ⇒ unbounded. */
1788
+ readonly concurrency?: number;
1789
+ /** The per-phase failure-policy OVERRIDE; omitted ⇒ inherits the workflow `bail`. */
1790
+ readonly bail?: boolean;
1791
+ }
1792
+
1793
+ /**
1794
+ * The shape of a PHASE in a draft workflow — identical to a strict phase shape EXCEPT `id` and
1795
+ * `name` are OPTIONAL, and its tasks are {@link taskDraftShape}s.
1796
+ */
1797
+ export declare const phaseDraftShape: ObjectShape<{
1798
+ id: OptionalShape<StringShape>;
1799
+ name: OptionalShape<StringShape>;
1800
+ description: OptionalShape<StringShape>;
1801
+ tasks: ArrayShape<ObjectShape<{
1802
+ id: OptionalShape<StringShape>;
1803
+ name: OptionalShape<StringShape>;
1804
+ description: OptionalShape<StringShape>;
1805
+ run: OptionalShape<StringShape>;
1806
+ retries: OptionalShape<NumberShape>;
1807
+ timeout: OptionalShape<NumberShape>;
1808
+ }, false>>;
1809
+ concurrency: OptionalShape<NumberShape>;
1810
+ bail: OptionalShape<LiteralShape<readonly [true, false]>>;
1811
+ }, false>;
1812
+
1813
+ export declare const PROMPT_TOOL_DESCRIPTION: string;
1814
+
1815
+ /**
1816
+ * The name {@link import('./factories.js').createPromptTool} advertises by default — the key a
1817
+ * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
1818
+ */
1819
+ export declare const PROMPT_TOOL_NAME = "ask";
1820
+
1821
+ /**
1822
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createPromptTool}
1823
+ * advertises in place of {@link PROMPT_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
1824
+ * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
1825
+ * for the full teaching description; the full text stays retrievable via
1826
+ * {@link import('./factories.js').createDescribeTool}.
1827
+ */
1828
+ export declare const PROMPT_TOOL_SUMMARY = "Ask another terminal a question and BLOCK until it answers; the call resolves with the answered value. Call describe('ask') for the required fields.";
1829
+
1830
+ /**
1831
+ * Options for {@link import('./factories.js').createPromptTool} — the live
1832
+ * {@link TerminalManagerInterface} (`@orkestrel/terminal`) to `ask` through, the terminal name
1833
+ * `from`, and the advertised tool overrides.
1834
+ *
1835
+ * @remarks
1836
+ * - `manager` — the terminal manager whose `ask(from, to, form, options)` the tool's handler
1837
+ * calls; BLOCKS the calling agent turn until the addressed terminal answers (or the ask
1838
+ * rejects — a cycle throws `TerminalError('DEADLOCK')`, re-surfaced as a typed `DEADLOCK`
1839
+ * {@link import('./errors.js').ToolboxError}; an expired prompt re-surfaces as `EXPIRE`).
1840
+ * - `from` — the terminal identity this tool asks AS; the model supplies the `to` target and the
1841
+ * prompt form per call.
1842
+ * - `name` / `description` — advertised tool overrides; default to
1843
+ * {@link import('./constants.js').PROMPT_TOOL_NAME} / {@link import('./constants.js').PROMPT_TOOL_DESCRIPTION}.
1844
+ */
1845
+ export declare interface PromptToolOptions {
1846
+ readonly manager: TerminalManagerInterface;
1847
+ readonly from: string;
1848
+ readonly name?: string;
1849
+ readonly description?: string;
1850
+ }
1851
+
1852
+ /**
1853
+ * The shape of {@link import('./factories.js').createPromptTool}'s call arguments — `to` (the
1854
+ * terminal identity to address), `form` (which of the six {@link import('@orkestrel/terminal').PromptType}
1855
+ * forms to ask), `message`, an optional `timeout` override, and every per-form optional field
1856
+ * FLATTENED onto one object (mirrors `workspaceToolShape`'s flat-arm style, but a single shared
1857
+ * shape rather than a discriminated union — `form` alone does not vary the REQUIRED fields, only
1858
+ * which of the optional ones apply, so a flat shape stays faithful without duplicating `to` /
1859
+ * `message` / `timeout` across six near-identical arms).
1860
+ *
1861
+ * @remarks
1862
+ * `choices` backs `'select'` / `'checkbox'`; `default` backs `'input'` / `'confirm'` / `'select'`
1863
+ * (a string for the first two forms' text default, `'true'`/`'false'` string for confirm — the
1864
+ * contract layer cannot vary a field's type by a sibling field's value, so `default` stays a
1865
+ * string and the handler coerces per form); `mask` backs `'password'`; `min` / `max` backs
1866
+ * `'checkbox'`; `validate` (declarative only) backs the four text-shaped forms
1867
+ * (`'input'` / `'password'` / `'confirm'` / `'editor'`).
1868
+ */
1869
+ export declare const promptToolShape: ObjectShape<{
1870
+ to: StringShape;
1871
+ form: LiteralShape<readonly ["input", "password", "confirm", "select", "checkbox", "editor"]>;
1872
+ message: StringShape;
1873
+ default: OptionalShape<StringShape>;
1874
+ choices: OptionalShape<ArrayShape<ObjectShape<{
1875
+ name: StringShape;
1876
+ value: StringShape;
1877
+ description: OptionalShape<StringShape>;
1878
+ }, boolean | ContractShape>>>;
1879
+ mask: OptionalShape<StringShape>;
1880
+ min: OptionalShape<NumberShape>;
1881
+ max: OptionalShape<NumberShape>;
1882
+ validate: OptionalShape<ObjectShape<{
1883
+ required: OptionalShape<BooleanShape>;
1884
+ minimum: OptionalShape<NumberShape>;
1885
+ maximum: OptionalShape<NumberShape>;
1886
+ pattern: OptionalShape<StringShape>;
1887
+ email: OptionalShape<BooleanShape>;
1888
+ url: OptionalShape<BooleanShape>;
1889
+ numeric: OptionalShape<BooleanShape>;
1890
+ integer: OptionalShape<BooleanShape>;
1891
+ alphanumeric: OptionalShape<BooleanShape>;
1892
+ }, boolean | ContractShape>>;
1893
+ timeout: OptionalShape<NumberShape>;
1894
+ }, false>;
1895
+
1896
+ /** The default cap on how many `include` path segments deep a `load` / `find` call may traverse — the relation tool's default include-depth ceiling. */
1897
+ export declare const RELATION_TOOL_DEPTH = 3;
1898
+
1899
+ /**
1900
+ * The DESCRIPTION the relation tool advertises — a multi-line guide that teaches a small model
1901
+ * the operation list and the flat dot-path `include` syntax.
1902
+ *
1903
+ * @remarks
1904
+ * An include path is a FLAT dot-separated string (`'contacts.account'`), never a nested object —
1905
+ * the same small-model ergonomic lever the other tools in this package use for flat args.
1906
+ */
1907
+ export declare const RELATION_TOOL_DESCRIPTION: string;
1908
+
1909
+ /** The default cap on rows a `find` / `links` call returns when the caller omits `limit` — the relation tool's default row ceiling. */
1910
+ export declare const RELATION_TOOL_LIMIT = 1000;
1911
+
1912
+ /**
1913
+ * The name `createRelationTool` advertises by default — the key a model calls and the
1914
+ * `ToolManagerInterface` (`@orkestrel/tool`) registers under.
1915
+ */
1916
+ export declare const RELATION_TOOL_NAME = "relation";
1917
+
1918
+ /**
1919
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} the relation tool advertises
1920
+ * in place of {@link RELATION_TOOL_DESCRIPTION}.
1921
+ */
1922
+ export declare const RELATION_TOOL_SUMMARY = "Traverse and edit relationships between database rows \u2014 one operation per call (load, find, link, unlink, links), chosen by the 'operation' field. Call describe('relation') for the include-path syntax.";
1923
+
1924
+ /** One key value — a string or number; the array form (multiple keys, positional) resolves FIRST per AGENTS §9.2. */
1925
+ export declare const relationKeyShape: UnionShape<readonly [ ArrayShape<UnionShape<readonly [ StringShape, NumberShape]>>, StringShape, NumberShape]>;
1926
+
1927
+ /**
1928
+ * Resolve which registered {@link RelationManagerInterface} a relation-tool call addresses — the
1929
+ * pure manager-resolution leaf {@link import('./factories.js').createRelationTool} calls on
1930
+ * every operation.
1931
+ *
1932
+ * @remarks
1933
+ * An explicit `name` must match a key of `managers` (a miss throws a typed `TOOL`
1934
+ * {@link ToolboxError} naming the registered managers). An OMITTED `name` resolves to the sole
1935
+ * registered manager when exactly one is registered, else throws the same typed error.
1936
+ *
1937
+ * @param managers - The tool's registered `RelationManagerInterface` map
1938
+ * @param name - The call's optional `manager` field
1939
+ * @returns The resolved {@link RelationManagerInterface}
1940
+ */
1941
+ export declare function relationManagerOf(managers: Readonly<Record<string, RelationManagerInterface>>, name: string | undefined): RelationManagerInterface;
1942
+
1943
+ /**
1944
+ * Resolve a `model` name against a live {@link RelationManagerInterface} — the pure model-lookup
1945
+ * leaf {@link import('./factories.js').createRelationTool} calls on every operation, mirroring
1946
+ * {@link relationManagerOf}'s guard shape.
1947
+ *
1948
+ * @param manager - The resolved {@link RelationManagerInterface}
1949
+ * @param name - The call's `model` field
1950
+ * @returns The model's {@link ModelInterface}
1951
+ */
1952
+ export declare function relationModelOf(manager: RelationManagerInterface, name: string): ModelInterface;
1953
+
1954
+ /**
1955
+ * Map a caught error to the {@link ToolboxErrorCode} the upcoming relation tool should throw
1956
+ * with — the pure classification step of that factory's error handling, mirroring
1957
+ * {@link terminalToolCode}'s idiom for `@orkestrel/relation`.
1958
+ *
1959
+ * @param error - The value caught from a `@orkestrel/relation` operation
1960
+ * @returns The granular {@link RelationErrorCode}, or `undefined` if `error` is not a `RelationError`
1961
+ */
1962
+ export declare function relationToolCode(error: unknown): RelationErrorCode | undefined;
1963
+
1964
+ /**
1965
+ * Options for {@link import('./factories.js').createRelationTool} — SRC-3 (the final unit) of
1966
+ * the 3-unit database / relation spine.
1967
+ *
1968
+ * @remarks
1969
+ * - `managers` — the live `RelationManagerInterface` (`@orkestrel/relation`) registry a call's
1970
+ * optional `manager` field addresses by name; REQUIRED (unlike the database tool's lazily
1971
+ * resolved handles, a relation manager's relations are declared up front and cannot be minted
1972
+ * on demand from a tool call). A call that omits `manager` resolves to the SOLE registered
1973
+ * manager when exactly one is registered, else throws a typed `TOOL`
1974
+ * {@link import('./errors.js').ToolboxError} naming the registered manager keys.
1975
+ * - `limit` — the row cap `'find'` / `'links'` enforce when a call's `limit` is omitted or
1976
+ * exceeds it. Defaults to {@link import('./constants.js').RELATION_TOOL_LIMIT}.
1977
+ * - `depth` — the max dot-path segment count `'load'` / `'find'`'s `include` paths may reach
1978
+ * ({@link import('./helpers.js').expandInclude}). Defaults to
1979
+ * {@link import('./constants.js').RELATION_TOOL_DEPTH}.
1980
+ * - `name` / `description` — advertised tool overrides; default to
1981
+ * {@link import('./constants.js').RELATION_TOOL_NAME} / {@link import('./constants.js').RELATION_TOOL_DESCRIPTION}.
1982
+ */
1983
+ export declare interface RelationToolOptions {
1984
+ readonly name?: string;
1985
+ readonly description?: string;
1986
+ readonly managers: Readonly<Record<string, RelationManagerInterface>>;
1987
+ readonly limit?: number;
1988
+ readonly depth?: number;
1989
+ }
1990
+
1991
+ /**
1992
+ * The shape of {@link import('./factories.js').createRelationTool}'s call arguments —
1993
+ * discriminated by `operation` into the 5 relation operations (`'load'` / `'find'` / `'link'` /
1994
+ * `'unlink'` / `'links'`).
1995
+ *
1996
+ * @remarks
1997
+ * `'load'` fetches one or more rows (positional key/array) with `include` attached. `'find'`
1998
+ * fetches rows (pagination / sort only) with `include` attached. `'link'` / `'unlink'` write /
1999
+ * remove a `through` junction row; `'links'` lists a `through` relation's linked keys.
2000
+ */
2001
+ export declare const relationToolShape: UnionShape<readonly [ ObjectShape<{
2002
+ operation: LiteralShape<readonly ["load"]>;
2003
+ manager: OptionalShape<StringShape>;
2004
+ model: StringShape;
2005
+ key: UnionShape<readonly [ ArrayShape<UnionShape<readonly [ StringShape, NumberShape]>>, StringShape, NumberShape]>;
2006
+ include: OptionalShape<ArrayShape<StringShape>>;
2007
+ }, false>, ObjectShape<{
2008
+ operation: LiteralShape<readonly ["find"]>;
2009
+ manager: OptionalShape<StringShape>;
2010
+ model: StringShape;
2011
+ include: OptionalShape<ArrayShape<StringShape>>;
2012
+ limit: OptionalShape<NumberShape>;
2013
+ offset: OptionalShape<NumberShape>;
2014
+ sort: OptionalShape<StringShape>;
2015
+ direction: OptionalShape<LiteralShape<readonly ["ascending", "descending"]>>;
2016
+ }, false>, ObjectShape<{
2017
+ operation: LiteralShape<readonly ["link"]>;
2018
+ manager: OptionalShape<StringShape>;
2019
+ model: StringShape;
2020
+ key: UnionShape<readonly [ StringShape, NumberShape]>;
2021
+ relation: StringShape;
2022
+ target: UnionShape<readonly [ StringShape, NumberShape]>;
2023
+ }, false>, ObjectShape<{
2024
+ operation: LiteralShape<readonly ["unlink"]>;
2025
+ manager: OptionalShape<StringShape>;
2026
+ model: StringShape;
2027
+ key: UnionShape<readonly [ StringShape, NumberShape]>;
2028
+ relation: StringShape;
2029
+ target: UnionShape<readonly [ StringShape, NumberShape]>;
2030
+ }, false>, ObjectShape<{
2031
+ operation: LiteralShape<readonly ["links"]>;
2032
+ manager: OptionalShape<StringShape>;
2033
+ model: StringShape;
2034
+ key: UnionShape<readonly [ StringShape, NumberShape]>;
2035
+ relation: StringShape;
2036
+ }, false>]>;
2037
+
2038
+ /** A loose row — a flat object of column name to JSON value; the array form (multiple rows) resolves FIRST per AGENTS §9.2. */
2039
+ export declare const rowShape: ObjectShape<Record<never, never>, JSONShape>;
2040
+
2041
+ /** One or many loose rows — the array form resolves FIRST per AGENTS §9.2. */
2042
+ export declare const rowsShape: UnionShape<readonly [ ArrayShape<ObjectShape<Record<never, never>, JSONShape>>, ObjectShape<Record<never, never>, JSONShape>]>;
2043
+
2044
+ /** A single row key (not an array) — used by `'link'` / `'unlink'` / `'links'`, which address exactly one owning row. */
2045
+ export declare const singleKeyShape: UnionShape<readonly [ StringShape, NumberShape]>;
2046
+
2047
+ /**
2048
+ * The shape of ONE flat step — `{ name }` — the building block of {@link workflowStepsShape}.
2049
+ *
2050
+ * @remarks
2051
+ * `name` is the REGISTERED behavior name the step runs (it becomes the task's `run`). The tool
2052
+ * expands each step into a one-task phase, in order ({@link import('./helpers.js').expandSteps}).
2053
+ */
2054
+ export declare const stepShape: ObjectShape<{
2055
+ name: StringShape;
2056
+ }, false>;
2057
+
2058
+ /**
2059
+ * Build one {@link TableSchema} from a table NAME and its `@orkestrel/database` `TableExport` —
2060
+ * the "deployed" schema shape `DatabaseInterface.migrate` diffs against, derived from a LIVE
2061
+ * handle's `export()` rather than a re-declared {@link TableSpec}, so it works for ANY handle
2062
+ * (config-tracked or caller-supplied).
2063
+ *
2064
+ * @param name - The table name
2065
+ * @param table - The table's `TableExport` (`{ key, columns }`, `@orkestrel/database`)
2066
+ * @returns The equivalent {@link TableSchema} (`indexes` empty — this package declares none)
2067
+ */
2068
+ export declare function tableSchema(name: string, table: Readonly<{
2069
+ key: string;
2070
+ columns: Readonly<Record<string, ContractShape>>;
2071
+ }>): TableSchema;
2072
+
2073
+ /**
2074
+ * A database's table layout — one entry per table, each a flat map of column name to
2075
+ * {@link ColumnSpec}. The small-model-facing DSL {@link import('./helpers.js').expandTables}
2076
+ * compiles into an `@orkestrel/database` `TablesShape`.
2077
+ */
2078
+ export declare type TableSpec = Readonly<Record<string, Readonly<{
2079
+ columns: Readonly<Record<string, ColumnSpec>>;
2080
+ }>>>;
2081
+
2082
+ /** A {@link import('./types.js').TableSpec} — table name to `{ columns }`, each column a {@link columnSpecShape}. */
2083
+ export declare const tableSpecShape: ObjectShape<Record<never, never>, ObjectShape<{
2084
+ columns: ObjectShape<Record<never, never>, UnionShape<readonly [ LiteralShape<readonly ["string", "integer", "number", "boolean"]>, ObjectShape<{
2085
+ type: LiteralShape<readonly ["string", "integer", "number", "boolean"]>;
2086
+ optional: OptionalShape<BooleanShape>;
2087
+ }, false>]>>;
2088
+ }, false>>;
2089
+
2090
+ /**
2091
+ * A draft task — a `TaskDefinition` (`@orkestrel/workflow`) with OPTIONAL `id` / `name`.
2092
+ *
2093
+ * @remarks
2094
+ * The tool synthesizes a missing `id` positionally and defaults a missing `name` to its `id`
2095
+ * ({@link import('./helpers.js').completeDraft}). A PROVIDED `id` / `name` is preserved verbatim
2096
+ * (and must be non-empty — the draft contract's `minLength: 1`).
2097
+ */
2098
+ export declare interface TaskDraft {
2099
+ readonly id?: string;
2100
+ readonly name?: string;
2101
+ readonly description?: string;
2102
+ /** The behavior reference — a registry key resolved against a workflow's functions registry at construction; omitted ⇒ no handler. */
2103
+ readonly run?: string;
2104
+ /** Extra attempts after the first on failure (a non-negative integer); overrides the phase Runner default. Execution-only. */
2105
+ readonly retries?: number;
2106
+ /** The per-attempt deadline in milliseconds (a non-negative integer); overrides the phase Runner default. Execution-only. */
2107
+ readonly timeout?: number;
2108
+ }
2109
+
2110
+ /**
2111
+ * The shape of a {@link import('./types.js').TaskDraft} — identical to a strict task shape
2112
+ * EXCEPT `id` and `name` are OPTIONAL.
2113
+ */
2114
+ export declare const taskDraftShape: ObjectShape<{
2115
+ id: OptionalShape<StringShape>;
2116
+ name: OptionalShape<StringShape>;
2117
+ description: OptionalShape<StringShape>;
2118
+ run: OptionalShape<StringShape>;
2119
+ retries: OptionalShape<NumberShape>;
2120
+ timeout: OptionalShape<NumberShape>;
2121
+ }, false>;
2122
+
2123
+ /**
2124
+ * Map a caught error to the {@link ToolboxErrorCode} the terminal-tool factory should throw
2125
+ * with — the pure classification step of that factory's error handling.
2126
+ *
2127
+ * @remarks
2128
+ * Narrows `error` with {@link isTerminalError} (`@orkestrel/terminal`) first: a non-`TerminalError`
2129
+ * value returns `undefined`, telling the caller this mapper does not apply (rethrow / handle
2130
+ * otherwise). For a genuine `TerminalError`, `'DEADLOCK'` maps to `'DEADLOCK'`, `'EXPIRE'` maps
2131
+ * to `'EXPIRE'`, and every other {@link import('@orkestrel/terminal').TerminalErrorCode}
2132
+ * (`'TARGET'`, `'CANCEL'`, `'DRIVER'`) maps to the generic `'TOOL'` code. The mapper only
2133
+ * classifies — the factory performs the actual throw.
2134
+ *
2135
+ * @param error - The value caught from a terminal-manager operation (`ask` / `answer` / …)
2136
+ * @returns The mapped {@link ToolboxErrorCode}, or `undefined` if `error` is not a `TerminalError`
2137
+ */
2138
+ export declare function terminalToolCode(error: unknown): ToolboxErrorCode | undefined;
2139
+
2140
+ /**
2141
+ * Thrown by {@link import('./factories.js').createAgentTool}'s and
2142
+ * {@link import('./factories.js').createDescribeTool}'s handlers on every failure path — a
2143
+ * malformed / unresolvable call or an unknown tool name (`TOOL`), a delegation that would
2144
+ * exceed the configured depth bound or re-enter an ancestor (`DEPTH`), a prompt cycle
2145
+ * (`DEADLOCK`), a prompt that expired before it was answered (`EXPIRE`), or an answer that
2146
+ * failed to apply (`ANSWER`) — the last three thrown by
2147
+ * {@link import('./factories.js').createPromptTool} / {@link import('./factories.js').createAnswerTool}.
2148
+ *
2149
+ * @remarks
2150
+ * Carries a machine-readable `code` (see {@link import('./types.js').ToolboxErrorCode}) and
2151
+ * an optional `context` bag for structured diagnostics. They are readable through an in-process
2152
+ * catch, including around a direct `tool.execute(args)` call. The `ToolManagerInterface`
2153
+ * (`@orkestrel/tool`) instead flattens every throw to the canonical tool result's top-level
2154
+ * `error` message string under AGENTS' “narrow untrusted input with guards” rule.
2155
+ *
2156
+ * @example
2157
+ * ```ts
2158
+ * import { ToolboxError, isToolboxError } from '@src/core'
2159
+ *
2160
+ * try {
2161
+ * throw new ToolboxError('TOOL', 'task is required')
2162
+ * } catch (error) {
2163
+ * if (isToolboxError(error)) console.log(error.code) // 'TOOL'
2164
+ * }
2165
+ * ```
2166
+ */
2167
+ export declare class ToolboxError extends Error {
2168
+ readonly code: ToolboxErrorCode;
2169
+ readonly context?: Readonly<Record<string, unknown>>;
2170
+ constructor(code: ToolboxErrorCode, message: string, context?: Readonly<Record<string, unknown>>);
2171
+ }
2172
+
2173
+ /**
2174
+ * The seven-value machine-readable code a thrown
2175
+ * {@link import('./errors.js').ToolboxError} carries (AGENTS §14: a thrown, typed,
2176
+ * code-bearing error, never a `{ error }` return).
2177
+ *
2178
+ * @remarks
2179
+ * `TOOL` — malformed calls and package-owned resolution or configuration failures, including
2180
+ * unknown tools, terminals, databases, drivers, relation managers, or models; invalid prompt
2181
+ * choices or include paths; disabled readonly mutations; and invalid infer/endpoint inputs.
2182
+ * `DEPTH` — the delegation would exceed {@link import('./constants.js').AGENT_TOOL_DEPTH}, or
2183
+ * the resolved agent is already an ancestor (a cycle).
2184
+ * `DEADLOCK` — an `ask` call ({@link import('./factories.js').createPromptTool}) would form a
2185
+ * prompt cycle (`TerminalManagerInterface.ask`, `@orkestrel/terminal`, rejects with its own
2186
+ * `TerminalError('DEADLOCK')`, re-surfaced here).
2187
+ * `EXPIRE` — an `ask` call's addressed prompt expired before it was answered.
2188
+ * `ANSWER` — {@link import('./factories.js').createAnswerTool}'s answer call failed to apply
2189
+ * because the prompt id is unknown or already settled, or the terminal manager rejected the
2190
+ * answer.
2191
+ * `DATABASE` — a typed `@orkestrel/database` failure (`DatabaseError`), re-surfaced with the
2192
+ * granular {@link import('@orkestrel/database').DatabaseErrorCode} carried in `context.code`.
2193
+ * `RELATION` — a typed `@orkestrel/relation` failure (`RelationError`), re-surfaced with the
2194
+ * granular {@link import('@orkestrel/relation').RelationErrorCode} carried in `context.code`.
2195
+ */
2196
+ export declare type ToolboxErrorCode = 'TOOL' | 'DEPTH' | 'DEADLOCK' | 'EXPIRE' | 'ANSWER' | 'DATABASE' | 'RELATION';
2197
+
2198
+ export declare const WORKFLOW_TOOL_DESCRIPTION: string;
2199
+
2200
+ /**
2201
+ * A complete FLAT authoring example — the PRIMARY way a small model authors a workflow through
2202
+ * {@link import('./factories.js').createWorkflowTool}: `{ name, steps: [{ name }] }`.
2203
+ *
2204
+ * @remarks
2205
+ * OWNED here now (ported from `@orkestrel/workflow`). Each step becomes a one-task phase, in
2206
+ * order; a step's `name` is a REGISTERED behavior name (not a label) — the registry key its
2207
+ * task's `run` resolves against. The tool expands this
2208
+ * ({@link import('./helpers.js').expandSteps}) into a valid `WorkflowDefinition`
2209
+ * (`@orkestrel/workflow`). It is embedded VERBATIM in {@link WORKFLOW_TOOL_DESCRIPTION}.
2210
+ */
2211
+ export declare const WORKFLOW_TOOL_FLAT_EXAMPLE: WorkflowSteps;
2212
+
2213
+ /**
2214
+ * The name {@link import('./factories.js').createWorkflowTool} advertises by default — the key a
2215
+ * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under, and the name
2216
+ * {@link import('./factories.js').createAgentFunction} binds the depth/cycle-aware workflow tool
2217
+ * under onto a wrapped agent's `context.tools`.
2218
+ *
2219
+ * @remarks
2220
+ * OWNED here now (ported from `@orkestrel/workflow`). The propagation seam's well-known key: when
2221
+ * `createAgentFunction`'s `runner` option is supplied, it adds a `createWorkflowTool`-built tool
2222
+ * under this name to the agent's `context.tools`, so it can author + run a NESTED workflow
2223
+ * (bounded by {@link MAX_WORKFLOW_DEPTH}).
2224
+ */
2225
+ export declare const WORKFLOW_TOOL_NAME = "workflow";
2226
+
2227
+ /**
2228
+ * A minimal NESTED authoring example — the ADVANCED escape-hatch form a model may use instead of
2229
+ * the flat shape: a full `WorkflowDefinition` (`@orkestrel/workflow`).
2230
+ *
2231
+ * @remarks
2232
+ * OWNED here now (ported from `@orkestrel/workflow`). The full four-level form, documented in
2233
+ * {@link WORKFLOW_TOOL_DESCRIPTION} as the advanced alternative. It is embedded VERBATIM.
2234
+ */
2235
+ export declare const WORKFLOW_TOOL_NESTED_EXAMPLE: WorkflowDefinition;
2236
+
2237
+ /**
2238
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createWorkflowTool}
2239
+ * advertises in place of {@link WORKFLOW_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
2240
+ * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
2241
+ * for the full teaching description; the full text stays retrievable via
2242
+ * {@link import('./factories.js').createDescribeTool}.
2243
+ */
2244
+ 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.";
2245
+
2246
+ /**
2247
+ * A draft workflow — a `WorkflowDefinition` (`@orkestrel/workflow`) with OPTIONAL `id` / `name`
2248
+ * at all three levels (workflow / phase / task).
2249
+ *
2250
+ * @remarks
2251
+ * The lenient authoring form {@link import('./factories.js').createWorkflowDraftContract}
2252
+ * validates and {@link import('./helpers.js').completeDraft} completes into a strict
2253
+ * `WorkflowDefinition`. `run` stays optional (a plain name string); the `bail` policy carries
2254
+ * over.
2255
+ */
2256
+ export declare interface WorkflowDraft {
2257
+ readonly id?: string;
2258
+ readonly name?: string;
2259
+ readonly description?: string;
2260
+ readonly phases: readonly PhaseDraft[];
2261
+ /** Failure policy: `false` (default) continues gracefully, `true` halts on the first failure. */
2262
+ readonly bail?: boolean;
2263
+ }
2264
+
2265
+ /**
2266
+ * The shape of a DRAFT workflow — identical to a strict workflow shape EXCEPT `id` and `name`
2267
+ * are OPTIONAL at all three levels (workflow / phase / task), so a small model can omit the six
2268
+ * identity strings and let the tool synthesize them positionally.
2269
+ *
2270
+ * @remarks
2271
+ * The lenient counterpart {@link import('./factories.js').createWorkflowDraftContract} compiles.
2272
+ * `run` stays required on the strict form; a provided `id` / `name` still has `minLength: 1` (so
2273
+ * an explicitly-empty `id: ''` is REJECTED, not auto-filled). After
2274
+ * {@link import('./helpers.js').completeDraft} fills the missing ids/names, the result is
2275
+ * validated against the STRICT `createWorkflowContract` (`@orkestrel/workflow`) gate before
2276
+ * running.
2277
+ */
2278
+ export declare const workflowDraftShape: ObjectShape<{
2279
+ id: OptionalShape<StringShape>;
2280
+ name: OptionalShape<StringShape>;
2281
+ description: OptionalShape<StringShape>;
2282
+ phases: ArrayShape<ObjectShape<{
2283
+ id: OptionalShape<StringShape>;
2284
+ name: OptionalShape<StringShape>;
2285
+ description: OptionalShape<StringShape>;
2286
+ tasks: ArrayShape<ObjectShape<{
2287
+ id: OptionalShape<StringShape>;
2288
+ name: OptionalShape<StringShape>;
2289
+ description: OptionalShape<StringShape>;
2290
+ run: OptionalShape<StringShape>;
2291
+ retries: OptionalShape<NumberShape>;
2292
+ timeout: OptionalShape<NumberShape>;
2293
+ }, false>>;
2294
+ concurrency: OptionalShape<NumberShape>;
2295
+ bail: OptionalShape<LiteralShape<readonly [true, false]>>;
2296
+ }, false>>;
2297
+ bail: OptionalShape<LiteralShape<readonly [true, false]>>;
2298
+ }, false>;
2299
+
2300
+ /**
2301
+ * One flat step — `{ name }` — the building block of a {@link WorkflowSteps} blob.
2302
+ *
2303
+ * @remarks
2304
+ * `name` is the REGISTERED behavior name the step runs (it becomes the task's `run`, NOT a
2305
+ * human label) — resolved against a workflow-level functions registry at construction.
2306
+ */
2307
+ export declare interface WorkflowStep {
2308
+ /** The registered behavior name this step runs (becomes the task's `run`). */
2309
+ readonly name: string;
2310
+ }
2311
+
2312
+ /**
2313
+ * The FLAT authoring blob {@link import('./factories.js').createWorkflowTool} advertises —
2314
+ * `{ name?, steps }` — the simplest surface a small model can fill.
2315
+ *
2316
+ * @remarks
2317
+ * Each {@link WorkflowStep} becomes a one-task phase, in order
2318
+ * ({@link import('./helpers.js').expandSteps}); `name` is the optional workflow name (defaulted
2319
+ * when omitted).
2320
+ */
2321
+ export declare interface WorkflowSteps {
2322
+ readonly name?: string;
2323
+ readonly steps: readonly WorkflowStep[];
2324
+ }
2325
+
2326
+ /**
2327
+ * The FLAT authoring shape {@link import('./factories.js').createWorkflowTool} advertises as its
2328
+ * `parameters` — the simplest surface a small model can fill: `{ name?, steps: [{ name }] }`.
2329
+ *
2330
+ * @remarks
2331
+ * A deliberately-reduced surface: a flat ordered list of steps, each a `{ name }`. The tool
2332
+ * EXPANDS it ({@link import('./helpers.js').expandSteps}) into a full
2333
+ * {@link import('./types.js').WorkflowDefinition} — one one-task phase per step, in order —
2334
+ * then validates against the STRICT `createWorkflowContract` (`@orkestrel/workflow`) gate. The
2335
+ * full nested form is STILL accepted by the tool (it branches on the args' shape) and is
2336
+ * documented as the advanced escape-hatch in the tool's description — but THIS is what
2337
+ * `parameters` advertises.
2338
+ */
2339
+ export declare const workflowStepsShape: ObjectShape<{
2340
+ name: OptionalShape<StringShape>;
2341
+ steps: ArrayShape<ObjectShape<{
2342
+ name: StringShape;
2343
+ }, false>>;
2344
+ }, false>;
2345
+
2346
+ /**
2347
+ * The ancestry identifier of a workflow in a run chain — `workflow:<id>`.
2348
+ *
2349
+ * @remarks
2350
+ * Namespacing keeps a workflow id and an {@link agentTag} agent name in ONE set without
2351
+ * collision, so re-entering a workflow OR an agent already in the chain is a single `includes`
2352
+ * check.
2353
+ *
2354
+ * @param id - The workflow definition's `id`
2355
+ * @returns The namespaced ancestry tag (`workflow:<id>`)
2356
+ */
2357
+ export declare function workflowTag(id: string): string;
2358
+
2359
+ /**
2360
+ * Options for {@link import('./factories.js').createWorkflowTool} — the depth + ancestry a
2361
+ * nested workflow run is bound at, plus the optional durable {@link WorkflowStoreInterface}
2362
+ * (`@orkestrel/workflow`) this package layers on top of the ported handler logic.
2363
+ *
2364
+ * @remarks
2365
+ * This is the PROPAGATION carrier across the agent/tool boundary. A `Tool`'s handler receives
2366
+ * ONLY the model-supplied `args` (no ambient context, no signal — see `@orkestrel/tool`'s
2367
+ * `ToolOptions`), so the run's position in the workflow→agent→workflow chain CANNOT be threaded
2368
+ * through a tool call at runtime. Instead {@link import('./factories.js').createAgentFunction}
2369
+ * CLOSES `depth` / `ancestry` over the tool at BIND time. Both are OPTIONAL: a workflow tool
2370
+ * built for a TOP-LEVEL caller omits them — its nested run starts the chain at depth `1` with
2371
+ * the bare `workflow:<id>` ancestry.
2372
+ *
2373
+ * `store` is this package's ADDITION: when supplied, the tool's handler persists the run's final
2374
+ * snapshot (`store.set(result.workflow.snapshot())`) once the run settles, so a workflow
2375
+ * authored + run through the tool is retrievable / restorable afterwards. Omitted ⇒ no
2376
+ * persistence.
2377
+ */
2378
+ export declare interface WorkflowToolOptions {
2379
+ /** The depth the INVOKING agent runs at; the nested workflow runs at `depth + 1`. Default `0`. */
2380
+ readonly depth?: number;
2381
+ /** The ancestry of the invoking run; the nested run extends it with its own `workflow:<id>`. Default empty. */
2382
+ readonly ancestry?: readonly string[];
2383
+ readonly store?: WorkflowStoreInterface;
2384
+ }
2385
+
2386
+ /**
2387
+ * Build the plain success summary {@link import('./factories.js').createWorkflowTool} returns on
2388
+ * a completed run — the universal tool-handler contract (AGENTS §14): return a plain value on
2389
+ * success, appearing identically over BOTH the agent loop and MCP.
2390
+ *
2391
+ * @remarks
2392
+ * The summary is LEAN: the workflow's terminal `status` and the COUNT of settled task results —
2393
+ * enough for a caller / model to react without serializing the whole live tree. (It carries no
2394
+ * synthetic `id` / `name`: a tool handler has no call id; the `ToolManagerInterface`
2395
+ * (`@orkestrel/tool`) supplies the canonical envelope's identity.)
2396
+ *
2397
+ * @param result - The terminal `WorkflowResult` (`@orkestrel/workflow`) the run produced
2398
+ * @returns The plain success summary — `{ status, count }`
2399
+ */
2400
+ export declare function workflowToolSummary(result: WorkflowResult): Readonly<{
2401
+ status: WorkflowStatus;
2402
+ count: number;
2403
+ }>;
2404
+
2405
+ export declare const WORKSPACE_TOOL_DESCRIPTION: string;
2406
+
2407
+ /**
2408
+ * A valid {@link import('./types.js').WorkspaceOperation} object — the canonical example embedded
2409
+ * VERBATIM in {@link WORKSPACE_TOOL_DESCRIPTION}.
2410
+ *
2411
+ * @remarks
2412
+ * OWNED here now (ported from `@orkestrel/agent`). A `'write'` op (the most common authoring
2413
+ * action): create or overwrite `notes.txt` with `hello`. Frozen so it cannot be mutated in
2414
+ * place.
2415
+ */
2416
+ export declare const WORKSPACE_TOOL_EXAMPLE: WorkspaceOperation;
2417
+
2418
+ /**
2419
+ * The name {@link import('./factories.js').createWorkspaceTool} advertises by default — the key a
2420
+ * model calls and the `ToolManagerInterface` (`@orkestrel/tool`) registers under.
2421
+ *
2422
+ * @remarks
2423
+ * OWNED here now (ported from `@orkestrel/agent`).
2424
+ */
2425
+ export declare const WORKSPACE_TOOL_NAME = "workspace";
2426
+
2427
+ /**
2428
+ * The lean {@link import('@orkestrel/tool').ToolInterface.summary} {@link import('./factories.js').createWorkspaceTool}
2429
+ * advertises in place of {@link WORKSPACE_TOOL_DESCRIPTION} — a `ToolManagerInterface.definitions()`
2430
+ * (`@orkestrel/tool`) advertises `summary ?? description`, so this one-sentence text stands in
2431
+ * for the full teaching description; the full text stays retrievable via
2432
+ * {@link import('./factories.js').createDescribeTool}.
2433
+ */
2434
+ 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.";
2435
+
2436
+ /**
2437
+ * One operation an agent invokes through {@link import('./factories.js').createWorkspaceTool} — a
2438
+ * FLAT, descriptive tagged union over the 13 workspace edit / read / navigation actions,
2439
+ * discriminated by the `operation` literal (AGENTS §4.8: a discriminant is named for its axis —
2440
+ * the action being performed — NEVER `kind`).
2441
+ *
2442
+ * @remarks
2443
+ * This is the SOURCE OF TRUTH the tool contract is typed to
2444
+ * ({@link import('./shapers.js').workspaceToolShape} compiles to a structurally-identical guard /
2445
+ * parser / JSON Schema). Every field is FLAT (no nested objects) — the small-model ergonomic
2446
+ * lever: a range edit is the four flat integers of the `'splice'` arm (`fromLine` /
2447
+ * `fromColumn` / `toLine` / `toColumn`), reassembled into a 1-based `Range` (`@orkestrel/agent`)
2448
+ * by `rangeOf`, never a nested `{ start, end }`. Each EDIT / READ arm maps onto exactly one
2449
+ * `WorkspaceInterface` call against the manager's ACTIVE workspace; the two REGISTRY arms
2450
+ * (`switch` / `workspaces`) drive the {@link WorkspaceManagerInterface} pointer instead —
2451
+ * `workspaces` LISTS the workspaces the model can move between, and `switch` re-points which one
2452
+ * the edit / read arms target.
2453
+ */
2454
+ export declare type WorkspaceOperation =
2455
+ /** Read a whole text file's text by `path` from the ACTIVE workspace (a binary / absent path — or no active workspace — yields no content). */
2456
+ {
2457
+ readonly operation: 'read';
2458
+ readonly path: string;
2459
+ }
2460
+ /** List every file in the ACTIVE workspace (path / state / size / lines / kind summaries); `[]` when no workspace is active. */
2461
+ | {
2462
+ readonly operation: 'list';
2463
+ }
2464
+ /** Whether a file exists at `path` in the ACTIVE workspace (`false` when no workspace is active). */
2465
+ | {
2466
+ readonly operation: 'has';
2467
+ readonly path: string;
2468
+ }
2469
+ /**
2470
+ * Scan every text file for `query`, returning each hit (path + 1-based line / column + the line).
2471
+ *
2472
+ * @remarks
2473
+ * `regex` treats `query` as a regular-expression source (default `false` — a literal substring);
2474
+ * `exact` matches case-sensitively (default `true`); `limit` caps the total hits returned.
2475
+ */
2476
+ | {
2477
+ readonly operation: 'search';
2478
+ readonly query: string;
2479
+ readonly regex?: boolean;
2480
+ readonly exact?: boolean;
2481
+ readonly limit?: number;
2482
+ }
2483
+ /**
2484
+ * Replace `query` with `replacement` across every text file, returning the tally.
2485
+ *
2486
+ * @remarks
2487
+ * Same matching axes as `search`: `regex` (default `false`), `exact` (default `true`), `limit`
2488
+ * (cap the total replacements).
2489
+ */
2490
+ | {
2491
+ readonly operation: 'replace';
2492
+ readonly query: string;
2493
+ readonly replacement: string;
2494
+ readonly regex?: boolean;
2495
+ readonly exact?: boolean;
2496
+ readonly limit?: number;
2497
+ }
2498
+ /** Write (create or overwrite) the whole file at `path` with `content`. */
2499
+ | {
2500
+ readonly operation: 'write';
2501
+ readonly path: string;
2502
+ readonly content: string;
2503
+ }
2504
+ /**
2505
+ * Splice `content` into an existing text file, replacing the 1-based range
2506
+ * `(fromLine, fromColumn)` (INCLUSIVE) → `(toLine, toColumn)` (EXCLUSIVE).
2507
+ *
2508
+ * @remarks
2509
+ * The FLAT range edit — the four positive-integer caret components reassemble into a `Range`
2510
+ * (`@orkestrel/agent`) via `rangeOf`. An empty span (`from === to`) inserts; a span past the
2511
+ * end is clamped. An inverted / sub-1 range throws `RANGE`; a binary target throws
2512
+ * `MODALITY`.
2513
+ */
2514
+ | {
2515
+ readonly operation: 'splice';
2516
+ readonly path: string;
2517
+ readonly content: string;
2518
+ readonly fromLine: number;
2519
+ readonly fromColumn: number;
2520
+ readonly toLine: number;
2521
+ readonly toColumn: number;
2522
+ }
2523
+ /** Prepend `content` to the start of the file at `path` (creating it when absent). */
2524
+ | {
2525
+ readonly operation: 'prepend';
2526
+ readonly path: string;
2527
+ readonly content: string;
2528
+ }
2529
+ /** Append `content` to the end of the file at `path` (creating it when absent). */
2530
+ | {
2531
+ readonly operation: 'append';
2532
+ readonly path: string;
2533
+ readonly content: string;
2534
+ }
2535
+ /** Re-key the file `from` → `to` (overwriting an occupied target). */
2536
+ | {
2537
+ readonly operation: 'move';
2538
+ readonly from: string;
2539
+ readonly to: string;
2540
+ }
2541
+ /** Remove the file at `path` from the workspace. */
2542
+ | {
2543
+ readonly operation: 'remove';
2544
+ readonly path: string;
2545
+ }
2546
+ /** List the workspaces the model can move between — each `{ id, files, active }` — so it can choose an `id` to `switch` to. */
2547
+ | {
2548
+ readonly operation: 'workspaces';
2549
+ }
2550
+ /** 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. */
2551
+ | {
2552
+ readonly operation: 'switch';
2553
+ readonly id: string;
2554
+ };
2555
+
2556
+ /**
2557
+ * Options for {@link import('./factories.js').createWorkspaceTool} — EITHER a caller-built
2558
+ * {@link WorkspaceManagerInterface} to drive directly, OR a {@link WorkspaceStoreInterface} the
2559
+ * tool constructs a fresh manager over; neither given constructs a manager over
2560
+ * `@orkestrel/agent`'s in-memory store.
2561
+ *
2562
+ * @remarks
2563
+ * - `manager` — drive THIS manager directly (its `active` workspace is what every edit / read
2564
+ * operation targets). Takes priority over `store` when both are supplied.
2565
+ * - `store` — construct a manager over this durable {@link WorkspaceStoreInterface} (via
2566
+ * `@orkestrel/agent`'s `createWorkspaceManager`) — used only when `manager` is omitted.
2567
+ * The store only backs the manager's own `open` / `save` operations: the tool's edits are
2568
+ * NOT auto-persisted — durability requires an explicit caller `save` on the manager
2569
+ * (unlike the workflow tool's `store`, which persists each executed snapshot on settle).
2570
+ * - `name` / `description` — advertised tool overrides; default to
2571
+ * {@link import('./constants.js').WORKSPACE_TOOL_NAME} / {@link import('./constants.js').WORKSPACE_TOOL_DESCRIPTION}.
2572
+ */
2573
+ export declare interface WorkspaceToolOptions {
2574
+ readonly name?: string;
2575
+ readonly description?: string;
2576
+ readonly manager?: WorkspaceManagerInterface;
2577
+ readonly store?: WorkspaceStoreInterface;
2578
+ }
2579
+
2580
+ /**
2581
+ * The shape of a {@link import('./types.js').WorkspaceOperation} — a descriptive tagged union
2582
+ * over the 13 workspace edit / read / navigation operations, discriminated by the `operation`
2583
+ * literal (never a bare `kind`; AGENTS §4.4). Each variant leads with its `operation`
2584
+ * discriminant then its FLAT fields, every field via `stringShape` / `optionalShape` /
2585
+ * `integerShape({ min: 1 })` / `booleanShape`, each carrying a strong field-level `description`.
2586
+ *
2587
+ * @remarks
2588
+ * The union compiles to an `anyOf` JSON Schema + a `unionOf` guard + a first-match parser
2589
+ * automatically ({@link import('./factories.js').createWorkspaceTool} types the result to the
2590
+ * hand-written {@link import('./types.js').WorkspaceOperation}). `limit` and the four `'splice'`
2591
+ * caret components are POSITIVE integers (`integerShape({ min: 1 })`); `regex` / `exact` are
2592
+ * `optionalShape(booleanShape(...))`. The two REGISTRY arms — `workspaces` (list the workspaces
2593
+ * the model can move between) and `switch` (re-point the active one by `id`) — let a model
2594
+ * DISCOVER then CHOOSE which workspace the edit / read arms target.
2595
+ */
2596
+ export declare const workspaceToolShape: UnionShape<readonly [ ObjectShape<{
2597
+ operation: LiteralShape<readonly ["read"]>;
2598
+ path: StringShape;
2599
+ }, false>, ObjectShape<{
2600
+ operation: LiteralShape<readonly ["list"]>;
2601
+ }, false>, ObjectShape<{
2602
+ operation: LiteralShape<readonly ["has"]>;
2603
+ path: StringShape;
2604
+ }, false>, ObjectShape<{
2605
+ operation: LiteralShape<readonly ["search"]>;
2606
+ query: StringShape;
2607
+ regex: OptionalShape<BooleanShape>;
2608
+ exact: OptionalShape<BooleanShape>;
2609
+ limit: OptionalShape<NumberShape>;
2610
+ }, false>, ObjectShape<{
2611
+ operation: LiteralShape<readonly ["replace"]>;
2612
+ query: StringShape;
2613
+ replacement: StringShape;
2614
+ regex: OptionalShape<BooleanShape>;
2615
+ exact: OptionalShape<BooleanShape>;
2616
+ limit: OptionalShape<NumberShape>;
2617
+ }, false>, ObjectShape<{
2618
+ operation: LiteralShape<readonly ["write"]>;
2619
+ path: StringShape;
2620
+ content: StringShape;
2621
+ }, false>, ObjectShape<{
2622
+ operation: LiteralShape<readonly ["splice"]>;
2623
+ path: StringShape;
2624
+ content: StringShape;
2625
+ fromLine: NumberShape;
2626
+ fromColumn: NumberShape;
2627
+ toLine: NumberShape;
2628
+ toColumn: NumberShape;
2629
+ }, false>, ObjectShape<{
2630
+ operation: LiteralShape<readonly ["prepend"]>;
2631
+ path: StringShape;
2632
+ content: StringShape;
2633
+ }, false>, ObjectShape<{
2634
+ operation: LiteralShape<readonly ["append"]>;
2635
+ path: StringShape;
2636
+ content: StringShape;
2637
+ }, false>, ObjectShape<{
2638
+ operation: LiteralShape<readonly ["move"]>;
2639
+ from: StringShape;
2640
+ to: StringShape;
2641
+ }, false>, ObjectShape<{
2642
+ operation: LiteralShape<readonly ["remove"]>;
2643
+ path: StringShape;
2644
+ }, false>, ObjectShape<{
2645
+ operation: LiteralShape<readonly ["workspaces"]>;
2646
+ }, false>, ObjectShape<{
2647
+ operation: LiteralShape<readonly ["switch"]>;
2648
+ id: StringShape;
2649
+ }, false>]>;
2650
+
2651
+ export { }