@oharness/engine 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agent.d.ts +196 -0
- package/dist/agent/agent.js +758 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/compaction.d.ts +68 -0
- package/dist/agent/compaction.js +179 -0
- package/dist/agent/compaction.js.map +1 -0
- package/dist/agent/hooks.d.ts +77 -0
- package/dist/agent/hooks.js +152 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/memory.d.ts +45 -0
- package/dist/agent/memory.js +147 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/overflow.d.ts +35 -0
- package/dist/agent/overflow.js +69 -0
- package/dist/agent/overflow.js.map +1 -0
- package/dist/agent/permissions.d.ts +181 -0
- package/dist/agent/permissions.js +289 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/agent/prompt.d.ts +25 -0
- package/dist/agent/prompt.js +63 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/session.d.ts +108 -0
- package/dist/agent/session.js +231 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/settings.d.ts +37 -0
- package/dist/agent/settings.js +113 -0
- package/dist/agent/settings.js.map +1 -0
- package/dist/agent/skills.d.ts +58 -0
- package/dist/agent/skills.js +225 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/store.d.ts +308 -0
- package/dist/agent/store.js +596 -0
- package/dist/agent/store.js.map +1 -0
- package/dist/agent/subagent.d.ts +44 -0
- package/dist/agent/subagent.js +138 -0
- package/dist/agent/subagent.js.map +1 -0
- package/dist/agent/titles.d.ts +8 -0
- package/dist/agent/titles.js +23 -0
- package/dist/agent/titles.js.map +1 -0
- package/dist/agent/workspace.d.ts +60 -0
- package/dist/agent/workspace.js +156 -0
- package/dist/agent/workspace.js.map +1 -0
- package/dist/artifacts/publish.d.ts +94 -0
- package/dist/artifacts/publish.js +104 -0
- package/dist/artifacts/publish.js.map +1 -0
- package/dist/artifacts/store.d.ts +324 -0
- package/dist/artifacts/store.js +500 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/auth/index.d.ts +13 -0
- package/dist/auth/index.js +10 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/manager.d.ts +83 -0
- package/dist/auth/manager.js +266 -0
- package/dist/auth/manager.js.map +1 -0
- package/dist/auth/oauth.d.ts +83 -0
- package/dist/auth/oauth.js +327 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/providers/account.d.ts +59 -0
- package/dist/auth/providers/account.js +282 -0
- package/dist/auth/providers/account.js.map +1 -0
- package/dist/auth/providers/anthropic.d.ts +24 -0
- package/dist/auth/providers/anthropic.js +209 -0
- package/dist/auth/providers/anthropic.js.map +1 -0
- package/dist/auth/providers/generic.d.ts +57 -0
- package/dist/auth/providers/generic.js +155 -0
- package/dist/auth/providers/generic.js.map +1 -0
- package/dist/auth/providers/official.d.ts +3 -0
- package/dist/auth/providers/official.js +90 -0
- package/dist/auth/providers/official.js.map +1 -0
- package/dist/auth/providers/ottoport.d.ts +3 -0
- package/dist/auth/providers/ottoport.js +60 -0
- package/dist/auth/providers/ottoport.js.map +1 -0
- package/dist/auth/store.d.ts +22 -0
- package/dist/auth/store.js +138 -0
- package/dist/auth/store.js.map +1 -0
- package/dist/auth/types.d.ts +167 -0
- package/dist/auth/types.js +16 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/config.d.ts +197 -0
- package/dist/config.js +195 -0
- package/dist/config.js.map +1 -0
- package/dist/core/errors.d.ts +46 -0
- package/dist/core/errors.js +83 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/tokens.d.ts +12 -0
- package/dist/core/tokens.js +56 -0
- package/dist/core/tokens.js.map +1 -0
- package/dist/core/types.d.ts +91 -0
- package/dist/core/types.js +49 -0
- package/dist/core/types.js.map +1 -0
- package/dist/harness.d.ts +302 -0
- package/dist/harness.js +695 -0
- package/dist/harness.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +55 -0
- package/dist/mcp/client.js +199 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/manager.d.ts +77 -0
- package/dist/mcp/manager.js +325 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/oauth.d.ts +63 -0
- package/dist/mcp/oauth.js +302 -0
- package/dist/mcp/oauth.js.map +1 -0
- package/dist/mcp/protocol.d.ts +130 -0
- package/dist/mcp/protocol.js +14 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/registry.d.ts +52 -0
- package/dist/mcp/registry.js +100 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/registry.json +293 -0
- package/dist/mcp/secrets.d.ts +20 -0
- package/dist/mcp/secrets.js +75 -0
- package/dist/mcp/secrets.js.map +1 -0
- package/dist/mcp/transport.d.ts +51 -0
- package/dist/mcp/transport.js +158 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/paths.d.ts +37 -0
- package/dist/paths.js +63 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugins.d.ts +55 -0
- package/dist/plugins.js +201 -0
- package/dist/plugins.js.map +1 -0
- package/dist/providers/builtin.d.ts +23 -0
- package/dist/providers/builtin.js +141 -0
- package/dist/providers/builtin.js.map +1 -0
- package/dist/providers/catalog.d.ts +129 -0
- package/dist/providers/catalog.js +254 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/catalog.json +472 -0
- package/dist/providers/discovery.d.ts +16 -0
- package/dist/providers/discovery.js +161 -0
- package/dist/providers/discovery.js.map +1 -0
- package/dist/providers/http.d.ts +24 -0
- package/dist/providers/http.js +139 -0
- package/dist/providers/http.js.map +1 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/piai.d.ts +124 -0
- package/dist/providers/piai.js +551 -0
- package/dist/providers/piai.js.map +1 -0
- package/dist/providers/registry.d.ts +65 -0
- package/dist/providers/registry.js +195 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/resilient.d.ts +46 -0
- package/dist/providers/resilient.js +117 -0
- package/dist/providers/resilient.js.map +1 -0
- package/dist/providers/types.d.ts +182 -0
- package/dist/providers/types.js +50 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/schedule/cron.d.ts +35 -0
- package/dist/schedule/cron.js +125 -0
- package/dist/schedule/cron.js.map +1 -0
- package/dist/schedule/scheduler.d.ts +87 -0
- package/dist/schedule/scheduler.js +237 -0
- package/dist/schedule/scheduler.js.map +1 -0
- package/dist/storage/kv.d.ts +56 -0
- package/dist/storage/kv.js +173 -0
- package/dist/storage/kv.js.map +1 -0
- package/dist/storage/migrate.d.ts +11 -0
- package/dist/storage/migrate.js +93 -0
- package/dist/storage/migrate.js.map +1 -0
- package/dist/storage/project.d.ts +9 -0
- package/dist/storage/project.js +57 -0
- package/dist/storage/project.js.map +1 -0
- package/dist/storage/records.d.ts +32 -0
- package/dist/storage/records.js +48 -0
- package/dist/storage/records.js.map +1 -0
- package/dist/sync/client.d.ts +79 -0
- package/dist/sync/client.js +118 -0
- package/dist/sync/client.js.map +1 -0
- package/dist/sync/mirror.d.ts +85 -0
- package/dist/sync/mirror.js +389 -0
- package/dist/sync/mirror.js.map +1 -0
- package/dist/sync/protocol.d.ts +67 -0
- package/dist/sync/protocol.js +16 -0
- package/dist/sync/protocol.js.map +1 -0
- package/dist/sync/settings.d.ts +56 -0
- package/dist/sync/settings.js +60 -0
- package/dist/sync/settings.js.map +1 -0
- package/dist/tools/builtin/artifact.d.ts +16 -0
- package/dist/tools/builtin/artifact.js +134 -0
- package/dist/tools/builtin/artifact.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +3 -0
- package/dist/tools/builtin/bash.js +142 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/fs.d.ts +19 -0
- package/dist/tools/builtin/fs.js +280 -0
- package/dist/tools/builtin/fs.js.map +1 -0
- package/dist/tools/builtin/index.d.ts +22 -0
- package/dist/tools/builtin/index.js +42 -0
- package/dist/tools/builtin/index.js.map +1 -0
- package/dist/tools/builtin/mcp-resource.d.ts +3 -0
- package/dist/tools/builtin/mcp-resource.js +220 -0
- package/dist/tools/builtin/mcp-resource.js.map +1 -0
- package/dist/tools/builtin/memory.d.ts +10 -0
- package/dist/tools/builtin/memory.js +76 -0
- package/dist/tools/builtin/memory.js.map +1 -0
- package/dist/tools/builtin/recall.d.ts +13 -0
- package/dist/tools/builtin/recall.js +163 -0
- package/dist/tools/builtin/recall.js.map +1 -0
- package/dist/tools/builtin/search.d.ts +3 -0
- package/dist/tools/builtin/search.js +240 -0
- package/dist/tools/builtin/search.js.map +1 -0
- package/dist/tools/builtin/skill.d.ts +10 -0
- package/dist/tools/builtin/skill.js +46 -0
- package/dist/tools/builtin/skill.js.map +1 -0
- package/dist/tools/builtin/task.d.ts +9 -0
- package/dist/tools/builtin/task.js +68 -0
- package/dist/tools/builtin/task.js.map +1 -0
- package/dist/tools/builtin/todo.d.ts +20 -0
- package/dist/tools/builtin/todo.js +63 -0
- package/dist/tools/builtin/todo.js.map +1 -0
- package/dist/tools/define.d.ts +19 -0
- package/dist/tools/define.js +39 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +39 -0
- package/dist/tools/registry.js +101 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +112 -0
- package/dist/tools/types.js +22 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/util/id.d.ts +9 -0
- package/dist/util/id.js +19 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/json.d.ts +25 -0
- package/dist/util/json.js +100 -0
- package/dist/util/json.js.map +1 -0
- package/dist/util/jwt.d.ts +74 -0
- package/dist/util/jwt.js +177 -0
- package/dist/util/jwt.js.map +1 -0
- package/dist/util/logger.d.ts +13 -0
- package/dist/util/logger.js +59 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/queue.d.ts +26 -0
- package/dist/util/queue.js +106 -0
- package/dist/util/queue.js.map +1 -0
- package/dist/util/schema.d.ts +17 -0
- package/dist/util/schema.js +98 -0
- package/dist/util/schema.js.map +1 -0
- package/dist/util/shell.d.ts +20 -0
- package/dist/util/shell.js +24 -0
- package/dist/util/shell.js.map +1 -0
- package/official.json +4 -0
- package/package.json +38 -0
- package/skills/artifact-authoring/SKILL.md +81 -0
- package/skills/canvas/SKILL.md +85 -0
- package/skills/skill-authoring/SKILL.md +85 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineTool } from "../define.js";
|
|
3
|
+
import { toolError, toolText } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Spawns a subagent with its own context window and tool set.
|
|
6
|
+
*
|
|
7
|
+
* The description is built at registration time so the model sees the agent
|
|
8
|
+
* types that actually exist in this configuration, rather than a generic
|
|
9
|
+
* placeholder it has to guess against.
|
|
10
|
+
*/
|
|
11
|
+
export function createTaskTool(host) {
|
|
12
|
+
const types = host.listSubagentTypes();
|
|
13
|
+
const roster = types.length === 0
|
|
14
|
+
? "(no subagent types are configured)"
|
|
15
|
+
: types.map((t) => `- ${t.name}: ${t.description}`).join("\n");
|
|
16
|
+
return defineTool({
|
|
17
|
+
name: "task",
|
|
18
|
+
description: [
|
|
19
|
+
"Delegate a self-contained piece of work to a subagent with its own context window.",
|
|
20
|
+
"The subagent cannot ask follow-up questions, so put everything it needs in the prompt — file paths, constraints, and what to return.",
|
|
21
|
+
"You receive only its final message, so state explicitly what it should report back.",
|
|
22
|
+
"Use this for wide searches or independent tracks of work; do routine multi-step work yourself rather than paying the delegation overhead.",
|
|
23
|
+
"",
|
|
24
|
+
"Available agent types:",
|
|
25
|
+
roster,
|
|
26
|
+
].join("\n"),
|
|
27
|
+
parameters: z.object({
|
|
28
|
+
agentType: z
|
|
29
|
+
.string()
|
|
30
|
+
.describe(`Which subagent to run. One of: ${types.map((t) => t.name).join(", ") || "none"}`),
|
|
31
|
+
description: z.string().describe("Short (3-5 word) description of the task"),
|
|
32
|
+
prompt: z.string().min(1).describe("The complete, self-contained task for the subagent"),
|
|
33
|
+
model: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Override the model for this subagent, e.g. 'haiku' for cheap fan-out"),
|
|
37
|
+
}),
|
|
38
|
+
renderTitle: (input) => `Task(${input.agentType}: ${input.description})`,
|
|
39
|
+
async execute(input, ctx) {
|
|
40
|
+
const known = ctx.host.listSubagentTypes().map((t) => t.name);
|
|
41
|
+
if (!known.includes(input.agentType)) {
|
|
42
|
+
return toolError(`unknown agent type "${input.agentType}". Available: ${known.join(", ") || "none"}`);
|
|
43
|
+
}
|
|
44
|
+
ctx.onProgress({
|
|
45
|
+
toolCallId: ctx.toolCallId,
|
|
46
|
+
toolName: "task",
|
|
47
|
+
message: `Running ${input.agentType} subagent: ${input.description}`,
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
const result = await ctx.host.runSubagent({
|
|
51
|
+
agentType: input.agentType,
|
|
52
|
+
prompt: input.prompt,
|
|
53
|
+
description: input.description,
|
|
54
|
+
model: input.model,
|
|
55
|
+
signal: ctx.signal,
|
|
56
|
+
});
|
|
57
|
+
return toolText(result.text || "(the subagent returned no text)", {
|
|
58
|
+
turns: result.turns,
|
|
59
|
+
usage: result.usage,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
return toolError(`subagent failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../../src/tools/builtin/task.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const TodoItemSchema: z.ZodObject<{
|
|
3
|
+
content: z.ZodString;
|
|
4
|
+
status: z.ZodEnum<{
|
|
5
|
+
pending: "pending";
|
|
6
|
+
in_progress: "in_progress";
|
|
7
|
+
completed: "completed";
|
|
8
|
+
}>;
|
|
9
|
+
activeForm: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export type TodoItem = z.infer<typeof TodoItemSchema>;
|
|
12
|
+
/**
|
|
13
|
+
* A scratchpad the model owns. Its value is less the storage than the forcing
|
|
14
|
+
* function: writing the plan down keeps multi-step work from drifting, and
|
|
15
|
+
* gives the user something to watch.
|
|
16
|
+
*/
|
|
17
|
+
export declare const todoTool: import("../types.ts").Tool;
|
|
18
|
+
export declare function getTodos(state: Map<string, unknown>): TodoItem[];
|
|
19
|
+
export declare function renderTodos(todos: TodoItem[]): string;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineTool } from "../define.js";
|
|
3
|
+
import { toolText } from "../types.js";
|
|
4
|
+
const TODO_KEY = "todo:list";
|
|
5
|
+
const TodoItemSchema = z.object({
|
|
6
|
+
content: z.string().min(1).describe("What needs to be done, in imperative form"),
|
|
7
|
+
status: z.enum(["pending", "in_progress", "completed"]),
|
|
8
|
+
activeForm: z
|
|
9
|
+
.string()
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("Present-continuous form shown while the item is in progress"),
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* A scratchpad the model owns. Its value is less the storage than the forcing
|
|
15
|
+
* function: writing the plan down keeps multi-step work from drifting, and
|
|
16
|
+
* gives the user something to watch.
|
|
17
|
+
*/
|
|
18
|
+
export const todoTool = defineTool({
|
|
19
|
+
name: "todo_write",
|
|
20
|
+
description: [
|
|
21
|
+
"Record or update the task list for multi-step work.",
|
|
22
|
+
"Send the complete list every time — it replaces the previous one.",
|
|
23
|
+
"Keep exactly one item `in_progress`, and mark items `completed` as soon as they are actually done.",
|
|
24
|
+
"Skip this for single-step or trivial requests.",
|
|
25
|
+
].join(" "),
|
|
26
|
+
parameters: z.object({
|
|
27
|
+
todos: z.array(TodoItemSchema).describe("The full task list, in order"),
|
|
28
|
+
}),
|
|
29
|
+
renderTitle: (input) => `Todo(${input.todos.length} items)`,
|
|
30
|
+
// The same: a list held in session state, guarded by nobody.
|
|
31
|
+
sessionLocal: true,
|
|
32
|
+
async execute(input, ctx) {
|
|
33
|
+
const inProgress = input.todos.filter((t) => t.status === "in_progress");
|
|
34
|
+
if (inProgress.length > 1) {
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: `${inProgress.length} items are in_progress. Exactly one item may be in progress at a time.`,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
isError: true,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
ctx.host.state.set(TODO_KEY, input.todos);
|
|
46
|
+
return toolText(renderTodos(input.todos), { todos: input.todos });
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
export function getTodos(state) {
|
|
50
|
+
const stored = state.get(TODO_KEY);
|
|
51
|
+
return Array.isArray(stored) ? stored : [];
|
|
52
|
+
}
|
|
53
|
+
export function renderTodos(todos) {
|
|
54
|
+
if (todos.length === 0)
|
|
55
|
+
return "Task list cleared.";
|
|
56
|
+
const done = todos.filter((t) => t.status === "completed").length;
|
|
57
|
+
const lines = todos.map((todo) => {
|
|
58
|
+
const mark = todo.status === "completed" ? "x" : todo.status === "in_progress" ? "~" : " ";
|
|
59
|
+
return `[${mark}] ${todo.content}`;
|
|
60
|
+
});
|
|
61
|
+
return `${lines.join("\n")}\n\n${done}/${todos.length} complete.`;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=todo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo.js","sourceRoot":"","sources":["../../../src/tools/builtin/todo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Tool, ToolContext, ToolResult } from "./types.ts";
|
|
3
|
+
export interface DefineToolOptions<S extends z.ZodType> {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
parameters: S;
|
|
7
|
+
readOnly?: boolean;
|
|
8
|
+
concurrencySafe?: boolean;
|
|
9
|
+
sessionLocal?: boolean;
|
|
10
|
+
hidden?: boolean;
|
|
11
|
+
renderTitle?(input: z.infer<S>): string;
|
|
12
|
+
execute(input: z.infer<S>, ctx: ToolContext): Promise<ToolResult>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Define a tool from a zod schema. The schema does double duty: it generates
|
|
16
|
+
* the JSON Schema the model sees, and it validates the model's input before
|
|
17
|
+
* `execute` runs — so tools never have to defend against malformed arguments.
|
|
18
|
+
*/
|
|
19
|
+
export declare function defineTool<S extends z.ZodType>(opts: DefineToolOptions<S>): Tool;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { zodToJsonSchema } from "../util/schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Define a tool from a zod schema. The schema does double duty: it generates
|
|
5
|
+
* the JSON Schema the model sees, and it validates the model's input before
|
|
6
|
+
* `execute` runs — so tools never have to defend against malformed arguments.
|
|
7
|
+
*/
|
|
8
|
+
export function defineTool(opts) {
|
|
9
|
+
const inputSchema = zodToJsonSchema(opts.parameters);
|
|
10
|
+
return {
|
|
11
|
+
name: opts.name,
|
|
12
|
+
description: opts.description,
|
|
13
|
+
inputSchema,
|
|
14
|
+
readOnly: opts.readOnly,
|
|
15
|
+
concurrencySafe: opts.concurrencySafe ?? opts.readOnly,
|
|
16
|
+
sessionLocal: opts.sessionLocal,
|
|
17
|
+
hidden: opts.hidden,
|
|
18
|
+
source: "builtin",
|
|
19
|
+
validate(raw) {
|
|
20
|
+
const parsed = opts.parameters.safeParse(raw ?? {});
|
|
21
|
+
if (parsed.success)
|
|
22
|
+
return { ok: true, value: parsed.data };
|
|
23
|
+
return { ok: false, error: formatZodError(parsed.error) };
|
|
24
|
+
},
|
|
25
|
+
renderTitle: opts.renderTitle
|
|
26
|
+
? (input) => opts.renderTitle(input)
|
|
27
|
+
: undefined,
|
|
28
|
+
execute: (input, ctx) => opts.execute(input, ctx),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function formatZodError(error) {
|
|
32
|
+
return error.issues
|
|
33
|
+
.map((issue) => {
|
|
34
|
+
const path = issue.path.length ? issue.path.join(".") : "(root)";
|
|
35
|
+
return `${path}: ${issue.message}`;
|
|
36
|
+
})
|
|
37
|
+
.join("; ");
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAepD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAsB,IAA0B;IACxE,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAErD,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW;QACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,QAAQ;QACtD,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,SAAS;QACjB,QAAQ,CAAC,GAAG;YACV,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;YACpD,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,CAAC;QACD,WAAW,EAAE,IAAI,CAAC,WAAW;YAC3B,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,WAAY,CAAC,KAAmB,CAAC;YACnD,CAAC,CAAC,SAAS;QACb,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAmB,EAAE,GAAG,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAiB;IACvC,OAAO,KAAK,CAAC,MAAM;SAChB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACjE,OAAO,GAAG,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACrC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { defineTool } from "./define.ts";
|
|
2
|
+
export type { DefineToolOptions } from "./define.ts";
|
|
3
|
+
export { ToolRegistry, matchesFilter, matchPattern } from "./registry.ts";
|
|
4
|
+
export type { ToolFilter } from "./registry.ts";
|
|
5
|
+
export { toolText, toolError, toolImage, toolResultText } from "./types.ts";
|
|
6
|
+
export type { SubagentRunOptions, SubagentRunResult, Tool, ToolContent, ToolContext, ToolHost, ToolProgress, ToolResult, } from "./types.ts";
|
|
7
|
+
export * from "./builtin/index.ts";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAW5E,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ToolSchema } from "../core/types.ts";
|
|
2
|
+
import type { Tool } from "./types.ts";
|
|
3
|
+
export interface ToolFilter {
|
|
4
|
+
/** Only these tool names are exposed (glob-ish `mcp__github__*` allowed). */
|
|
5
|
+
allow?: string[];
|
|
6
|
+
/** These are removed, applied after `allow`. */
|
|
7
|
+
deny?: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The set of tools a given agent may call. Registries are cheap to clone, so
|
|
11
|
+
* subagents get a filtered view rather than a shared mutable one.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ToolRegistry {
|
|
14
|
+
private readonly tools;
|
|
15
|
+
register(tool: Tool): this;
|
|
16
|
+
registerAll(tools: Iterable<Tool>): this;
|
|
17
|
+
unregister(name: string): boolean;
|
|
18
|
+
/** Drop every tool contributed by an MCP server (used on disconnect). */
|
|
19
|
+
unregisterServer(server: string): number;
|
|
20
|
+
get(name: string): Tool | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Like `get`, but throws when the tool is missing. For call sites that
|
|
23
|
+
* cannot meaningfully continue without it — the agent loop uses `get` and
|
|
24
|
+
* reports the miss to the model instead.
|
|
25
|
+
*/
|
|
26
|
+
require(name: string): Tool;
|
|
27
|
+
has(name: string): boolean;
|
|
28
|
+
list(): Tool[];
|
|
29
|
+
/** Tools the model is told about: visible, and passing the filter. */
|
|
30
|
+
visible(filter?: ToolFilter): Tool[];
|
|
31
|
+
/** The provider-facing schema list. */
|
|
32
|
+
schemas(filter?: ToolFilter): ToolSchema[];
|
|
33
|
+
clone(): ToolRegistry;
|
|
34
|
+
/** A view containing only the tools that pass `filter`. */
|
|
35
|
+
filtered(filter: ToolFilter): ToolRegistry;
|
|
36
|
+
}
|
|
37
|
+
export declare function matchesFilter(name: string, filter: ToolFilter | undefined): boolean;
|
|
38
|
+
/** `*` matches any run of characters; everything else is literal. */
|
|
39
|
+
export declare function matchPattern(value: string, pattern: string): boolean;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { ToolError } from "../core/errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* The set of tools a given agent may call. Registries are cheap to clone, so
|
|
4
|
+
* subagents get a filtered view rather than a shared mutable one.
|
|
5
|
+
*/
|
|
6
|
+
export class ToolRegistry {
|
|
7
|
+
tools = new Map();
|
|
8
|
+
register(tool) {
|
|
9
|
+
this.tools.set(tool.name, tool);
|
|
10
|
+
return this;
|
|
11
|
+
}
|
|
12
|
+
registerAll(tools) {
|
|
13
|
+
for (const tool of tools)
|
|
14
|
+
this.register(tool);
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
unregister(name) {
|
|
18
|
+
return this.tools.delete(name);
|
|
19
|
+
}
|
|
20
|
+
/** Drop every tool contributed by an MCP server (used on disconnect). */
|
|
21
|
+
unregisterServer(server) {
|
|
22
|
+
let removed = 0;
|
|
23
|
+
for (const [name, tool] of this.tools) {
|
|
24
|
+
if (tool.source === "mcp" && tool.server === server) {
|
|
25
|
+
this.tools.delete(name);
|
|
26
|
+
removed++;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return removed;
|
|
30
|
+
}
|
|
31
|
+
get(name) {
|
|
32
|
+
return this.tools.get(name);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Like `get`, but throws when the tool is missing. For call sites that
|
|
36
|
+
* cannot meaningfully continue without it — the agent loop uses `get` and
|
|
37
|
+
* reports the miss to the model instead.
|
|
38
|
+
*/
|
|
39
|
+
require(name) {
|
|
40
|
+
const tool = this.tools.get(name);
|
|
41
|
+
if (!tool) {
|
|
42
|
+
throw new ToolError(name, `no tool named "${name}". Registered: ${this.list().map((t) => t.name).join(", ")}`);
|
|
43
|
+
}
|
|
44
|
+
return tool;
|
|
45
|
+
}
|
|
46
|
+
has(name) {
|
|
47
|
+
return this.tools.has(name);
|
|
48
|
+
}
|
|
49
|
+
list() {
|
|
50
|
+
return [...this.tools.values()];
|
|
51
|
+
}
|
|
52
|
+
/** Tools the model is told about: visible, and passing the filter. */
|
|
53
|
+
visible(filter) {
|
|
54
|
+
return this.list().filter((tool) => !tool.hidden && matchesFilter(tool.name, filter));
|
|
55
|
+
}
|
|
56
|
+
/** The provider-facing schema list. */
|
|
57
|
+
schemas(filter) {
|
|
58
|
+
return this.visible(filter).map((tool) => ({
|
|
59
|
+
name: tool.name,
|
|
60
|
+
description: tool.description,
|
|
61
|
+
inputSchema: tool.inputSchema,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
clone() {
|
|
65
|
+
const copy = new ToolRegistry();
|
|
66
|
+
for (const tool of this.tools.values())
|
|
67
|
+
copy.register(tool);
|
|
68
|
+
return copy;
|
|
69
|
+
}
|
|
70
|
+
/** A view containing only the tools that pass `filter`. */
|
|
71
|
+
filtered(filter) {
|
|
72
|
+
const copy = new ToolRegistry();
|
|
73
|
+
for (const tool of this.tools.values()) {
|
|
74
|
+
if (matchesFilter(tool.name, filter))
|
|
75
|
+
copy.register(tool);
|
|
76
|
+
}
|
|
77
|
+
return copy;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export function matchesFilter(name, filter) {
|
|
81
|
+
if (!filter)
|
|
82
|
+
return true;
|
|
83
|
+
if (filter.allow?.length && !filter.allow.some((p) => matchPattern(name, p)))
|
|
84
|
+
return false;
|
|
85
|
+
if (filter.deny?.length && filter.deny.some((p) => matchPattern(name, p)))
|
|
86
|
+
return false;
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/** `*` matches any run of characters; everything else is literal. */
|
|
90
|
+
export function matchPattern(value, pattern) {
|
|
91
|
+
if (pattern === "*")
|
|
92
|
+
return true;
|
|
93
|
+
if (!pattern.includes("*"))
|
|
94
|
+
return value === pattern;
|
|
95
|
+
const escaped = pattern
|
|
96
|
+
.split("*")
|
|
97
|
+
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
98
|
+
.join(".*");
|
|
99
|
+
return new RegExp(`^${escaped}$`).test(value);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { ImageBlock, JSONSchema, TextBlock } from "../core/types.ts";
|
|
2
|
+
import type { Logger } from "../util/logger.ts";
|
|
3
|
+
export type ToolContent = Array<TextBlock | ImageBlock>;
|
|
4
|
+
export interface ToolResult {
|
|
5
|
+
content: ToolContent;
|
|
6
|
+
isError?: boolean;
|
|
7
|
+
/** Not sent to the model; available to hooks and the UI. */
|
|
8
|
+
metadata?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/** Emitted while a tool runs, so a UI can show progress. */
|
|
11
|
+
export interface ToolProgress {
|
|
12
|
+
toolCallId: string;
|
|
13
|
+
toolName: string;
|
|
14
|
+
message: string;
|
|
15
|
+
data?: unknown;
|
|
16
|
+
}
|
|
17
|
+
export interface ToolContext {
|
|
18
|
+
cwd: string;
|
|
19
|
+
sessionId: string;
|
|
20
|
+
/** Id of the agent invoking the tool — main loop or a subagent. */
|
|
21
|
+
agentId: string;
|
|
22
|
+
toolCallId: string;
|
|
23
|
+
signal: AbortSignal;
|
|
24
|
+
logger: Logger;
|
|
25
|
+
onProgress(progress: ToolProgress): void;
|
|
26
|
+
/**
|
|
27
|
+
* Capabilities the harness lends to tools. Kept as an interface so the tool
|
|
28
|
+
* layer never imports the agent (which imports tools).
|
|
29
|
+
*/
|
|
30
|
+
host: ToolHost;
|
|
31
|
+
}
|
|
32
|
+
export interface SubagentRunOptions {
|
|
33
|
+
agentType: string;
|
|
34
|
+
prompt: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
model?: string;
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
export interface SubagentRunResult {
|
|
40
|
+
text: string;
|
|
41
|
+
turns: number;
|
|
42
|
+
usage: {
|
|
43
|
+
inputTokens: number;
|
|
44
|
+
outputTokens: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface ToolHost {
|
|
48
|
+
/** Spawn a subagent and run it to completion. Backs the Task tool. */
|
|
49
|
+
runSubagent(opts: SubagentRunOptions): Promise<SubagentRunResult>;
|
|
50
|
+
listSubagentTypes(): Array<{
|
|
51
|
+
name: string;
|
|
52
|
+
description: string;
|
|
53
|
+
}>;
|
|
54
|
+
/** Shared, session-scoped scratch state (the todo list lives here). */
|
|
55
|
+
state: Map<string, unknown>;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a model-supplied path against the workspace policy, throwing when
|
|
58
|
+
* it falls outside the roots allowed for that kind of access.
|
|
59
|
+
*
|
|
60
|
+
* Optional because the policy belongs to the agent and a bare host may not
|
|
61
|
+
* have one; tools then fall back to confining paths to the working
|
|
62
|
+
* directory. Lent as a capability rather than exposed as data so the tool
|
|
63
|
+
* layer still never imports the agent.
|
|
64
|
+
*/
|
|
65
|
+
resolvePath?(input: string, access: "read" | "write"): string;
|
|
66
|
+
}
|
|
67
|
+
export interface Tool {
|
|
68
|
+
name: string;
|
|
69
|
+
/** Sent to the model — the main lever on whether the tool gets used well. */
|
|
70
|
+
description: string;
|
|
71
|
+
inputSchema: JSONSchema;
|
|
72
|
+
/**
|
|
73
|
+
* Read-only tools can be batched in parallel and skip permission prompts.
|
|
74
|
+
* Anything that mutates state or reaches the network should leave this off.
|
|
75
|
+
*/
|
|
76
|
+
readOnly?: boolean;
|
|
77
|
+
/** Safe to run concurrently with other tools in the same assistant turn. */
|
|
78
|
+
concurrencySafe?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Mutates only this session's own scratch state — no file, no command, no
|
|
81
|
+
* network, nothing that outlives the process.
|
|
82
|
+
*
|
|
83
|
+
* Distinct from `readOnly`, which such a tool is not: it changes something,
|
|
84
|
+
* and plan mode should still stop it. What this says is narrower — that
|
|
85
|
+
* approving it protects nobody, so asking is a toll rather than a safeguard.
|
|
86
|
+
* The permission engine exists to guard effects outside this process; see
|
|
87
|
+
* the note at the top of packages/server/src/server.ts for what it is really
|
|
88
|
+
* standing between.
|
|
89
|
+
*/
|
|
90
|
+
sessionLocal?: boolean;
|
|
91
|
+
/** Hidden from the model but still invocable internally. */
|
|
92
|
+
hidden?: boolean;
|
|
93
|
+
/** Where the tool came from, for `/tools` and permission rules. */
|
|
94
|
+
source?: "builtin" | "mcp" | "custom";
|
|
95
|
+
/** MCP server name when `source === "mcp"`. */
|
|
96
|
+
server?: string;
|
|
97
|
+
/** Parse/validate raw model input. Returning an error skips execution. */
|
|
98
|
+
validate?(raw: unknown): {
|
|
99
|
+
ok: true;
|
|
100
|
+
value: unknown;
|
|
101
|
+
} | {
|
|
102
|
+
ok: false;
|
|
103
|
+
error: string;
|
|
104
|
+
};
|
|
105
|
+
/** One-line rendering of a call, e.g. `Bash(npm test)`. */
|
|
106
|
+
renderTitle?(input: unknown): string;
|
|
107
|
+
execute(input: unknown, ctx: ToolContext): Promise<ToolResult>;
|
|
108
|
+
}
|
|
109
|
+
export declare function toolText(text: string, metadata?: Record<string, unknown>): ToolResult;
|
|
110
|
+
export declare function toolError(message: string): ToolResult;
|
|
111
|
+
export declare function toolImage(mimeType: string, data: string, caption?: string): ToolResult;
|
|
112
|
+
export declare function toolResultText(result: ToolResult): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Result helpers
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
export function toolText(text, metadata) {
|
|
5
|
+
return { content: [{ type: "text", text }], ...(metadata ? { metadata } : {}) };
|
|
6
|
+
}
|
|
7
|
+
export function toolError(message) {
|
|
8
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
9
|
+
}
|
|
10
|
+
export function toolImage(mimeType, data, caption) {
|
|
11
|
+
const content = [{ type: "image", mimeType, data }];
|
|
12
|
+
if (caption)
|
|
13
|
+
content.unshift({ type: "text", text: caption });
|
|
14
|
+
return { content };
|
|
15
|
+
}
|
|
16
|
+
export function toolResultText(result) {
|
|
17
|
+
return result.content
|
|
18
|
+
.filter((b) => b.type === "text")
|
|
19
|
+
.map((b) => b.text)
|
|
20
|
+
.join("\n");
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AA0GA,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAkC;IACvE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,IAAY,EAAE,OAAgB;IACxE,MAAM,OAAO,GAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,IAAI,OAAO;QAAE,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,OAAO,MAAM,CAAC,OAAO;SAClB,MAAM,CAAC,CAAC,CAAC,EAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function uuid(): string;
|
|
2
|
+
export declare function shortId(bytes?: number): string;
|
|
3
|
+
/**
|
|
4
|
+
* Tool-call ids must satisfy the strictest provider we target: OpenAI accepts
|
|
5
|
+
* arbitrary strings but rejects long ones on some endpoints, Gemini ignores
|
|
6
|
+
* them entirely. `call_<hex>` is safe everywhere.
|
|
7
|
+
*/
|
|
8
|
+
export declare function toolCallId(): string;
|
|
9
|
+
export declare function sessionId(): string;
|
package/dist/util/id.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { randomUUID, randomBytes } from "node:crypto";
|
|
2
|
+
export function uuid() {
|
|
3
|
+
return randomUUID();
|
|
4
|
+
}
|
|
5
|
+
export function shortId(bytes = 6) {
|
|
6
|
+
return randomBytes(bytes).toString("hex");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Tool-call ids must satisfy the strictest provider we target: OpenAI accepts
|
|
10
|
+
* arbitrary strings but rejects long ones on some endpoints, Gemini ignores
|
|
11
|
+
* them entirely. `call_<hex>` is safe everywhere.
|
|
12
|
+
*/
|
|
13
|
+
export function toolCallId() {
|
|
14
|
+
return `call_${shortId(12)}`;
|
|
15
|
+
}
|
|
16
|
+
export function sessionId() {
|
|
17
|
+
return `${new Date().toISOString().slice(0, 10).replaceAll("-", "")}_${shortId(5)}`;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,UAAU,IAAI;IAClB,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAK,GAAG,CAAC;IAC/B,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AACtF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tolerant JSON helpers for streamed tool arguments.
|
|
3
|
+
*
|
|
4
|
+
* Providers emit tool inputs as a stream of JSON fragments. To render a
|
|
5
|
+
* live preview ("Bash(npm run bui…") we need to parse a prefix of a JSON
|
|
6
|
+
* document, so `parsePartialJson` closes any open strings/arrays/objects
|
|
7
|
+
* before handing the text to JSON.parse.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseJson<T = unknown>(raw: string): {
|
|
10
|
+
ok: true;
|
|
11
|
+
value: T;
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
error: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function parsePartialJson(raw: string): unknown;
|
|
17
|
+
/**
|
|
18
|
+
* Decode accumulated tool-argument JSON. Models occasionally emit a truncated
|
|
19
|
+
* or slightly malformed object; falling back to the partial parser keeps the
|
|
20
|
+
* turn alive, and an empty object lets the tool's own validation produce a
|
|
21
|
+
* useful error message instead of crashing the loop.
|
|
22
|
+
*/
|
|
23
|
+
export declare function decodeToolInput(raw: string): unknown;
|
|
24
|
+
/** Truncate deeply/hugely nested values before logging or previewing. */
|
|
25
|
+
export declare function previewJson(value: unknown, maxLength?: number): string;
|