@oh-my-pi/pi-coding-agent 15.1.2 → 15.1.4
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/CHANGELOG.md +60 -0
- package/dist/types/async/job-manager.d.ts +3 -2
- package/dist/types/cli/auth-broker-cli.d.ts +25 -0
- package/dist/types/cli/auth-gateway-cli.d.ts +18 -0
- package/dist/types/cli/grievances-cli.d.ts +12 -0
- package/dist/types/commands/auth-broker.d.ts +54 -0
- package/dist/types/commands/auth-gateway.d.ts +32 -0
- package/dist/types/commands/grievances.d.ts +1 -1
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +9 -1
- package/dist/types/commit/agentic/tools/schemas.d.ts +9 -1
- package/dist/types/commit/agentic/tools/split-commit.d.ts +9 -1
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/models-config-schema.d.ts +1 -0
- package/dist/types/config/settings-schema.d.ts +46 -0
- package/dist/types/discovery/agents.d.ts +12 -1
- package/dist/types/edit/renderer.d.ts +3 -0
- package/dist/types/eval/index.d.ts +0 -2
- package/dist/types/goals/tools/goal-tool.d.ts +10 -2
- package/dist/types/index.d.ts +0 -1
- package/dist/types/internal-urls/index.d.ts +1 -1
- package/dist/types/internal-urls/{pi-protocol.d.ts → omp-protocol.d.ts} +3 -3
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/main.d.ts +11 -2
- package/dist/types/modes/acp/acp-agent.d.ts +2 -1
- package/dist/types/modes/acp/acp-event-mapper.d.ts +13 -1
- package/dist/types/modes/acp/acp-mode.d.ts +3 -1
- package/dist/types/modes/emoji-autocomplete.d.ts +16 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +4 -0
- package/dist/types/plan-mode/approved-plan.d.ts +10 -4
- package/dist/types/sdk.d.ts +10 -3
- package/dist/types/session/agent-session.d.ts +7 -3
- package/dist/types/session/auth-broker-config.d.ts +13 -0
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/session/client-bridge.d.ts +3 -0
- package/dist/types/tools/eval.d.ts +41 -7
- package/dist/types/tools/irc.d.ts +8 -2
- package/dist/types/tools/report-tool-issue.d.ts +118 -1
- package/dist/types/tools/resolve.d.ts +8 -2
- package/examples/custom-tools/README.md +3 -12
- package/examples/extensions/README.md +2 -15
- package/examples/extensions/api-demo.ts +1 -7
- package/package.json +7 -7
- package/src/async/job-manager.ts +111 -13
- package/src/autoresearch/tools/init-experiment.ts +11 -33
- package/src/autoresearch/tools/log-experiment.ts +10 -24
- package/src/autoresearch/tools/run-experiment.ts +1 -1
- package/src/autoresearch/tools/update-notes.ts +2 -9
- package/src/cli/auth-broker-cli.ts +746 -0
- package/src/cli/auth-gateway-cli.ts +342 -0
- package/src/cli/grievances-cli.ts +109 -16
- package/src/cli/update-cli.ts +1 -5
- package/src/cli.ts +4 -2
- package/src/commands/auth-broker.ts +96 -0
- package/src/commands/auth-gateway.ts +61 -0
- package/src/commands/grievances.ts +13 -8
- package/src/commands/launch.ts +1 -1
- package/src/commit/agentic/agent.ts +2 -0
- package/src/commit/agentic/tools/analyze-file.ts +2 -2
- package/src/commit/agentic/tools/git-file-diff.ts +2 -2
- package/src/commit/agentic/tools/git-hunk.ts +3 -3
- package/src/commit/agentic/tools/git-overview.ts +2 -2
- package/src/commit/agentic/tools/propose-changelog.ts +1 -3
- package/src/commit/agentic/tools/recent-commits.ts +1 -1
- package/src/commit/agentic/tools/schemas.ts +1 -9
- package/src/config/model-equivalence.ts +279 -174
- package/src/config/model-registry.ts +37 -6
- package/src/config/model-resolver.ts +13 -8
- package/src/config/models-config-schema.ts +8 -0
- package/src/config/settings-schema.ts +52 -0
- package/src/cursor.ts +1 -1
- package/src/debug/log-formatting.ts +1 -1
- package/src/debug/log-viewer.ts +1 -1
- package/src/debug/profiler.ts +4 -0
- package/src/debug/raw-sse-buffer.ts +100 -59
- package/src/debug/raw-sse.ts +1 -1
- package/src/discovery/agents.ts +15 -4
- package/src/edit/modes/apply-patch.ts +1 -5
- package/src/edit/modes/patch.ts +5 -5
- package/src/edit/modes/replace.ts +5 -5
- package/src/edit/renderer.ts +2 -1
- package/src/edit/streaming.ts +1 -1
- package/src/eval/index.ts +0 -2
- package/src/eval/js/shared/runtime.ts +107 -2
- package/src/eval/py/kernel.ts +1 -1
- package/src/exa/researcher.ts +4 -4
- package/src/exa/search.ts +10 -22
- package/src/exa/websets.ts +33 -33
- package/src/extensibility/typebox.ts +44 -17
- package/src/goals/tools/goal-tool.ts +3 -3
- package/src/index.ts +0 -3
- package/src/internal-urls/docs-index.generated.ts +21 -18
- package/src/internal-urls/index.ts +1 -1
- package/src/internal-urls/{pi-protocol.ts → omp-protocol.ts} +10 -10
- package/src/internal-urls/router.ts +3 -3
- package/src/internal-urls/types.ts +1 -1
- package/src/lsp/types.ts +8 -11
- package/src/main.ts +216 -146
- package/src/mcp/tool-bridge.ts +3 -3
- package/src/modes/acp/acp-agent.ts +203 -57
- package/src/modes/acp/acp-client-bridge.ts +2 -1
- package/src/modes/acp/acp-event-mapper.ts +208 -32
- package/src/modes/acp/acp-mode.ts +11 -3
- package/src/modes/components/bash-execution.ts +1 -1
- package/src/modes/components/diff.ts +1 -2
- package/src/modes/components/eval-execution.ts +1 -1
- package/src/modes/components/oauth-selector.ts +38 -2
- package/src/modes/components/tool-execution.ts +1 -2
- package/src/modes/components/tree-selector.ts +26 -7
- package/src/modes/controllers/command-controller.ts +95 -34
- package/src/modes/controllers/input-controller.ts +4 -3
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/interactive-mode.ts +92 -19
- package/src/modes/print-mode.ts +3 -3
- package/src/modes/prompt-action-autocomplete.ts +14 -0
- package/src/plan-mode/approved-plan.ts +30 -9
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/system/ttsr-tool-reminder.md +5 -0
- package/src/prompts/tools/ask.md +4 -3
- package/src/prompts/tools/eval.md +25 -26
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/resolve.md +1 -1
- package/src/prompts/tools/search.md +1 -1
- package/src/prompts/tools/web-search.md +1 -1
- package/src/sdk.ts +81 -8
- package/src/session/agent-session.ts +362 -131
- package/src/session/agent-storage.ts +7 -2
- package/src/session/auth-broker-config.ts +102 -0
- package/src/session/auth-storage.ts +7 -1
- package/src/session/client-bridge.ts +3 -0
- package/src/session/streaming-output.ts +1 -1
- package/src/task/types.ts +10 -35
- package/src/tools/bash-interactive.ts +4 -1
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser.ts +12 -20
- package/src/tools/eval.ts +77 -100
- package/src/tools/gh.ts +21 -45
- package/src/tools/hindsight-recall.ts +1 -1
- package/src/tools/hindsight-reflect.ts +2 -2
- package/src/tools/hindsight-retain.ts +3 -7
- package/src/tools/index.ts +8 -1
- package/src/tools/inspect-image.ts +4 -1
- package/src/tools/irc.ts +4 -12
- package/src/tools/job.ts +3 -11
- package/src/tools/report-tool-issue.ts +462 -17
- package/src/tools/resolve.ts +2 -7
- package/src/tools/todo-write.ts +8 -15
- package/src/utils/title-generator.ts +3 -0
- package/src/web/search/index.ts +6 -6
- package/dist/types/eval/parse.d.ts +0 -28
- package/dist/types/eval/sniff.d.ts +0 -11
- package/src/eval/eval.lark +0 -36
- package/src/eval/parse.ts +0 -407
- package/src/eval/sniff.ts +0 -28
package/src/edit/modes/patch.ts
CHANGED
|
@@ -1578,16 +1578,16 @@ export async function computePatchDiff(
|
|
|
1578
1578
|
|
|
1579
1579
|
export const patchEditEntrySchema = z
|
|
1580
1580
|
.object({
|
|
1581
|
-
op: z.enum(["create", "delete", "update"]).optional().describe("
|
|
1582
|
-
rename: z.string().describe("
|
|
1583
|
-
diff: z.string().describe("
|
|
1581
|
+
op: z.enum(["create", "delete", "update"]).optional().describe("operation (default update)"),
|
|
1582
|
+
rename: z.string().describe("new path for move").optional(),
|
|
1583
|
+
diff: z.string().describe("diff hunks or full content for create").optional(),
|
|
1584
1584
|
})
|
|
1585
1585
|
.strict();
|
|
1586
1586
|
|
|
1587
1587
|
export const patchEditSchema = z
|
|
1588
1588
|
.object({
|
|
1589
|
-
path: z.string().describe("file path
|
|
1590
|
-
edits: z.array(patchEditEntrySchema).min(1).describe("
|
|
1589
|
+
path: z.string().describe("file path"),
|
|
1590
|
+
edits: z.array(patchEditEntrySchema).min(1).describe("patch operations"),
|
|
1591
1591
|
})
|
|
1592
1592
|
.strict();
|
|
1593
1593
|
|
|
@@ -978,16 +978,16 @@ export function findContextLine(
|
|
|
978
978
|
|
|
979
979
|
export const replaceEditEntrySchema = z
|
|
980
980
|
.object({
|
|
981
|
-
old_text: z.string().describe("
|
|
982
|
-
new_text: z.string().describe("
|
|
983
|
-
all: z.boolean().describe("
|
|
981
|
+
old_text: z.string().describe("text to find"),
|
|
982
|
+
new_text: z.string().describe("replacement text"),
|
|
983
|
+
all: z.boolean().describe("replace all occurrences").optional(),
|
|
984
984
|
})
|
|
985
985
|
.strict();
|
|
986
986
|
|
|
987
987
|
export const replaceEditSchema = z
|
|
988
988
|
.object({
|
|
989
|
-
path: z.string().describe("file path
|
|
990
|
-
edits: z.array(replaceEditEntrySchema).min(1).describe("
|
|
989
|
+
path: z.string().describe("file path"),
|
|
990
|
+
edits: z.array(replaceEditEntrySchema).min(1).describe("replacements"),
|
|
991
991
|
})
|
|
992
992
|
.strict();
|
|
993
993
|
|
package/src/edit/renderer.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Edit tool renderer and LSP batching helpers.
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
6
6
|
import { Text, visibleWidth, wrapTextWithAnsi } from "@oh-my-pi/pi-tui";
|
|
7
|
+
import { sanitizeText } from "@oh-my-pi/pi-utils";
|
|
7
8
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
8
9
|
import type { FileDiagnosticsResult } from "../lsp";
|
|
9
10
|
import { renderDiff as renderDiffColored } from "../modes/components/diff";
|
package/src/edit/streaming.ts
CHANGED
package/src/eval/index.ts
CHANGED
|
@@ -38,6 +38,75 @@ export interface RuntimeOptions {
|
|
|
38
38
|
extraGlobals?: Record<string, unknown>;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// Strict base64: characters from the standard alphabet plus optional `=` padding, and a
|
|
42
|
+
// length that is a multiple of four. URL-safe base64 and embedded whitespace are not
|
|
43
|
+
// accepted — the Anthropic API only honors strict base64 in image sources.
|
|
44
|
+
const BASE64_STRICT_RE = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
45
|
+
const DECIMAL_CSV_RE = /^\d{1,3}(?:,\d{1,3})*$/;
|
|
46
|
+
|
|
47
|
+
function isStrictBase64(s: string): boolean {
|
|
48
|
+
if (s.length === 0 || s.length % 4 !== 0) return false;
|
|
49
|
+
return BASE64_STRICT_RE.test(s);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Normalize the `data` field of an `{ type: "image", data, mimeType }` display payload
|
|
54
|
+
* into strict base64. Accepts:
|
|
55
|
+
* - already-valid base64 strings (passed through verbatim)
|
|
56
|
+
* - `Uint8Array` / `Buffer` / `ArrayBuffer` / typed array views
|
|
57
|
+
* - `{ type: "Buffer", data: number[] }` (the shape Node serializes Buffers to via
|
|
58
|
+
* `JSON.stringify`)
|
|
59
|
+
* - decimal-CSV byte strings (the output of `uint8array.toString("base64")`, which
|
|
60
|
+
* silently ignores the encoding argument and returns `Array.prototype.toString` —
|
|
61
|
+
* a footgun for callers expecting `Buffer.toString` semantics)
|
|
62
|
+
* Returns `null` if no recovery is possible.
|
|
63
|
+
*/
|
|
64
|
+
function coerceImageBase64(data: unknown): string | null {
|
|
65
|
+
if (typeof data === "string") {
|
|
66
|
+
if (isStrictBase64(data)) return data;
|
|
67
|
+
if (DECIMAL_CSV_RE.test(data)) {
|
|
68
|
+
const parts = data.split(",");
|
|
69
|
+
const bytes = new Uint8Array(parts.length);
|
|
70
|
+
for (let i = 0; i < parts.length; i++) {
|
|
71
|
+
const n = Number(parts[i]);
|
|
72
|
+
if (!Number.isInteger(n) || n < 0 || n > 255) return null;
|
|
73
|
+
bytes[i] = n;
|
|
74
|
+
}
|
|
75
|
+
return Buffer.from(bytes).toString("base64");
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (data instanceof Uint8Array) return Buffer.from(data).toString("base64");
|
|
80
|
+
if (data instanceof ArrayBuffer) return Buffer.from(data).toString("base64");
|
|
81
|
+
if (ArrayBuffer.isView(data)) {
|
|
82
|
+
const view = data as ArrayBufferView;
|
|
83
|
+
return Buffer.from(view.buffer, view.byteOffset, view.byteLength).toString("base64");
|
|
84
|
+
}
|
|
85
|
+
if (data && typeof data === "object") {
|
|
86
|
+
const obj = data as { type?: unknown; data?: unknown };
|
|
87
|
+
if (obj.type === "Buffer" && Array.isArray(obj.data)) {
|
|
88
|
+
const arr = obj.data as unknown[];
|
|
89
|
+
const bytes = new Uint8Array(arr.length);
|
|
90
|
+
for (let i = 0; i < arr.length; i++) {
|
|
91
|
+
const n = arr[i];
|
|
92
|
+
if (typeof n !== "number" || !Number.isInteger(n) || n < 0 || n > 255) return null;
|
|
93
|
+
bytes[i] = n;
|
|
94
|
+
}
|
|
95
|
+
return Buffer.from(bytes).toString("base64");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function describeDataType(data: unknown): string {
|
|
102
|
+
if (data === null) return "null";
|
|
103
|
+
if (data instanceof Uint8Array) return "Uint8Array";
|
|
104
|
+
if (data instanceof ArrayBuffer) return "ArrayBuffer";
|
|
105
|
+
if (ArrayBuffer.isView(data)) return data.constructor.name;
|
|
106
|
+
if (typeof data === "string") return `string(${data.length})`;
|
|
107
|
+
return typeof data;
|
|
108
|
+
}
|
|
109
|
+
|
|
41
110
|
/**
|
|
42
111
|
* Shared JS runtime for the eval worker and the browser tab worker. Owns the prelude,
|
|
43
112
|
* helper bag, console bridge, and indirect-eval execution. Emits text/display/tool-call
|
|
@@ -109,8 +178,19 @@ export class JsRuntime {
|
|
|
109
178
|
if (!hooks) return;
|
|
110
179
|
if (value && typeof value === "object") {
|
|
111
180
|
const record = value as Record<string, unknown>;
|
|
112
|
-
if (record.type === "image" && typeof record.
|
|
113
|
-
|
|
181
|
+
if (record.type === "image" && typeof record.mimeType === "string") {
|
|
182
|
+
const data = coerceImageBase64(record.data);
|
|
183
|
+
if (data !== null) {
|
|
184
|
+
hooks.onDisplay({ type: "image", data, mimeType: record.mimeType });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
logger.warn("js displayValue: dropping image with unrecognized data shape", {
|
|
188
|
+
mimeType: record.mimeType,
|
|
189
|
+
dataType: describeDataType(record.data),
|
|
190
|
+
});
|
|
191
|
+
hooks.onText(
|
|
192
|
+
`[display: image dropped — \`data\` must be a base64 string, Uint8Array/Buffer, or ArrayBuffer; got ${describeDataType(record.data)}]\n`,
|
|
193
|
+
);
|
|
114
194
|
return;
|
|
115
195
|
}
|
|
116
196
|
try {
|
|
@@ -137,6 +217,13 @@ export class JsRuntime {
|
|
|
137
217
|
},
|
|
138
218
|
__omp_import__: async (source: string, options?: ImportCallOptions) => {
|
|
139
219
|
const target = resolveImportSpecifier(this.#cwd, source);
|
|
220
|
+
// Always invalidate cached module records for user-owned source files so edits
|
|
221
|
+
// between cells are picked up. Bun ignores query-string busting on `file:` URLs
|
|
222
|
+
// but honors `delete require.cache[absPath]`; bare specifiers and URL schemes are
|
|
223
|
+
// left alone to keep package identity stable across cells.
|
|
224
|
+
if (isLocalPathSpecifier(source) && path.isAbsolute(target)) {
|
|
225
|
+
delete require.cache[target];
|
|
226
|
+
}
|
|
140
227
|
return options !== undefined ? await import(target, options) : await import(target);
|
|
141
228
|
},
|
|
142
229
|
__omp_emit_status__: (op: string, data: Record<string, unknown> = {}) => {
|
|
@@ -193,3 +280,21 @@ function resolveImportSpecifier(cwd: string, source: string): string {
|
|
|
193
280
|
return source;
|
|
194
281
|
}
|
|
195
282
|
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Returns true when the original specifier is a relative or absolute filesystem path
|
|
286
|
+
* (i.e. user-owned source the agent is iterating on). Bare specifiers and URL schemes
|
|
287
|
+
* are excluded — `node:` built-ins cannot be reloaded, and busting bare packages would
|
|
288
|
+
* defeat module identity for every cell while bringing no editing benefit.
|
|
289
|
+
*/
|
|
290
|
+
function isLocalPathSpecifier(source: string): boolean {
|
|
291
|
+
return (
|
|
292
|
+
source.startsWith("./") ||
|
|
293
|
+
source.startsWith("../") ||
|
|
294
|
+
source === "." ||
|
|
295
|
+
source === ".." ||
|
|
296
|
+
source.startsWith("/") ||
|
|
297
|
+
source.startsWith("~/") ||
|
|
298
|
+
/^[a-zA-Z]:[\\/]/.test(source)
|
|
299
|
+
);
|
|
300
|
+
}
|
package/src/eval/py/kernel.ts
CHANGED
|
@@ -626,7 +626,7 @@ export class PythonKernel {
|
|
|
626
626
|
const exitedPromise = this.#exitedPromise;
|
|
627
627
|
const timeout = new Promise<null>(resolve => {
|
|
628
628
|
const timer = setTimeout(() => resolve(null), Math.max(0, timeoutMs));
|
|
629
|
-
|
|
629
|
+
timer.unref?.();
|
|
630
630
|
});
|
|
631
631
|
return Promise.race([exitedPromise.then(code => code as number | null), timeout]);
|
|
632
632
|
}
|
package/src/exa/researcher.ts
CHANGED
|
@@ -14,9 +14,9 @@ const researcherStartTool = createExaTool(
|
|
|
14
14
|
"Start Deep Research",
|
|
15
15
|
"Start an asynchronous deep research task using Exa's researcher. Returns a task_id for polling completion.",
|
|
16
16
|
z.object({
|
|
17
|
-
query: z.string().describe("
|
|
18
|
-
depth: z.number().int().min(1).max(5).describe("
|
|
19
|
-
breadth: z.number().int().min(1).max(5).describe("
|
|
17
|
+
query: z.string().describe("research query"),
|
|
18
|
+
depth: z.number().int().min(1).max(5).describe("research depth (1-5)").optional(),
|
|
19
|
+
breadth: z.number().int().min(1).max(5).describe("research breadth (1-5)").optional(),
|
|
20
20
|
}),
|
|
21
21
|
"deep_researcher_start",
|
|
22
22
|
{ formatResponse: false },
|
|
@@ -27,7 +27,7 @@ const researcherPollTool = createExaTool(
|
|
|
27
27
|
"Poll Research Status",
|
|
28
28
|
"Poll the status of an asynchronous research task. Returns status (pending|running|completed|failed) and result if completed.",
|
|
29
29
|
z.object({
|
|
30
|
-
task_id: z.string().describe("
|
|
30
|
+
task_id: z.string().describe("task id"),
|
|
31
31
|
}),
|
|
32
32
|
"deep_researcher_check",
|
|
33
33
|
{ formatResponse: false },
|
package/src/exa/search.ts
CHANGED
|
@@ -30,28 +30,16 @@ Parameters:
|
|
|
30
30
|
- num_results: Maximum number of results to return (default: 10, max: 100)`,
|
|
31
31
|
|
|
32
32
|
z.object({
|
|
33
|
-
query: z.string().describe("
|
|
34
|
-
type: z
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
.optional(),
|
|
44
|
-
end_published_date: z.string().describe("Filter results published before this date (ISO 8601 format)").optional(),
|
|
45
|
-
use_autoprompt: z.boolean().describe("Let Exa optimize your query automatically (default: true)").optional(),
|
|
46
|
-
text: z.boolean().describe("Include page text content in results (costs more, default: false)").optional(),
|
|
47
|
-
highlights: z.boolean().describe("Include highlighted relevant snippets (default: false)").optional(),
|
|
48
|
-
num_results: z
|
|
49
|
-
.number()
|
|
50
|
-
.int()
|
|
51
|
-
.min(1)
|
|
52
|
-
.max(100)
|
|
53
|
-
.describe("Maximum number of results to return (default: 10, max: 100)")
|
|
54
|
-
.optional(),
|
|
33
|
+
query: z.string().describe("search query"),
|
|
34
|
+
type: z.enum(["keyword", "neural", "auto"]).describe("search type").optional(),
|
|
35
|
+
include_domains: z.array(z.string()).describe("include domains").optional(),
|
|
36
|
+
exclude_domains: z.array(z.string()).describe("exclude domains").optional(),
|
|
37
|
+
start_published_date: z.string().describe("published after (iso 8601)").optional(),
|
|
38
|
+
end_published_date: z.string().describe("published before (iso 8601)").optional(),
|
|
39
|
+
use_autoprompt: z.boolean().describe("autoprompt").optional(),
|
|
40
|
+
text: z.boolean().describe("include page text").optional(),
|
|
41
|
+
highlights: z.boolean().describe("include highlights").optional(),
|
|
42
|
+
num_results: z.number().int().min(1).max(100).describe("max results (1-100)").optional(),
|
|
55
43
|
}),
|
|
56
44
|
"web_search_exa",
|
|
57
45
|
);
|
package/src/exa/websets.ts
CHANGED
|
@@ -53,8 +53,8 @@ const websetCreateTool = createWebsetTool(
|
|
|
53
53
|
"Create Webset",
|
|
54
54
|
"Create a new webset collection for organizing web content.",
|
|
55
55
|
z.object({
|
|
56
|
-
name: z.string().describe("
|
|
57
|
-
description: z.string().describe("
|
|
56
|
+
name: z.string().describe("webset name"),
|
|
57
|
+
description: z.string().describe("description").optional(),
|
|
58
58
|
}),
|
|
59
59
|
"create_webset",
|
|
60
60
|
);
|
|
@@ -72,7 +72,7 @@ const websetGetTool = createWebsetTool(
|
|
|
72
72
|
"Get Webset",
|
|
73
73
|
"Get details of a specific webset by ID.",
|
|
74
74
|
z.object({
|
|
75
|
-
id: z.string().describe("
|
|
75
|
+
id: z.string().describe("webset id"),
|
|
76
76
|
}),
|
|
77
77
|
"get_webset",
|
|
78
78
|
);
|
|
@@ -82,9 +82,9 @@ const websetUpdateTool = createWebsetTool(
|
|
|
82
82
|
"Update Webset",
|
|
83
83
|
"Update a webset's name or description.",
|
|
84
84
|
z.object({
|
|
85
|
-
id: z.string().describe("
|
|
86
|
-
name: z.string().describe("
|
|
87
|
-
description: z.string().describe("
|
|
85
|
+
id: z.string().describe("webset id"),
|
|
86
|
+
name: z.string().describe("new name").optional(),
|
|
87
|
+
description: z.string().describe("new description").optional(),
|
|
88
88
|
}),
|
|
89
89
|
"update_webset",
|
|
90
90
|
);
|
|
@@ -94,7 +94,7 @@ const websetDeleteTool = createWebsetTool(
|
|
|
94
94
|
"Delete Webset",
|
|
95
95
|
"Delete a webset and all its contents.",
|
|
96
96
|
z.object({
|
|
97
|
-
id: z.string().describe("
|
|
97
|
+
id: z.string().describe("webset id"),
|
|
98
98
|
}),
|
|
99
99
|
"delete_webset",
|
|
100
100
|
);
|
|
@@ -105,9 +105,9 @@ const websetItemsListTool = createWebsetTool(
|
|
|
105
105
|
"List Webset Items",
|
|
106
106
|
"List items in a webset with optional pagination.",
|
|
107
107
|
z.object({
|
|
108
|
-
webset_id: z.string().describe("
|
|
109
|
-
limit: z.number().describe("
|
|
110
|
-
offset: z.number().describe("
|
|
108
|
+
webset_id: z.string().describe("webset id"),
|
|
109
|
+
limit: z.number().describe("max items").optional(),
|
|
110
|
+
offset: z.number().describe("offset").optional(),
|
|
111
111
|
}),
|
|
112
112
|
"list_webset_items",
|
|
113
113
|
);
|
|
@@ -117,8 +117,8 @@ const websetItemGetTool = createWebsetTool(
|
|
|
117
117
|
"Get Webset Item",
|
|
118
118
|
"Get a specific item from a webset.",
|
|
119
119
|
z.object({
|
|
120
|
-
webset_id: z.string().describe("
|
|
121
|
-
item_id: z.string().describe("
|
|
120
|
+
webset_id: z.string().describe("webset id"),
|
|
121
|
+
item_id: z.string().describe("item id"),
|
|
122
122
|
}),
|
|
123
123
|
"get_item",
|
|
124
124
|
);
|
|
@@ -129,8 +129,8 @@ const websetSearchCreateTool = createWebsetTool(
|
|
|
129
129
|
"Create Webset Search",
|
|
130
130
|
"Create a new search within a webset.",
|
|
131
131
|
z.object({
|
|
132
|
-
webset_id: z.string().describe("
|
|
133
|
-
query: z.string().describe("
|
|
132
|
+
webset_id: z.string().describe("webset id"),
|
|
133
|
+
query: z.string().describe("search query"),
|
|
134
134
|
}),
|
|
135
135
|
"create_search",
|
|
136
136
|
);
|
|
@@ -140,8 +140,8 @@ const websetSearchGetTool = createWebsetTool(
|
|
|
140
140
|
"Get Webset Search",
|
|
141
141
|
"Get the status and results of a webset search.",
|
|
142
142
|
z.object({
|
|
143
|
-
webset_id: z.string().describe("
|
|
144
|
-
search_id: z.string().describe("
|
|
143
|
+
webset_id: z.string().describe("webset id"),
|
|
144
|
+
search_id: z.string().describe("search id"),
|
|
145
145
|
}),
|
|
146
146
|
"get_search",
|
|
147
147
|
);
|
|
@@ -151,8 +151,8 @@ const websetSearchCancelTool = createWebsetTool(
|
|
|
151
151
|
"Cancel Webset Search",
|
|
152
152
|
"Cancel a running webset search.",
|
|
153
153
|
z.object({
|
|
154
|
-
webset_id: z.string().describe("
|
|
155
|
-
search_id: z.string().describe("
|
|
154
|
+
webset_id: z.string().describe("webset id"),
|
|
155
|
+
search_id: z.string().describe("search id"),
|
|
156
156
|
}),
|
|
157
157
|
"cancel_search",
|
|
158
158
|
);
|
|
@@ -163,9 +163,9 @@ const websetEnrichmentCreateTool = createWebsetTool(
|
|
|
163
163
|
"Create Enrichment",
|
|
164
164
|
"Create a new enrichment task for a webset.",
|
|
165
165
|
z.object({
|
|
166
|
-
webset_id: z.string().describe("
|
|
167
|
-
name: z.string().describe("
|
|
168
|
-
prompt: z.string().describe("
|
|
166
|
+
webset_id: z.string().describe("webset id"),
|
|
167
|
+
name: z.string().describe("enrichment name"),
|
|
168
|
+
prompt: z.string().describe("enrichment prompt"),
|
|
169
169
|
}),
|
|
170
170
|
"create_enrichment",
|
|
171
171
|
);
|
|
@@ -175,8 +175,8 @@ const websetEnrichmentGetTool = createWebsetTool(
|
|
|
175
175
|
"Get Enrichment",
|
|
176
176
|
"Get the status and results of an enrichment task.",
|
|
177
177
|
z.object({
|
|
178
|
-
webset_id: z.string().describe("
|
|
179
|
-
enrichment_id: z.string().describe("
|
|
178
|
+
webset_id: z.string().describe("webset id"),
|
|
179
|
+
enrichment_id: z.string().describe("enrichment id"),
|
|
180
180
|
}),
|
|
181
181
|
"get_enrichment",
|
|
182
182
|
);
|
|
@@ -186,10 +186,10 @@ const websetEnrichmentUpdateTool = createWebsetTool(
|
|
|
186
186
|
"Update Enrichment",
|
|
187
187
|
"Update an enrichment's name or prompt.",
|
|
188
188
|
z.object({
|
|
189
|
-
webset_id: z.string().describe("
|
|
190
|
-
enrichment_id: z.string().describe("
|
|
191
|
-
name: z.string().describe("
|
|
192
|
-
prompt: z.string().describe("
|
|
189
|
+
webset_id: z.string().describe("webset id"),
|
|
190
|
+
enrichment_id: z.string().describe("enrichment id"),
|
|
191
|
+
name: z.string().describe("new name").optional(),
|
|
192
|
+
prompt: z.string().describe("new prompt").optional(),
|
|
193
193
|
}),
|
|
194
194
|
"update_enrichment",
|
|
195
195
|
);
|
|
@@ -199,8 +199,8 @@ const websetEnrichmentDeleteTool = createWebsetTool(
|
|
|
199
199
|
"Delete Enrichment",
|
|
200
200
|
"Delete an enrichment task.",
|
|
201
201
|
z.object({
|
|
202
|
-
webset_id: z.string().describe("
|
|
203
|
-
enrichment_id: z.string().describe("
|
|
202
|
+
webset_id: z.string().describe("webset id"),
|
|
203
|
+
enrichment_id: z.string().describe("enrichment id"),
|
|
204
204
|
}),
|
|
205
205
|
"delete_enrichment",
|
|
206
206
|
);
|
|
@@ -210,8 +210,8 @@ const websetEnrichmentCancelTool = createWebsetTool(
|
|
|
210
210
|
"Cancel Enrichment",
|
|
211
211
|
"Cancel a running enrichment task.",
|
|
212
212
|
z.object({
|
|
213
|
-
webset_id: z.string().describe("
|
|
214
|
-
enrichment_id: z.string().describe("
|
|
213
|
+
webset_id: z.string().describe("webset id"),
|
|
214
|
+
enrichment_id: z.string().describe("enrichment id"),
|
|
215
215
|
}),
|
|
216
216
|
"cancel_enrichment",
|
|
217
217
|
);
|
|
@@ -222,8 +222,8 @@ const websetMonitorCreateTool = createWebsetTool(
|
|
|
222
222
|
"Create Monitor",
|
|
223
223
|
"Create a monitoring task for a webset with optional webhook notifications.",
|
|
224
224
|
z.object({
|
|
225
|
-
webset_id: z.string().describe("
|
|
226
|
-
webhook_url: z.string().describe("
|
|
225
|
+
webset_id: z.string().describe("webset id"),
|
|
226
|
+
webhook_url: z.string().describe("webhook url").optional(),
|
|
227
227
|
}),
|
|
228
228
|
"create_monitor",
|
|
229
229
|
);
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* `@sinclair/typebox` directly in their own package.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { areJsonValuesEqual } from "@oh-my-pi/pi-ai/utils/schema";
|
|
24
|
+
import { areJsonValuesEqual, zodToWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
|
|
25
25
|
import {
|
|
26
26
|
type ZodArray,
|
|
27
27
|
type ZodEnum,
|
|
@@ -104,19 +104,46 @@ interface ObjectOpts extends Meta {
|
|
|
104
104
|
// Helpers
|
|
105
105
|
// ---------------------------------------------------------------------------
|
|
106
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Stamp a non-enumerable `toJSON()` on a schema so `JSON.stringify(schema)`
|
|
109
|
+
* yields a clean draft 2020-12 JSON Schema — matching real TypeBox semantics
|
|
110
|
+
* where the schema object IS already a JSON Schema. Without this, an extension
|
|
111
|
+
* author who serialises the schema across any JSON boundary (worker
|
|
112
|
+
* postMessage, MCP transport, config persistence, network hop, structuredClone
|
|
113
|
+
* fallback) ships the raw Zod internals (`def`, `_zod`, object-shaped `enum`,
|
|
114
|
+
* `"type":"enum"`) — neither valid JSON Schema nor parseable Zod. See
|
|
115
|
+
* issue #1101 for the symptoms when this leaks into a tool's `input_schema`.
|
|
116
|
+
*
|
|
117
|
+
* Idempotent: re-stamping the same instance is a no-op.
|
|
118
|
+
*/
|
|
119
|
+
function wire<T extends ZodType>(schema: T): T {
|
|
120
|
+
if (!Object.hasOwn(schema as object, "toJSON")) {
|
|
121
|
+
Object.defineProperty(schema as object, "toJSON", {
|
|
122
|
+
value: function toJSON(this: ZodType) {
|
|
123
|
+
return zodToWireSchema(this);
|
|
124
|
+
},
|
|
125
|
+
enumerable: false,
|
|
126
|
+
writable: true,
|
|
127
|
+
configurable: true,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return schema;
|
|
131
|
+
}
|
|
132
|
+
|
|
107
133
|
function withMeta<T extends ZodType>(schema: T, opts: Meta | undefined): T {
|
|
108
|
-
if (!opts) return schema;
|
|
109
134
|
let out: ZodType = schema;
|
|
110
|
-
if (
|
|
111
|
-
|
|
135
|
+
if (opts) {
|
|
136
|
+
if (typeof opts.description === "string") out = out.describe(opts.description);
|
|
137
|
+
if ("default" in opts) out = out.default(opts.default as never) as unknown as ZodType;
|
|
112
138
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
139
|
+
const metadata: Record<string, unknown> = {};
|
|
140
|
+
for (const key in opts) {
|
|
141
|
+
if (key === "description" || key === "default" || key === "additionalProperties") continue;
|
|
142
|
+
metadata[key] = opts[key];
|
|
143
|
+
}
|
|
144
|
+
if (Object.keys(metadata).length > 0) out = out.meta(metadata);
|
|
117
145
|
}
|
|
118
|
-
|
|
119
|
-
return out as T;
|
|
146
|
+
return wire(out as T);
|
|
120
147
|
}
|
|
121
148
|
|
|
122
149
|
// ---------------------------------------------------------------------------
|
|
@@ -313,7 +340,8 @@ function tRecord<V extends ZodType>(key: ZodType, value: V, opts?: Meta): ZodTyp
|
|
|
313
340
|
}
|
|
314
341
|
|
|
315
342
|
function tOptional<E extends ZodType>(schema: E, _opts?: Meta): ZodOptional<E> {
|
|
316
|
-
|
|
343
|
+
if (isOptional(schema)) return wire(schema as unknown as ZodOptional<E>);
|
|
344
|
+
return wire(schema.optional() as ZodOptional<E>);
|
|
317
345
|
}
|
|
318
346
|
|
|
319
347
|
function tNullable<E extends ZodType>(schema: E, opts?: Meta): ZodType {
|
|
@@ -322,27 +350,26 @@ function tNullable<E extends ZodType>(schema: E, opts?: Meta): ZodType {
|
|
|
322
350
|
|
|
323
351
|
function tReadonly<E extends ZodType>(schema: E): E {
|
|
324
352
|
// TypeBox's `Type.Readonly` is purely a marker; runtime parsing is identical.
|
|
325
|
-
return schema;
|
|
353
|
+
return wire(schema);
|
|
326
354
|
}
|
|
327
355
|
|
|
328
356
|
function tPartial<P extends ZodRawShape>(obj: ZodObject<P>): ZodObject<P> {
|
|
329
|
-
return obj.partial() as unknown as ZodObject<P
|
|
357
|
+
return wire(obj.partial() as unknown as ZodObject<P>);
|
|
330
358
|
}
|
|
331
359
|
|
|
332
360
|
function tRequired<P extends ZodRawShape>(obj: ZodObject<P>): ZodObject<P> {
|
|
333
|
-
return obj.required() as unknown as ZodObject<P
|
|
361
|
+
return wire(obj.required() as unknown as ZodObject<P>);
|
|
334
362
|
}
|
|
335
363
|
|
|
336
364
|
function tPick<P extends ZodRawShape, K extends keyof P>(obj: ZodObject<P>, keys: readonly K[]): ZodObject<Pick<P, K>> {
|
|
337
365
|
const mask = Object.fromEntries(keys.map(k => [k as string, true]));
|
|
338
|
-
return obj.pick(mask as never) as unknown as ZodObject<Pick<P, K
|
|
366
|
+
return wire(obj.pick(mask as never) as unknown as ZodObject<Pick<P, K>>);
|
|
339
367
|
}
|
|
340
368
|
|
|
341
369
|
function tOmit<P extends ZodRawShape, K extends keyof P>(obj: ZodObject<P>, keys: readonly K[]): ZodObject<Omit<P, K>> {
|
|
342
370
|
const mask = Object.fromEntries(keys.map(k => [k as string, true]));
|
|
343
|
-
return obj.omit(mask as never) as unknown as ZodObject<Omit<P, K
|
|
371
|
+
return wire(obj.omit(mask as never) as unknown as ZodObject<Omit<P, K>>);
|
|
344
372
|
}
|
|
345
|
-
|
|
346
373
|
function tComposite(objects: readonly ZodObject<ZodRawShape>[], opts?: Meta): ZodObject<ZodRawShape> {
|
|
347
374
|
// `Type.Composite([...])` flattens every object schema into one object schema
|
|
348
375
|
// rather than producing an intersection. Mirror that via repeated `extend`.
|
|
@@ -15,9 +15,9 @@ import { completionBudgetReport, remainingTokens } from "../runtime";
|
|
|
15
15
|
import type { Goal, GoalStatus, GoalToolDetails } from "../state";
|
|
16
16
|
|
|
17
17
|
const goalSchema = z.object({
|
|
18
|
-
op: z.
|
|
19
|
-
objective: z.string().describe("
|
|
20
|
-
token_budget: z.number().int().describe("
|
|
18
|
+
op: z.enum(["create", "get", "complete"]).describe("goal operation"),
|
|
19
|
+
objective: z.string().describe("goal objective").optional(),
|
|
20
|
+
token_budget: z.number().int().describe("token budget").optional(),
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
export type GoalToolInput = z.infer<typeof goalSchema>;
|
package/src/index.ts
CHANGED
|
@@ -2,9 +2,6 @@ import { HookEditorComponent, HookInputComponent, HookSelectorComponent } from "
|
|
|
2
2
|
|
|
3
3
|
// Core session management
|
|
4
4
|
|
|
5
|
-
// TypeBox helper for string enums (convenience for custom tools)
|
|
6
|
-
// Re-export from pi-ai which uses the correct enum-based schema format
|
|
7
|
-
export { StringEnum } from "@oh-my-pi/pi-ai";
|
|
8
5
|
// Re-export TUI components for custom tool rendering
|
|
9
6
|
export { Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
|
|
10
7
|
// Logging
|