@oh-my-pi/pi-coding-agent 3.25.0 → 3.30.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 +19 -0
- package/package.json +4 -4
- package/src/core/tools/complete.ts +2 -4
- package/src/core/tools/jtd-to-json-schema.ts +174 -196
- package/src/core/tools/read.ts +4 -4
- package/src/core/tools/task/executor.ts +146 -20
- package/src/core/tools/task/name-generator.ts +1544 -214
- package/src/core/tools/task/types.ts +19 -5
- package/src/core/tools/task/worker.ts +103 -13
- package/src/core/tools/web-fetch-handlers/academic.test.ts +239 -0
- package/src/core/tools/web-fetch-handlers/artifacthub.ts +210 -0
- package/src/core/tools/web-fetch-handlers/arxiv.ts +84 -0
- package/src/core/tools/web-fetch-handlers/aur.ts +171 -0
- package/src/core/tools/web-fetch-handlers/biorxiv.ts +136 -0
- package/src/core/tools/web-fetch-handlers/bluesky.ts +277 -0
- package/src/core/tools/web-fetch-handlers/brew.ts +173 -0
- package/src/core/tools/web-fetch-handlers/business.test.ts +82 -0
- package/src/core/tools/web-fetch-handlers/cheatsh.ts +73 -0
- package/src/core/tools/web-fetch-handlers/chocolatey.ts +153 -0
- package/src/core/tools/web-fetch-handlers/coingecko.ts +179 -0
- package/src/core/tools/web-fetch-handlers/crates-io.ts +123 -0
- package/src/core/tools/web-fetch-handlers/dev-platforms.test.ts +254 -0
- package/src/core/tools/web-fetch-handlers/devto.ts +173 -0
- package/src/core/tools/web-fetch-handlers/discogs.ts +303 -0
- package/src/core/tools/web-fetch-handlers/dockerhub.ts +156 -0
- package/src/core/tools/web-fetch-handlers/documentation.test.ts +85 -0
- package/src/core/tools/web-fetch-handlers/finance-media.test.ts +144 -0
- package/src/core/tools/web-fetch-handlers/git-hosting.test.ts +272 -0
- package/src/core/tools/web-fetch-handlers/github-gist.ts +64 -0
- package/src/core/tools/web-fetch-handlers/github.ts +424 -0
- package/src/core/tools/web-fetch-handlers/gitlab.ts +444 -0
- package/src/core/tools/web-fetch-handlers/go-pkg.ts +271 -0
- package/src/core/tools/web-fetch-handlers/hackage.ts +89 -0
- package/src/core/tools/web-fetch-handlers/hackernews.ts +208 -0
- package/src/core/tools/web-fetch-handlers/hex.ts +121 -0
- package/src/core/tools/web-fetch-handlers/huggingface.ts +385 -0
- package/src/core/tools/web-fetch-handlers/iacr.ts +82 -0
- package/src/core/tools/web-fetch-handlers/index.ts +69 -0
- package/src/core/tools/web-fetch-handlers/lobsters.ts +186 -0
- package/src/core/tools/web-fetch-handlers/mastodon.ts +302 -0
- package/src/core/tools/web-fetch-handlers/maven.ts +147 -0
- package/src/core/tools/web-fetch-handlers/mdn.ts +174 -0
- package/src/core/tools/web-fetch-handlers/media.test.ts +138 -0
- package/src/core/tools/web-fetch-handlers/metacpan.ts +247 -0
- package/src/core/tools/web-fetch-handlers/npm.ts +107 -0
- package/src/core/tools/web-fetch-handlers/nuget.ts +201 -0
- package/src/core/tools/web-fetch-handlers/nvd.ts +238 -0
- package/src/core/tools/web-fetch-handlers/opencorporates.ts +273 -0
- package/src/core/tools/web-fetch-handlers/openlibrary.ts +313 -0
- package/src/core/tools/web-fetch-handlers/osv.ts +184 -0
- package/src/core/tools/web-fetch-handlers/package-managers-2.test.ts +199 -0
- package/src/core/tools/web-fetch-handlers/package-managers.test.ts +171 -0
- package/src/core/tools/web-fetch-handlers/package-registries.test.ts +259 -0
- package/src/core/tools/web-fetch-handlers/packagist.ts +170 -0
- package/src/core/tools/web-fetch-handlers/pub-dev.ts +185 -0
- package/src/core/tools/web-fetch-handlers/pubmed.ts +174 -0
- package/src/core/tools/web-fetch-handlers/pypi.ts +125 -0
- package/src/core/tools/web-fetch-handlers/readthedocs.ts +122 -0
- package/src/core/tools/web-fetch-handlers/reddit.ts +100 -0
- package/src/core/tools/web-fetch-handlers/repology.ts +257 -0
- package/src/core/tools/web-fetch-handlers/research.test.ts +107 -0
- package/src/core/tools/web-fetch-handlers/rfc.ts +205 -0
- package/src/core/tools/web-fetch-handlers/rubygems.ts +112 -0
- package/src/core/tools/web-fetch-handlers/sec-edgar.ts +269 -0
- package/src/core/tools/web-fetch-handlers/security.test.ts +103 -0
- package/src/core/tools/web-fetch-handlers/semantic-scholar.ts +190 -0
- package/src/core/tools/web-fetch-handlers/social-extended.test.ts +192 -0
- package/src/core/tools/web-fetch-handlers/social.test.ts +259 -0
- package/src/core/tools/web-fetch-handlers/spotify.ts +218 -0
- package/src/core/tools/web-fetch-handlers/stackexchange.test.ts +120 -0
- package/src/core/tools/web-fetch-handlers/stackoverflow.ts +123 -0
- package/src/core/tools/web-fetch-handlers/standards.test.ts +122 -0
- package/src/core/tools/web-fetch-handlers/terraform.ts +296 -0
- package/src/core/tools/web-fetch-handlers/tldr.ts +47 -0
- package/src/core/tools/web-fetch-handlers/twitter.ts +84 -0
- package/src/core/tools/web-fetch-handlers/types.ts +163 -0
- package/src/core/tools/web-fetch-handlers/utils.ts +91 -0
- package/src/core/tools/web-fetch-handlers/vimeo.ts +152 -0
- package/src/core/tools/web-fetch-handlers/wikidata.ts +349 -0
- package/src/core/tools/web-fetch-handlers/wikipedia.test.ts +73 -0
- package/src/core/tools/web-fetch-handlers/wikipedia.ts +91 -0
- package/src/core/tools/web-fetch-handlers/youtube.test.ts +198 -0
- package/src/core/tools/web-fetch-handlers/youtube.ts +319 -0
- package/src/core/tools/web-fetch.ts +152 -1324
- package/src/utils/tools-manager.ts +110 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [3.30.0] - 2026-01-07
|
|
6
|
+
### Added
|
|
7
|
+
|
|
8
|
+
- Added environment variable configuration for task limits: `OMP_TASK_MAX_PARALLEL`, `OMP_TASK_MAX_CONCURRENCY`, `OMP_TASK_MAX_OUTPUT_BYTES`, `OMP_TASK_MAX_OUTPUT_LINES`, and `OMP_TASK_MAX_AGENTS_IN_DESCRIPTION`
|
|
9
|
+
- Added specialized web-fetch handlers for 50+ platforms including GitHub, GitLab, npm, PyPI, crates.io, Stack Overflow, Wikipedia, arXiv, PubMed, Hacker News, Reddit, Mastodon, Bluesky, and many more
|
|
10
|
+
- Added automatic yt-dlp installation for YouTube transcript extraction
|
|
11
|
+
- Added YouTube video support with automatic transcript extraction via yt-dlp
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Changed task executor to gracefully handle worker termination with proper cleanup and timeout handling
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Fixed Lobsters front page handler to use correct API endpoint (`/hottest.json` instead of invalid `.json`)
|
|
20
|
+
- Fixed task worker error handling to prevent hanging on worker crashes, uncaught errors, and unhandled rejections
|
|
21
|
+
- Fixed double-stringified JSON output from subagents being returned as escaped strings instead of parsed objects
|
|
22
|
+
- Fixed markitdown tool installation to use automatic tool installer instead of requiring manual installation
|
|
23
|
+
|
|
5
24
|
## [3.25.0] - 2026-01-07
|
|
6
25
|
### Added
|
|
7
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.30.0",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"ompConfig": {
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@mariozechner/pi-ai": "^0.37.4",
|
|
43
|
-
"@oh-my-pi/pi-agent-core": "3.
|
|
44
|
-
"@oh-my-pi/pi-git-tool": "3.
|
|
45
|
-
"@oh-my-pi/pi-tui": "3.
|
|
43
|
+
"@oh-my-pi/pi-agent-core": "3.30.0",
|
|
44
|
+
"@oh-my-pi/pi-git-tool": "3.30.0",
|
|
45
|
+
"@oh-my-pi/pi-tui": "3.30.0",
|
|
46
46
|
"@openai/agents": "^0.3.7",
|
|
47
47
|
"@sinclair/typebox": "^0.34.46",
|
|
48
48
|
"ajv": "^8.17.1",
|
|
@@ -74,7 +74,7 @@ export function createCompleteTool(session: ToolSession) {
|
|
|
74
74
|
const dataSchema = normalizedSchema
|
|
75
75
|
? Type.Unsafe({
|
|
76
76
|
...(normalizedSchema as object),
|
|
77
|
-
description:
|
|
77
|
+
description: `Structured output matching the schema:\n${schemaHint}`,
|
|
78
78
|
})
|
|
79
79
|
: Type.Any({ description: "Structured JSON output (no schema specified)" });
|
|
80
80
|
|
|
@@ -110,9 +110,7 @@ export function createCompleteTool(session: ToolSession) {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
const responseText =
|
|
113
|
-
status === "aborted"
|
|
114
|
-
? `Task aborted: ${params.error || "No reason provided"}`
|
|
115
|
-
: "Completion recorded.";
|
|
113
|
+
status === "aborted" ? `Task aborted: ${params.error || "No reason provided"}` : "Completion recorded.";
|
|
116
114
|
|
|
117
115
|
return {
|
|
118
116
|
content: [{ type: "text", text: responseText }],
|
|
@@ -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/read.ts
CHANGED
|
@@ -311,10 +311,10 @@ async function findReadPathSuggestions(
|
|
|
311
311
|
return { suggestions, scopeLabel, truncated };
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
-
function convertWithMarkitdown(filePath: string): { content: string; ok: boolean; error?: string } {
|
|
315
|
-
const cmd =
|
|
314
|
+
async function convertWithMarkitdown(filePath: string): Promise<{ content: string; ok: boolean; error?: string }> {
|
|
315
|
+
const cmd = await ensureTool("markitdown", true);
|
|
316
316
|
if (!cmd) {
|
|
317
|
-
return { content: "", ok: false, error: "markitdown not found" };
|
|
317
|
+
return { content: "", ok: false, error: "markitdown not found (uv/pip unavailable)" };
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
const result = Bun.spawnSync([cmd, filePath], {
|
|
@@ -449,7 +449,7 @@ export function createReadTool(session: ToolSession): AgentTool<typeof readSchem
|
|
|
449
449
|
}
|
|
450
450
|
} else if (CONVERTIBLE_EXTENSIONS.has(ext)) {
|
|
451
451
|
// Convert document via markitdown
|
|
452
|
-
const result = convertWithMarkitdown(absolutePath);
|
|
452
|
+
const result = await convertWithMarkitdown(absolutePath);
|
|
453
453
|
if (result.ok) {
|
|
454
454
|
// Apply truncation to converted content
|
|
455
455
|
const truncation = truncateHead(result.content);
|