@code-yeongyu/senpi-agent-core 2026.9.30 → 2026.10.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.
Files changed (64) hide show
  1. package/README.md +49 -20
  2. package/dist/agent-loop.d.ts +27 -3
  3. package/dist/agent-loop.js +192 -56
  4. package/dist/agent.d.ts +21 -7
  5. package/dist/agent.js +38 -18
  6. package/dist/harness/execution/tools.d.ts +1 -1
  7. package/dist/harness/execution/tools.js +0 -2
  8. package/dist/harness/messages.js +1 -0
  9. package/dist/harness/pico3/bash.d.ts +10 -0
  10. package/dist/harness/pico3/bash.js +25 -0
  11. package/dist/harness/pico3/bounded.d.ts +21 -0
  12. package/dist/harness/pico3/bounded.js +95 -0
  13. package/dist/harness/pico3/chord.d.ts +41 -0
  14. package/dist/harness/pico3/chord.js +147 -0
  15. package/dist/harness/pico3/context.d.ts +16 -0
  16. package/dist/harness/pico3/context.js +88 -0
  17. package/dist/harness/pico3/harness.d.ts +198 -0
  18. package/dist/harness/pico3/harness.js +645 -0
  19. package/dist/harness/pico3/hooks.d.ts +10 -0
  20. package/dist/harness/pico3/hooks.js +33 -0
  21. package/dist/harness/pico3/index.d.ts +19 -0
  22. package/dist/harness/pico3/index.js +15 -0
  23. package/dist/harness/pico3/jsonl.d.ts +58 -0
  24. package/dist/harness/pico3/jsonl.js +322 -0
  25. package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
  26. package/dist/harness/pico3/kinds/collapse.js +191 -0
  27. package/dist/harness/pico3/kinds/entries.d.ts +78 -0
  28. package/dist/harness/pico3/kinds/entries.js +13 -0
  29. package/dist/harness/pico3/kinds/frames.d.ts +9 -0
  30. package/dist/harness/pico3/kinds/frames.js +75 -0
  31. package/dist/harness/pico3/kinds/generation.d.ts +94 -0
  32. package/dist/harness/pico3/kinds/generation.js +504 -0
  33. package/dist/harness/pico3/kinds/job.d.ts +44 -0
  34. package/dist/harness/pico3/kinds/job.js +143 -0
  35. package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
  36. package/dist/harness/pico3/kinds/plugin.js +35 -0
  37. package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
  38. package/dist/harness/pico3/kinds/post-tools.js +145 -0
  39. package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
  40. package/dist/harness/pico3/kinds/task-api.js +45 -0
  41. package/dist/harness/pico3/kinds/tool.d.ts +43 -0
  42. package/dist/harness/pico3/kinds/tool.js +373 -0
  43. package/dist/harness/pico3/legacy-tracker.d.ts +11 -0
  44. package/dist/harness/pico3/legacy-tracker.js +39 -0
  45. package/dist/harness/pico3/membrane.d.ts +23 -0
  46. package/dist/harness/pico3/membrane.js +140 -0
  47. package/dist/harness/pico3/memory.d.ts +53 -0
  48. package/dist/harness/pico3/memory.js +265 -0
  49. package/dist/harness/pico3/scheduler.d.ts +49 -0
  50. package/dist/harness/pico3/scheduler.js +437 -0
  51. package/dist/harness/pico3/session.d.ts +264 -0
  52. package/dist/harness/pico3/session.js +1328 -0
  53. package/dist/harness/pico3/system.d.ts +126 -0
  54. package/dist/harness/pico3/system.js +244 -0
  55. package/dist/harness/pico3/types.d.ts +973 -0
  56. package/dist/harness/pico3/types.js +94 -0
  57. package/dist/harness/pico3/view.d.ts +34 -0
  58. package/dist/harness/pico3/view.js +404 -0
  59. package/dist/harness/runtime/drive/tool-placement.js +2 -27
  60. package/dist/harness/telemetry.d.ts +36 -36
  61. package/dist/harness/tools/image.js +1 -1
  62. package/dist/proxy.d.ts +2 -2
  63. package/dist/types.d.ts +111 -34
  64. package/package.json +9 -5
@@ -0,0 +1,143 @@
1
+ const failed = (reason, detail) => ({
2
+ status: "failed",
3
+ failure: { reason, detail },
4
+ });
5
+ const notice = (text, now) => ({
6
+ kind: "pi.notice",
7
+ model: [{ role: "user", content: text, timestamp: now }],
8
+ });
9
+ const jobKind = {
10
+ name: "pi.job",
11
+ slot: () => ({}),
12
+ describe: (task) => ({
13
+ stage: task.checkpoint?.phase ?? "starting",
14
+ ...(task.slot ?? {}),
15
+ }),
16
+ inflight: ["spawning", "running"],
17
+ phases: {
18
+ async waiting(task, runtime, ctx) {
19
+ await runtime.sleep(task.checkpoint.untilMs, ctx);
20
+ return spawn(task, task.checkpoint.occurrence, runtime, ctx);
21
+ },
22
+ async spawning(task, runtime, ctx) {
23
+ return reconcile(task, task.checkpoint, runtime, ctx);
24
+ },
25
+ async running(task, runtime, ctx) {
26
+ return reconcile(task, task.checkpoint, runtime, ctx);
27
+ },
28
+ },
29
+ async initial(task, runtime, ctx) {
30
+ if (runtime.processHost === undefined)
31
+ return { done: () => failed("spawn", "no process host") };
32
+ const now = runtime.now();
33
+ const untilMs = task.input.notBefore ?? now;
34
+ if (untilMs > now)
35
+ return { next: { phase: "waiting", untilMs, occurrence: 1 } };
36
+ return spawn(task, 1, runtime, ctx);
37
+ },
38
+ async abort(task, runtime, ctx) {
39
+ const checkpoint = task.checkpoint;
40
+ if (checkpoint === undefined || checkpoint.phase === "waiting" || runtime.processHost === undefined)
41
+ return async () => ({ killed: false });
42
+ await runtime.processHost.kill(checkpoint.key, "SIGTERM", ctx);
43
+ await runtime.sleep(runtime.now() + 5000, ctx);
44
+ await runtime.processHost.kill(checkpoint.key, "SIGKILL", ctx);
45
+ return async () => ({ killed: true });
46
+ },
47
+ };
48
+ export const job = Object.freeze(jobKind);
49
+ async function spawn(task, occurrence, runtime, ctx) {
50
+ const key = `${task.id}:${occurrence}`;
51
+ await runtime.commit((tx) => tx.checkpoint({ phase: "spawning", key, occurrence }), ctx);
52
+ try {
53
+ await runtime.processHost.start(key, task.input, ctx);
54
+ }
55
+ catch (error) {
56
+ if (ctx.abortSignal?.aborted)
57
+ throw error;
58
+ return {
59
+ done: async (tx, current) => {
60
+ if (task.input.notify)
61
+ await tx.write(current.conversationId, notice(`job ${task.id} failed to start: ${String(error)}`, runtime.now()));
62
+ return failed("spawn", String(error));
63
+ },
64
+ };
65
+ }
66
+ await runtime.commit((tx) => tx.checkpoint({ phase: "running", key, occurrence }), ctx);
67
+ return poll(task, key, occurrence, runtime, ctx);
68
+ }
69
+ async function reconcile(task, checkpoint, runtime, ctx) {
70
+ if (runtime.processHost === undefined)
71
+ return { done: () => failed("interrupted", "no process host after restart") };
72
+ let status;
73
+ try {
74
+ status = await runtime.processHost.status(checkpoint.key, ctx);
75
+ }
76
+ catch (error) {
77
+ return { done: () => failed("interrupted", `host status failed: ${String(error)}`) };
78
+ }
79
+ if (status.status === "unknown") {
80
+ if (!task.input.rerun)
81
+ return { done: () => failed("interrupted", "process outcome unknown") };
82
+ return spawn(task, checkpoint.occurrence, runtime, ctx);
83
+ }
84
+ if (checkpoint.phase === "spawning") {
85
+ await runtime.commit((tx) => tx.checkpoint({ phase: "running", key: checkpoint.key, occurrence: checkpoint.occurrence }), ctx);
86
+ }
87
+ return poll(task, checkpoint.key, checkpoint.occurrence, runtime, ctx);
88
+ }
89
+ async function poll(task, key, occurrence, runtime, ctx) {
90
+ for (let attempt = 0;; attempt++) {
91
+ let status;
92
+ try {
93
+ status = await runtime.processHost.status(key, ctx);
94
+ }
95
+ catch (error) {
96
+ return { done: () => failed("interrupted", `host status failed: ${String(error)}`) };
97
+ }
98
+ if (status.status === "unknown") {
99
+ if (!task.input.rerun)
100
+ return { done: () => failed("interrupted", "process outcome unknown") };
101
+ return spawn(task, occurrence, runtime, ctx);
102
+ }
103
+ const snapshot = status;
104
+ await runtime.commit((tx, current) => {
105
+ const output = tx.slot({ id: current.id, kind: jobKind });
106
+ output.stdout = snapshot.stdout;
107
+ output.stderr = snapshot.stderr;
108
+ output.droppedStdout = snapshot.droppedStdout;
109
+ output.droppedStderr = snapshot.droppedStderr;
110
+ if (snapshot.status === "exited")
111
+ output.exitCode = snapshot.exitCode;
112
+ }, ctx);
113
+ if (snapshot.status === "exited") {
114
+ const { exitCode, stdout, stderr } = snapshot;
115
+ if (task.input.every === undefined) {
116
+ return {
117
+ done: async (tx, current) => {
118
+ if (task.input.notify)
119
+ await tx.write(current.conversationId, notice(`job ${task.id} exited with code ${exitCode}`, runtime.now()));
120
+ return { status: "completed", result: { exitCode, occurrences: occurrence, stdout, stderr } };
121
+ },
122
+ };
123
+ }
124
+ const untilMs = runtime.now() + task.input.every;
125
+ return {
126
+ next: async (tx, current) => {
127
+ if (task.input.notify)
128
+ await tx.write(current.conversationId, notice(`job ${task.id} occurrence ${occurrence} exited with code ${exitCode}`, runtime.now()));
129
+ const output = tx.slot({ id: current.id, kind: jobKind });
130
+ output.stdout = "";
131
+ output.stderr = "";
132
+ output.droppedStdout = 0;
133
+ output.droppedStderr = 0;
134
+ delete output.exitCode;
135
+ output.occurrence = occurrence + 1;
136
+ return { phase: "waiting", untilMs, occurrence: occurrence + 1 };
137
+ },
138
+ };
139
+ }
140
+ await runtime.sleep(runtime.now() + Math.min(1000, 100 * 2 ** Math.min(attempt, 4)), ctx);
141
+ }
142
+ }
143
+ //# sourceMappingURL=job.js.map
@@ -0,0 +1,15 @@
1
+ import { type JsonValue, type Kind } from "../types.ts";
2
+ export type PluginInput = {
3
+ handler: string;
4
+ input: JsonValue;
5
+ };
6
+ type PluginCheckpoint = {
7
+ phase: "started";
8
+ };
9
+ type PluginFailure = {
10
+ reason: "missing_handler" | "threw";
11
+ detail: string;
12
+ };
13
+ export declare const plugin: Readonly<Kind<PluginInput, PluginCheckpoint, import("@earendil-works/chord").JsonValue, PluginFailure, null, object, import("../types.ts").KindConfig<import("../types.ts").ConfigShape, import("../types.ts").ConfigShape>, import("../types.ts").JsonObject, import("../types.ts").TaskTx>>;
14
+ export {};
15
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1,35 @@
1
+ import { toStored } from "../types.js";
2
+ import { taskApi } from "./task-api.js";
3
+ const pluginKind = {
4
+ name: "pi.plugin",
5
+ inflight: ["started"],
6
+ phases: {
7
+ async started(task, runtime, ctx) {
8
+ return run(task, runtime, ctx);
9
+ },
10
+ },
11
+ async initial(task, runtime, ctx) {
12
+ await runtime.commit((tx) => tx.checkpoint({ phase: "started" }), ctx);
13
+ return run(task, runtime, ctx);
14
+ },
15
+ async abort() {
16
+ return async () => null;
17
+ },
18
+ };
19
+ export const plugin = Object.freeze(pluginKind);
20
+ async function run(task, runtime, ctx) {
21
+ const handler = runtime.plugins.get(task.input.handler);
22
+ if (handler === undefined) {
23
+ return { done: () => ({ status: "failed", failure: { reason: "missing_handler", detail: task.input.handler } }) };
24
+ }
25
+ try {
26
+ const result = toStored(await handler(task.input.input, taskApi(task, runtime), ctx));
27
+ return { done: () => ({ status: "completed", result }) };
28
+ }
29
+ catch (error) {
30
+ if (ctx.abortSignal?.aborted)
31
+ throw error;
32
+ return { done: () => ({ status: "failed", failure: { reason: "threw", detail: String(error) } }) };
33
+ }
34
+ }
35
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1,22 @@
1
+ import type { Context } from "@earendil-works/chord";
2
+ import { type CoreKind, type HookInfo, type Id } from "../types.ts";
3
+ export type PostToolsInput = {
4
+ inputs: Id[];
5
+ assistant: Id;
6
+ tools: Id[];
7
+ };
8
+ export type PostToolsResult = {
9
+ successor?: Id;
10
+ ended?: "terminate" | "handoff";
11
+ };
12
+ export interface PostToolsHooks {
13
+ afterTools(assistant: Id, results: Id[], info: HookInfo, ctx: Context): void | Promise<void>;
14
+ }
15
+ export declare const postToolsConfig: {
16
+ readonly sticky: {
17
+ readonly steeringMode: "all" | "one-at-a-time";
18
+ readonly followUpMode: "all" | "one-at-a-time";
19
+ };
20
+ };
21
+ export declare const postTools: CoreKind<PostToolsInput, never, PostToolsResult, never, null, PostToolsHooks, typeof postToolsConfig>;
22
+ //# sourceMappingURL=post-tools.d.ts.map
@@ -0,0 +1,145 @@
1
+ import { toStored } from "../types.js";
2
+ export const postToolsConfig = {
3
+ sticky: {
4
+ steeringMode: "one-at-a-time",
5
+ followUpMode: "one-at-a-time",
6
+ },
7
+ };
8
+ export const postTools = {
9
+ name: "pi.post_tools",
10
+ turn: true,
11
+ config: postToolsConfig,
12
+ phases: {},
13
+ async initial(task, rt, ctx) {
14
+ const rows = await rt.commit(async (tx) => {
15
+ const assistant = await tx.entry(task.input.assistant);
16
+ const calls = (assistant?.model?.[0]?.content ?? []).filter((content) => content.type === "toolCall");
17
+ return Promise.all(task.input.tools.map(async (id, index) => {
18
+ const toolTask = (await tx.task(id));
19
+ const call = calls[index];
20
+ if (toolTask.outcome?.status === "completed") {
21
+ const result = toolTask.outcome.result;
22
+ return {
23
+ call,
24
+ entry: result.entry,
25
+ control: result.control,
26
+ missing: undefined,
27
+ };
28
+ }
29
+ if (toolTask.outcome?.status === "aborted") {
30
+ const aborted = toolTask.outcome.result;
31
+ return {
32
+ call,
33
+ entry: aborted.entry,
34
+ control: undefined,
35
+ missing: aborted.entry === undefined ? "aborted" : undefined,
36
+ };
37
+ }
38
+ return { call, entry: undefined, control: undefined, missing: "orphaned" };
39
+ }));
40
+ }, ctx);
41
+ const results = rows.map((row) => row.entry).filter((entry) => entry !== undefined);
42
+ await rt.hooks.each(ctx, (hook, api) => hook.afterTools?.(task.input.assistant, results, api, ctx));
43
+ return {
44
+ done: async (tx, current) => {
45
+ const conversationId = current.conversationId;
46
+ const head = await tx.newestEntry(conversationId, { withHead: true });
47
+ const state = tx.rewindable(conversationId);
48
+ const selectedTools = [...state.selectedTools];
49
+ let terminate = false;
50
+ let handoff;
51
+ for (const row of rows) {
52
+ for (const name of row.control?.addTools ?? [])
53
+ if (!selectedTools.includes(name))
54
+ selectedTools.push(name);
55
+ if (row.control?.terminate)
56
+ terminate = true;
57
+ if (row.control?.handoff !== undefined)
58
+ handoff = row.control.handoff;
59
+ }
60
+ if (selectedTools.length !== state.selectedTools.length) {
61
+ state.selectedTools = selectedTools;
62
+ tx.emit({ type: "config.changed", keys: ["selectedTools"] });
63
+ }
64
+ for (const row of rows) {
65
+ if (row.missing === undefined)
66
+ continue;
67
+ tx.appendEntry(conversationId, {
68
+ kind: "pi.tool_result",
69
+ model: [
70
+ toStored({
71
+ role: "toolResult",
72
+ toolCallId: row.call.id,
73
+ toolName: row.call.name,
74
+ content: [{ type: "text", text: `Tool result unavailable: task ${row.missing}.` }],
75
+ isError: true,
76
+ timestamp: rt.now(),
77
+ }),
78
+ ],
79
+ data: { diagnostics: [{ severity: "error", message: row.missing, code: row.missing }] },
80
+ });
81
+ tx.emit({
82
+ type: "warning",
83
+ source: "post_tools",
84
+ message: `synthesized ${row.missing} tool result for ${row.call.id}`,
85
+ });
86
+ }
87
+ let headBoundary = head?.id;
88
+ if (handoff !== undefined) {
89
+ headBoundary = tx.appendEntry(conversationId, {
90
+ kind: "pi.handoff",
91
+ head: "self",
92
+ model: [{ role: "user", content: handoff, timestamp: rt.now() }],
93
+ });
94
+ }
95
+ if (handoff !== undefined || terminate) {
96
+ tx.sticky(conversationId).turn = { tools: [] };
97
+ await tx.resolveInputs(task.input.inputs, { status: "done", answer: task.input.assistant });
98
+ tx.emit({ type: "turn.ended", inputs: task.input.inputs, status: "done", answer: task.input.assistant });
99
+ const { triggers } = await tx.boundary(conversationId, "final", headBoundary);
100
+ if (triggers.length > 0)
101
+ tx.emit({ type: "turn.started", inputs: triggers });
102
+ const ended = handoff !== undefined ? "handoff" : "terminate";
103
+ return {
104
+ status: "completed",
105
+ result: triggers.length > 0
106
+ ? { ended, successor: tx.createTask({ kind: "pi.generation", input: { inputs: triggers } }) }
107
+ : { ended },
108
+ };
109
+ }
110
+ const { triggers, terminated } = await tx.boundary(conversationId, "postTools", headBoundary);
111
+ if (terminated) {
112
+ tx.sticky(conversationId).turn = { tools: [] };
113
+ await tx.resolveInputs(task.input.inputs, { status: "unanswered", reason: "terminated" });
114
+ tx.emit({ type: "turn.ended", inputs: task.input.inputs, status: "unanswered", reason: "terminated" });
115
+ if (triggers.length > 0)
116
+ tx.emit({ type: "turn.started", inputs: triggers });
117
+ return {
118
+ status: "completed",
119
+ result: triggers.length > 0
120
+ ? { successor: tx.createTask({ kind: "pi.generation", input: { inputs: triggers } }) }
121
+ : {},
122
+ };
123
+ }
124
+ return {
125
+ status: "completed",
126
+ result: {
127
+ successor: tx.createTask({
128
+ kind: "pi.generation",
129
+ input: { inputs: [...task.input.inputs, ...triggers] },
130
+ }),
131
+ },
132
+ };
133
+ },
134
+ };
135
+ },
136
+ async abort(task) {
137
+ return async (tx, current) => {
138
+ tx.sticky(current.conversationId).turn = { tools: [] };
139
+ await tx.resolveInputs(task.input.inputs, { status: "unanswered", reason: "aborted" });
140
+ tx.emit({ type: "turn.ended", inputs: task.input.inputs, status: "unanswered", reason: "aborted" });
141
+ return null;
142
+ };
143
+ },
144
+ };
145
+ //# sourceMappingURL=post-tools.js.map
@@ -0,0 +1,3 @@
1
+ import type { Runtime, Task, ToolApi } from "../types.ts";
2
+ export declare function taskApi(task: Task, runtime: Runtime): ToolApi;
3
+ //# sourceMappingURL=task-api.d.ts.map
@@ -0,0 +1,45 @@
1
+ export function taskApi(task, runtime) {
2
+ const isKind = (value) => typeof value === "object" && value !== null && "name" in value && "initial" in value;
3
+ return {
4
+ taskId: task.id,
5
+ conversationId: task.conversationId,
6
+ callId: "",
7
+ stream: () => {
8
+ throw new Error("stream is only available to tools");
9
+ },
10
+ progress: () => {
11
+ throw new Error("progress is only available to tools");
12
+ },
13
+ memo: (() => Promise.reject(new Error("memo is only available to tools"))),
14
+ async conversation(spec, ctx) {
15
+ const id = await runtime.createOwnedConversation(spec, ctx);
16
+ return {
17
+ id,
18
+ send: async (input, childContext) => {
19
+ const inputId = await runtime.sendOwned(id, input, childContext);
20
+ return {
21
+ id: inputId,
22
+ wait: (waitContext) => runtime.waitForInput(inputId, waitContext),
23
+ result: (resultContext) => runtime.commit((tx) => tx.input(inputId), resultContext),
24
+ };
25
+ },
26
+ abort: (childContext) => runtime.abortConversation(id, childContext),
27
+ };
28
+ },
29
+ task: ((kind, input, opts, ctx) => {
30
+ if (!isKind(kind))
31
+ throw new Error("task(): pass a kind token");
32
+ return runtime.commit((tx) => tx.createTask(kind, input, opts), ctx);
33
+ }),
34
+ getTask: async (ref, ctx) => (await runtime.commit((tx) => tx.task(ref.id), ctx)),
35
+ waitForTask: (ref, ctx) => runtime.waitForTask(ref.id, ctx),
36
+ slot: (ref, ctx) => runtime.commit(async (tx) => {
37
+ const storedTask = await tx.task(ref.id);
38
+ if (storedTask === undefined)
39
+ return undefined;
40
+ return (tx.snapshot({ doc: "sticky", conversationId: storedTask.conversationId }).tasks[ref.id] ??
41
+ undefined);
42
+ }, ctx),
43
+ };
44
+ }
45
+ //# sourceMappingURL=task-api.js.map
@@ -0,0 +1,43 @@
1
+ import type { Context } from "@earendil-works/chord";
2
+ import type { ToolCall } from "@earendil-works/pi-ai";
3
+ import { type AnyToolDeclaration, type BeforeToolApi, type CoreKind, type HookInfo, type HookResult, type Id, type Step, type Stored, type ToolControl, type ToolResult } from "../types.ts";
4
+ export type StoredToolCall = Stored<ToolCall>;
5
+ export type ToolInput = {
6
+ assistant: Id;
7
+ call: StoredToolCall;
8
+ offered: string[];
9
+ index: number;
10
+ };
11
+ export type ToolCheckpoint = {
12
+ phase: "started";
13
+ replay: "safe" | "unsafe";
14
+ call: StoredToolCall;
15
+ };
16
+ export type ToolTaskResult = {
17
+ entry: Id;
18
+ control?: ToolControl;
19
+ };
20
+ /** Hook points this kind calls. Register with `h.hooks(namespace, kinds.tool, { … })`. */
21
+ export interface ToolHooks {
22
+ /** Before invocation, before `started`. Chain on `call`; `{ block }` stops it. A throw blocks. */
23
+ beforeTool(call: StoredToolCall, api: BeforeToolApi, ctx: Context): HookResult<{
24
+ call?: StoredToolCall;
25
+ block?: string;
26
+ }>;
27
+ /** After the tool returns; may replace the result. Chain. */
28
+ afterTool(call: StoredToolCall, result: ToolResult, api: HookInfo & {
29
+ readonly callId: string;
30
+ }, ctx: Context): HookResult<ToolResult>;
31
+ }
32
+ /** Validate arguments with the tool's real schema (TypeBox 1.x). */
33
+ export declare function invalid(declaration: AnyToolDeclaration, call: StoredToolCall): string | undefined;
34
+ export declare const tool: CoreKind<ToolInput, ToolCheckpoint, ToolTaskResult, never, {
35
+ entry: Id;
36
+ }, ToolHooks>;
37
+ export declare const DEFAULT_BOUNDS: {
38
+ maxBytes: number;
39
+ maxLines: number;
40
+ retain: "head";
41
+ };
42
+ export type { Step };
43
+ //# sourceMappingURL=tool.d.ts.map