@oh-my-pi/pi-coding-agent 3.25.0 → 3.31.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/CHANGELOG.md +90 -0
- package/package.json +5 -5
- package/src/cli/args.ts +4 -0
- package/src/core/agent-session.ts +29 -2
- package/src/core/bash-executor.ts +2 -1
- package/src/core/custom-commands/bundled/review/index.ts +369 -14
- package/src/core/custom-commands/bundled/wt/index.ts +1 -1
- package/src/core/session-manager.ts +158 -246
- package/src/core/session-storage.ts +379 -0
- package/src/core/settings-manager.ts +155 -4
- package/src/core/system-prompt.ts +62 -64
- package/src/core/tools/ask.ts +5 -4
- package/src/core/tools/bash-interceptor.ts +26 -61
- package/src/core/tools/bash.ts +13 -8
- package/src/core/tools/complete.ts +2 -4
- package/src/core/tools/edit-diff.ts +11 -4
- package/src/core/tools/edit.ts +7 -13
- package/src/core/tools/find.ts +111 -50
- package/src/core/tools/gemini-image.ts +128 -147
- package/src/core/tools/grep.ts +397 -415
- package/src/core/tools/index.test.ts +5 -1
- package/src/core/tools/index.ts +6 -8
- package/src/core/tools/jtd-to-json-schema.ts +174 -196
- package/src/core/tools/ls.ts +12 -10
- package/src/core/tools/lsp/client.ts +58 -9
- package/src/core/tools/lsp/config.ts +205 -656
- package/src/core/tools/lsp/defaults.json +465 -0
- package/src/core/tools/lsp/index.ts +55 -32
- package/src/core/tools/lsp/rust-analyzer.ts +49 -10
- package/src/core/tools/lsp/types.ts +1 -0
- package/src/core/tools/lsp/utils.ts +1 -1
- package/src/core/tools/read.ts +152 -76
- package/src/core/tools/render-utils.ts +70 -10
- package/src/core/tools/review.ts +38 -126
- package/src/core/tools/task/artifacts.ts +5 -4
- package/src/core/tools/task/executor.ts +204 -67
- package/src/core/tools/task/index.ts +129 -92
- package/src/core/tools/task/name-generator.ts +1544 -214
- package/src/core/tools/task/parallel.ts +30 -3
- package/src/core/tools/task/render.ts +85 -39
- package/src/core/tools/task/types.ts +34 -11
- package/src/core/tools/task/worker.ts +152 -27
- package/src/core/tools/web-fetch.ts +220 -1657
- package/src/core/tools/web-scrapers/academic.test.ts +239 -0
- package/src/core/tools/web-scrapers/artifacthub.ts +215 -0
- package/src/core/tools/web-scrapers/arxiv.ts +88 -0
- package/src/core/tools/web-scrapers/aur.ts +175 -0
- package/src/core/tools/web-scrapers/biorxiv.ts +141 -0
- package/src/core/tools/web-scrapers/bluesky.ts +284 -0
- package/src/core/tools/web-scrapers/brew.ts +177 -0
- package/src/core/tools/web-scrapers/business.test.ts +82 -0
- package/src/core/tools/web-scrapers/cheatsh.ts +78 -0
- package/src/core/tools/web-scrapers/chocolatey.ts +158 -0
- package/src/core/tools/web-scrapers/choosealicense.ts +110 -0
- package/src/core/tools/web-scrapers/cisa-kev.ts +100 -0
- package/src/core/tools/web-scrapers/clojars.ts +180 -0
- package/src/core/tools/web-scrapers/coingecko.ts +184 -0
- package/src/core/tools/web-scrapers/crates-io.ts +128 -0
- package/src/core/tools/web-scrapers/crossref.ts +149 -0
- package/src/core/tools/web-scrapers/dev-platforms.test.ts +254 -0
- package/src/core/tools/web-scrapers/devto.ts +177 -0
- package/src/core/tools/web-scrapers/discogs.ts +308 -0
- package/src/core/tools/web-scrapers/discourse.ts +221 -0
- package/src/core/tools/web-scrapers/dockerhub.ts +160 -0
- package/src/core/tools/web-scrapers/documentation.test.ts +85 -0
- package/src/core/tools/web-scrapers/fdroid.ts +158 -0
- package/src/core/tools/web-scrapers/finance-media.test.ts +144 -0
- package/src/core/tools/web-scrapers/firefox-addons.ts +214 -0
- package/src/core/tools/web-scrapers/flathub.ts +239 -0
- package/src/core/tools/web-scrapers/git-hosting.test.ts +272 -0
- package/src/core/tools/web-scrapers/github-gist.ts +68 -0
- package/src/core/tools/web-scrapers/github.ts +455 -0
- package/src/core/tools/web-scrapers/gitlab.ts +456 -0
- package/src/core/tools/web-scrapers/go-pkg.ts +275 -0
- package/src/core/tools/web-scrapers/hackage.ts +94 -0
- package/src/core/tools/web-scrapers/hackernews.ts +208 -0
- package/src/core/tools/web-scrapers/hex.ts +121 -0
- package/src/core/tools/web-scrapers/huggingface.ts +385 -0
- package/src/core/tools/web-scrapers/iacr.ts +86 -0
- package/src/core/tools/web-scrapers/index.ts +250 -0
- package/src/core/tools/web-scrapers/jetbrains-marketplace.ts +169 -0
- package/src/core/tools/web-scrapers/lemmy.ts +220 -0
- package/src/core/tools/web-scrapers/lobsters.ts +186 -0
- package/src/core/tools/web-scrapers/mastodon.ts +310 -0
- package/src/core/tools/web-scrapers/maven.ts +152 -0
- package/src/core/tools/web-scrapers/mdn.ts +174 -0
- package/src/core/tools/web-scrapers/media.test.ts +138 -0
- package/src/core/tools/web-scrapers/metacpan.ts +253 -0
- package/src/core/tools/web-scrapers/musicbrainz.ts +273 -0
- package/src/core/tools/web-scrapers/npm.ts +114 -0
- package/src/core/tools/web-scrapers/nuget.ts +205 -0
- package/src/core/tools/web-scrapers/nvd.ts +243 -0
- package/src/core/tools/web-scrapers/ollama.ts +267 -0
- package/src/core/tools/web-scrapers/open-vsx.ts +119 -0
- package/src/core/tools/web-scrapers/opencorporates.ts +275 -0
- package/src/core/tools/web-scrapers/openlibrary.ts +319 -0
- package/src/core/tools/web-scrapers/orcid.ts +299 -0
- package/src/core/tools/web-scrapers/osv.ts +189 -0
- package/src/core/tools/web-scrapers/package-managers-2.test.ts +199 -0
- package/src/core/tools/web-scrapers/package-managers.test.ts +171 -0
- package/src/core/tools/web-scrapers/package-registries.test.ts +259 -0
- package/src/core/tools/web-scrapers/packagist.ts +174 -0
- package/src/core/tools/web-scrapers/pub-dev.ts +185 -0
- package/src/core/tools/web-scrapers/pubmed.ts +178 -0
- package/src/core/tools/web-scrapers/pypi.ts +129 -0
- package/src/core/tools/web-scrapers/rawg.ts +124 -0
- package/src/core/tools/web-scrapers/readthedocs.ts +126 -0
- package/src/core/tools/web-scrapers/reddit.ts +104 -0
- package/src/core/tools/web-scrapers/repology.ts +262 -0
- package/src/core/tools/web-scrapers/research.test.ts +107 -0
- package/src/core/tools/web-scrapers/rfc.ts +209 -0
- package/src/core/tools/web-scrapers/rubygems.ts +117 -0
- package/src/core/tools/web-scrapers/searchcode.ts +217 -0
- package/src/core/tools/web-scrapers/sec-edgar.ts +274 -0
- package/src/core/tools/web-scrapers/security.test.ts +103 -0
- package/src/core/tools/web-scrapers/semantic-scholar.ts +190 -0
- package/src/core/tools/web-scrapers/snapcraft.ts +200 -0
- package/src/core/tools/web-scrapers/social-extended.test.ts +192 -0
- package/src/core/tools/web-scrapers/social.test.ts +259 -0
- package/src/core/tools/web-scrapers/sourcegraph.ts +373 -0
- package/src/core/tools/web-scrapers/spdx.ts +121 -0
- package/src/core/tools/web-scrapers/spotify.ts +218 -0
- package/src/core/tools/web-scrapers/stackexchange.test.ts +120 -0
- package/src/core/tools/web-scrapers/stackoverflow.ts +124 -0
- package/src/core/tools/web-scrapers/standards.test.ts +122 -0
- package/src/core/tools/web-scrapers/terraform.ts +304 -0
- package/src/core/tools/web-scrapers/tldr.ts +51 -0
- package/src/core/tools/web-scrapers/twitter.ts +96 -0
- package/src/core/tools/web-scrapers/types.ts +234 -0
- package/src/core/tools/web-scrapers/utils.ts +162 -0
- package/src/core/tools/web-scrapers/vimeo.ts +152 -0
- package/src/core/tools/web-scrapers/vscode-marketplace.ts +195 -0
- package/src/core/tools/web-scrapers/w3c.ts +163 -0
- package/src/core/tools/web-scrapers/wikidata.ts +357 -0
- package/src/core/tools/web-scrapers/wikipedia.test.ts +73 -0
- package/src/core/tools/web-scrapers/wikipedia.ts +95 -0
- package/src/core/tools/web-scrapers/youtube.test.ts +198 -0
- package/src/core/tools/web-scrapers/youtube.ts +371 -0
- package/src/core/tools/write.ts +21 -18
- package/src/core/voice.ts +3 -2
- package/src/lib/worktree/collapse.ts +2 -1
- package/src/lib/worktree/git.ts +2 -18
- package/src/main.ts +59 -3
- package/src/modes/interactive/components/extensions/extension-dashboard.ts +33 -19
- package/src/modes/interactive/components/extensions/extension-list.ts +15 -8
- package/src/modes/interactive/components/hook-editor.ts +2 -1
- package/src/modes/interactive/components/model-selector.ts +19 -4
- package/src/modes/interactive/interactive-mode.ts +41 -38
- package/src/modes/interactive/theme/theme.ts +58 -58
- package/src/modes/rpc/rpc-mode.ts +10 -9
- package/src/prompts/review-request.md +27 -0
- package/src/prompts/reviewer.md +64 -68
- package/src/prompts/tools/output.md +22 -3
- package/src/prompts/tools/task.md +32 -33
- package/src/utils/clipboard.ts +2 -1
- package/src/utils/tools-manager.ts +110 -8
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
|
@@ -110,6 +110,8 @@ describe("createTools", () => {
|
|
|
110
110
|
getEditFuzzyMatch: () => true,
|
|
111
111
|
getGitToolEnabled: () => false,
|
|
112
112
|
getBashInterceptorEnabled: () => true,
|
|
113
|
+
getBashInterceptorSimpleLsEnabled: () => true,
|
|
114
|
+
getBashInterceptorRules: () => [],
|
|
113
115
|
},
|
|
114
116
|
});
|
|
115
117
|
const tools = await createTools(session);
|
|
@@ -128,6 +130,8 @@ describe("createTools", () => {
|
|
|
128
130
|
getEditFuzzyMatch: () => true,
|
|
129
131
|
getGitToolEnabled: () => true,
|
|
130
132
|
getBashInterceptorEnabled: () => true,
|
|
133
|
+
getBashInterceptorSimpleLsEnabled: () => true,
|
|
134
|
+
getBashInterceptorRules: () => [],
|
|
131
135
|
},
|
|
132
136
|
});
|
|
133
137
|
const tools = await createTools(session);
|
|
@@ -183,6 +187,6 @@ describe("createTools", () => {
|
|
|
183
187
|
});
|
|
184
188
|
|
|
185
189
|
it("HIDDEN_TOOLS contains review tools", () => {
|
|
186
|
-
expect(Object.keys(HIDDEN_TOOLS).sort()).toEqual(["complete", "report_finding"
|
|
190
|
+
expect(Object.keys(HIDDEN_TOOLS).sort()).toEqual(["complete", "report_finding"]);
|
|
187
191
|
});
|
|
188
192
|
});
|
package/src/core/tools/index.ts
CHANGED
|
@@ -18,13 +18,12 @@ export {
|
|
|
18
18
|
type LspServerStatus,
|
|
19
19
|
type LspToolDetails,
|
|
20
20
|
type LspWarmupResult,
|
|
21
|
-
lspTool,
|
|
22
21
|
warmupLspServers,
|
|
23
22
|
} from "./lsp/index";
|
|
24
23
|
export { createNotebookTool, type NotebookToolDetails } from "./notebook";
|
|
25
24
|
export { createOutputTool, type OutputToolDetails } from "./output";
|
|
26
25
|
export { createReadTool, type ReadToolDetails } from "./read";
|
|
27
|
-
export { reportFindingTool,
|
|
26
|
+
export { reportFindingTool, type SubmitReviewDetails } from "./review";
|
|
28
27
|
export { filterRulebookRules, formatRulesForPrompt, type RulebookToolDetails } from "./rulebook";
|
|
29
28
|
export { BUNDLED_AGENTS, createTaskTool, taskTool } from "./task/index";
|
|
30
29
|
export type { TruncationResult } from "./truncate";
|
|
@@ -53,6 +52,7 @@ export { createWriteTool, type WriteToolDetails } from "./write";
|
|
|
53
52
|
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
54
53
|
import type { Rule } from "../../capability/rule";
|
|
55
54
|
import type { EventBus } from "../event-bus";
|
|
55
|
+
import type { BashInterceptorRule } from "../settings-manager";
|
|
56
56
|
import { createAskTool } from "./ask";
|
|
57
57
|
import { createBashTool } from "./bash";
|
|
58
58
|
import { createCompleteTool } from "./complete";
|
|
@@ -65,7 +65,7 @@ import { createLspTool } from "./lsp/index";
|
|
|
65
65
|
import { createNotebookTool } from "./notebook";
|
|
66
66
|
import { createOutputTool } from "./output";
|
|
67
67
|
import { createReadTool } from "./read";
|
|
68
|
-
import { reportFindingTool
|
|
68
|
+
import { reportFindingTool } from "./review";
|
|
69
69
|
import { createRulebookTool } from "./rulebook";
|
|
70
70
|
import { createTaskTool } from "./task/index";
|
|
71
71
|
import { createWebFetchTool } from "./web-fetch";
|
|
@@ -102,6 +102,8 @@ export interface ToolSession {
|
|
|
102
102
|
getEditFuzzyMatch(): boolean;
|
|
103
103
|
getGitToolEnabled(): boolean;
|
|
104
104
|
getBashInterceptorEnabled(): boolean;
|
|
105
|
+
getBashInterceptorSimpleLsEnabled(): boolean;
|
|
106
|
+
getBashInterceptorRules(): BashInterceptorRule[];
|
|
105
107
|
};
|
|
106
108
|
}
|
|
107
109
|
|
|
@@ -129,7 +131,6 @@ export const BUILTIN_TOOLS: Record<string, ToolFactory> = {
|
|
|
129
131
|
export const HIDDEN_TOOLS: Record<string, ToolFactory> = {
|
|
130
132
|
complete: createCompleteTool,
|
|
131
133
|
report_finding: () => reportFindingTool,
|
|
132
|
-
submit_review: () => submitReviewTool,
|
|
133
134
|
};
|
|
134
135
|
|
|
135
136
|
export type ToolName = keyof typeof BUILTIN_TOOLS;
|
|
@@ -147,10 +148,7 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P
|
|
|
147
148
|
|
|
148
149
|
const entries = requestedTools
|
|
149
150
|
? requestedTools.filter((name) => name in allTools).map((name) => [name, allTools[name]] as const)
|
|
150
|
-
: [
|
|
151
|
-
...Object.entries(BUILTIN_TOOLS),
|
|
152
|
-
...(includeComplete ? ([["complete", HIDDEN_TOOLS.complete]] as const) : []),
|
|
153
|
-
];
|
|
151
|
+
: [...Object.entries(BUILTIN_TOOLS), ...(includeComplete ? ([["complete", HIDDEN_TOOLS.complete]] as const) : [])];
|
|
154
152
|
const results = await Promise.all(entries.map(([, factory]) => factory(session)));
|
|
155
153
|
const tools = results.filter((t): t is Tool => t !== null);
|
|
156
154
|
|
|
@@ -9,211 +9,199 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
type JTDPrimitive =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
| "boolean"
|
|
13
|
+
| "string"
|
|
14
|
+
| "timestamp"
|
|
15
|
+
| "float32"
|
|
16
|
+
| "float64"
|
|
17
|
+
| "int8"
|
|
18
|
+
| "uint8"
|
|
19
|
+
| "int16"
|
|
20
|
+
| "uint16"
|
|
21
|
+
| "int32"
|
|
22
|
+
| "uint32";
|
|
23
23
|
|
|
24
24
|
interface JTDType {
|
|
25
|
-
|
|
25
|
+
type: JTDPrimitive;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
interface JTDEnum {
|
|
29
|
-
|
|
29
|
+
enum: string[];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
interface JTDElements {
|
|
33
|
-
|
|
33
|
+
elements: JTDSchema;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
interface JTDValues {
|
|
37
|
-
|
|
37
|
+
values: JTDSchema;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
interface JTDProperties {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
properties?: Record<string, JTDSchema>;
|
|
42
|
+
optionalProperties?: Record<string, JTDSchema>;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
interface JTDDiscriminator {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
discriminator: string;
|
|
47
|
+
mapping: Record<string, JTDProperties>;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
interface JTDRef {
|
|
51
|
-
|
|
51
|
+
ref: string;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
interface JTDEmpty {}
|
|
55
55
|
|
|
56
|
-
type JTDSchema =
|
|
57
|
-
| JTDType
|
|
58
|
-
| JTDEnum
|
|
59
|
-
| JTDElements
|
|
60
|
-
| JTDValues
|
|
61
|
-
| JTDProperties
|
|
62
|
-
| JTDDiscriminator
|
|
63
|
-
| JTDRef
|
|
64
|
-
| JTDEmpty;
|
|
56
|
+
type JTDSchema = JTDType | JTDEnum | JTDElements | JTDValues | JTDProperties | JTDDiscriminator | JTDRef | JTDEmpty;
|
|
65
57
|
|
|
66
58
|
const primitiveMap: Record<JTDPrimitive, string> = {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
boolean: "boolean",
|
|
60
|
+
string: "string",
|
|
61
|
+
timestamp: "string", // ISO 8601
|
|
62
|
+
float32: "number",
|
|
63
|
+
float64: "number",
|
|
64
|
+
int8: "integer",
|
|
65
|
+
uint8: "integer",
|
|
66
|
+
int16: "integer",
|
|
67
|
+
uint16: "integer",
|
|
68
|
+
int32: "integer",
|
|
69
|
+
uint32: "integer",
|
|
78
70
|
};
|
|
79
71
|
|
|
80
72
|
function isJTDType(schema: unknown): schema is JTDType {
|
|
81
|
-
|
|
73
|
+
return typeof schema === "object" && schema !== null && "type" in schema;
|
|
82
74
|
}
|
|
83
75
|
|
|
84
76
|
function isJTDEnum(schema: unknown): schema is JTDEnum {
|
|
85
|
-
|
|
77
|
+
return typeof schema === "object" && schema !== null && "enum" in schema;
|
|
86
78
|
}
|
|
87
79
|
|
|
88
80
|
function isJTDElements(schema: unknown): schema is JTDElements {
|
|
89
|
-
|
|
81
|
+
return typeof schema === "object" && schema !== null && "elements" in schema;
|
|
90
82
|
}
|
|
91
83
|
|
|
92
84
|
function isJTDValues(schema: unknown): schema is JTDValues {
|
|
93
|
-
|
|
85
|
+
return typeof schema === "object" && schema !== null && "values" in schema;
|
|
94
86
|
}
|
|
95
87
|
|
|
96
88
|
function isJTDProperties(schema: unknown): schema is JTDProperties {
|
|
97
|
-
|
|
98
|
-
typeof schema === "object" &&
|
|
99
|
-
schema !== null &&
|
|
100
|
-
("properties" in schema || "optionalProperties" in schema)
|
|
101
|
-
);
|
|
89
|
+
return typeof schema === "object" && schema !== null && ("properties" in schema || "optionalProperties" in schema);
|
|
102
90
|
}
|
|
103
91
|
|
|
104
92
|
function isJTDDiscriminator(schema: unknown): schema is JTDDiscriminator {
|
|
105
|
-
|
|
93
|
+
return typeof schema === "object" && schema !== null && "discriminator" in schema;
|
|
106
94
|
}
|
|
107
95
|
|
|
108
96
|
function isJTDRef(schema: unknown): schema is JTDRef {
|
|
109
|
-
|
|
97
|
+
return typeof schema === "object" && schema !== null && "ref" in schema;
|
|
110
98
|
}
|
|
111
99
|
|
|
112
100
|
function convertSchema(schema: unknown): unknown {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
101
|
+
if (schema === null || typeof schema !== "object") {
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Type form: { type: "string" } → { type: "string" }
|
|
106
|
+
if (isJTDType(schema)) {
|
|
107
|
+
const jsonType = primitiveMap[schema.type as JTDPrimitive];
|
|
108
|
+
if (!jsonType) {
|
|
109
|
+
return { type: schema.type };
|
|
110
|
+
}
|
|
111
|
+
const result: Record<string, unknown> = { type: jsonType };
|
|
112
|
+
// Add format for timestamp
|
|
113
|
+
if (schema.type === "timestamp") {
|
|
114
|
+
result.format = "date-time";
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Enum form: { enum: ["a", "b"] } → { enum: ["a", "b"] }
|
|
120
|
+
if (isJTDEnum(schema)) {
|
|
121
|
+
return { enum: schema.enum };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Elements form: { elements: { type: "string" } } → { type: "array", items: ... }
|
|
125
|
+
if (isJTDElements(schema)) {
|
|
126
|
+
return {
|
|
127
|
+
type: "array",
|
|
128
|
+
items: convertSchema(schema.elements),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Values form: { values: { type: "string" } } → { type: "object", additionalProperties: ... }
|
|
133
|
+
if (isJTDValues(schema)) {
|
|
134
|
+
return {
|
|
135
|
+
type: "object",
|
|
136
|
+
additionalProperties: convertSchema(schema.values),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Properties form: { properties: {...}, optionalProperties: {...} }
|
|
141
|
+
if (isJTDProperties(schema)) {
|
|
142
|
+
const properties: Record<string, unknown> = {};
|
|
143
|
+
const required: string[] = [];
|
|
144
|
+
|
|
145
|
+
// Required properties
|
|
146
|
+
if (schema.properties) {
|
|
147
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
148
|
+
properties[key] = convertSchema(value);
|
|
149
|
+
required.push(key);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Optional properties
|
|
154
|
+
if (schema.optionalProperties) {
|
|
155
|
+
for (const [key, value] of Object.entries(schema.optionalProperties)) {
|
|
156
|
+
properties[key] = convertSchema(value);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const result: Record<string, unknown> = {
|
|
161
|
+
type: "object",
|
|
162
|
+
properties,
|
|
163
|
+
additionalProperties: false,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
if (required.length > 0) {
|
|
167
|
+
result.required = required;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Discriminator form: { discriminator: "type", mapping: { ... } }
|
|
174
|
+
if (isJTDDiscriminator(schema)) {
|
|
175
|
+
const oneOf: unknown[] = [];
|
|
176
|
+
|
|
177
|
+
for (const [tag, props] of Object.entries(schema.mapping)) {
|
|
178
|
+
const converted = convertSchema(props) as Record<string, unknown>;
|
|
179
|
+
// Add the discriminator property
|
|
180
|
+
const properties = (converted.properties || {}) as Record<string, unknown>;
|
|
181
|
+
properties[schema.discriminator] = { const: tag };
|
|
182
|
+
|
|
183
|
+
const required = ((converted.required as string[]) || []).slice();
|
|
184
|
+
if (!required.includes(schema.discriminator)) {
|
|
185
|
+
required.push(schema.discriminator);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
oneOf.push({
|
|
189
|
+
...converted,
|
|
190
|
+
properties,
|
|
191
|
+
required,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return { oneOf };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Ref form: { ref: "MyType" } → { $ref: "#/$defs/MyType" }
|
|
199
|
+
if (isJTDRef(schema)) {
|
|
200
|
+
return { $ref: `#/$defs/${schema.ref}` };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Empty form: {} → {} (accepts anything)
|
|
204
|
+
return {};
|
|
217
205
|
}
|
|
218
206
|
|
|
219
207
|
/**
|
|
@@ -223,43 +211,33 @@ function convertSchema(schema: unknown): unknown {
|
|
|
223
211
|
* JSON Schema uses: type: "object", type: "array", items, additionalProperties, etc.
|
|
224
212
|
*/
|
|
225
213
|
export function isJTDSchema(schema: unknown): boolean {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return true;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// JTD properties form without type: "object" (JSON Schema requires it)
|
|
258
|
-
if ("properties" in obj && !("type" in obj)) {
|
|
259
|
-
return true;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return false;
|
|
214
|
+
if (schema === null || typeof schema !== "object") {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const obj = schema as Record<string, unknown>;
|
|
219
|
+
|
|
220
|
+
// JTD-specific keywords
|
|
221
|
+
if ("elements" in obj) return true;
|
|
222
|
+
if ("values" in obj) return true;
|
|
223
|
+
if ("optionalProperties" in obj) return true;
|
|
224
|
+
if ("discriminator" in obj) return true;
|
|
225
|
+
if ("ref" in obj) return true;
|
|
226
|
+
|
|
227
|
+
// JTD type primitives (JSON Schema doesn't have int32, float64, etc.)
|
|
228
|
+
if ("type" in obj) {
|
|
229
|
+
const jtdPrimitives = ["timestamp", "float32", "float64", "int8", "uint8", "int16", "uint16", "int32", "uint32"];
|
|
230
|
+
if (jtdPrimitives.includes(obj.type as string)) {
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// JTD properties form without type: "object" (JSON Schema requires it)
|
|
236
|
+
if ("properties" in obj && !("type" in obj)) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return false;
|
|
263
241
|
}
|
|
264
242
|
|
|
265
243
|
/**
|
|
@@ -267,8 +245,8 @@ export function isJTDSchema(schema: unknown): boolean {
|
|
|
267
245
|
* If already JSON Schema, returns as-is.
|
|
268
246
|
*/
|
|
269
247
|
export function jtdToJsonSchema(schema: unknown): unknown {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
248
|
+
if (!isJTDSchema(schema)) {
|
|
249
|
+
return schema;
|
|
250
|
+
}
|
|
251
|
+
return convertSchema(schema);
|
|
274
252
|
}
|
package/src/core/tools/ls.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
2
1
|
import nodePath from "node:path";
|
|
3
2
|
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
4
3
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
@@ -53,23 +52,25 @@ export function createLsTool(session: ToolSession): AgentTool<typeof lsSchema> {
|
|
|
53
52
|
const dirPath = resolveToCwd(path || ".", session.cwd);
|
|
54
53
|
const effectiveLimit = limit ?? DEFAULT_LIMIT;
|
|
55
54
|
|
|
56
|
-
// Check if path exists
|
|
57
|
-
|
|
55
|
+
// Check if path exists and is a directory
|
|
56
|
+
let dirStat: Awaited<ReturnType<Bun.BunFile["stat"]>>;
|
|
57
|
+
try {
|
|
58
|
+
dirStat = await Bun.file(dirPath).stat();
|
|
59
|
+
} catch {
|
|
58
60
|
throw new Error(`Path not found: ${dirPath}`);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
const stat = statSync(dirPath);
|
|
63
|
-
if (!stat.isDirectory()) {
|
|
63
|
+
if (!dirStat.isDirectory()) {
|
|
64
64
|
throw new Error(`Not a directory: ${dirPath}`);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// Read directory entries
|
|
68
68
|
let entries: string[];
|
|
69
69
|
try {
|
|
70
|
-
entries =
|
|
71
|
-
} catch (
|
|
72
|
-
|
|
70
|
+
entries = await Array.fromAsync(new Bun.Glob("*").scan({ cwd: dirPath, dot: true, onlyFiles: false }));
|
|
71
|
+
} catch (error) {
|
|
72
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
73
|
+
throw new Error(`Cannot read directory: ${message}`);
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
// Sort alphabetically (case-insensitive)
|
|
@@ -82,6 +83,7 @@ export function createLsTool(session: ToolSession): AgentTool<typeof lsSchema> {
|
|
|
82
83
|
let fileCount = 0;
|
|
83
84
|
|
|
84
85
|
for (const entry of entries) {
|
|
86
|
+
signal?.throwIfAborted();
|
|
85
87
|
if (results.length >= effectiveLimit) {
|
|
86
88
|
entryLimitReached = true;
|
|
87
89
|
break;
|
|
@@ -92,7 +94,7 @@ export function createLsTool(session: ToolSession): AgentTool<typeof lsSchema> {
|
|
|
92
94
|
let age = "";
|
|
93
95
|
|
|
94
96
|
try {
|
|
95
|
-
const entryStat =
|
|
97
|
+
const entryStat = await Bun.file(fullPath).stat();
|
|
96
98
|
if (entryStat.isDirectory()) {
|
|
97
99
|
suffix = "/";
|
|
98
100
|
dirCount += 1;
|