@molecule/api-ai-tools 1.5.8 → 1.5.9
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/README.md +429 -425
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +5 -2
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +11 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-10-
|
|
6
|
+
Generated: 2026-10-16T00:26:34.364Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -58,6 +58,62 @@ npm install @molecule/api-ai-tools @molecule/api-ai
|
|
|
58
58
|
|
|
59
59
|
### Interfaces
|
|
60
60
|
|
|
61
|
+
#### `NormalizableSchema`
|
|
62
|
+
|
|
63
|
+
The JSON-Schema-ish shape every tool in this package declares.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
interface NormalizableSchema {
|
|
67
|
+
name: string
|
|
68
|
+
parameters?: {
|
|
69
|
+
type?: string
|
|
70
|
+
properties?: Record<string, { type?: string; description?: string }>
|
|
71
|
+
required?: string[]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### `NormalizedInput`
|
|
77
|
+
|
|
78
|
+
The result of normalizing one tool call's input.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface NormalizedInput {
|
|
82
|
+
/** The input to hand the handler, with aliases moved onto the declared names. */
|
|
83
|
+
input: Record<string, unknown>
|
|
84
|
+
/** Declared-required parameters still absent after aliasing. */
|
|
85
|
+
missing: string[]
|
|
86
|
+
/** `alias→declared` pairs that were moved, for logging. */
|
|
87
|
+
aliased: string[]
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### `GuardOptions`
|
|
92
|
+
|
|
93
|
+
Options shared by {@link guardToolExecute} and {@link guardAITool}.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
interface GuardOptions {
|
|
97
|
+
/**
|
|
98
|
+
* Redactor applied to a THROWN error's message before it is returned to the
|
|
99
|
+
* model. Defaults to this package's `redactSecrets`.
|
|
100
|
+
*/
|
|
101
|
+
redactError?: (message: string) => string
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### `ToolSchema`
|
|
106
|
+
|
|
107
|
+
JSON-schema-backed definition for a single agent tool.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
interface ToolSchema {
|
|
111
|
+
name: string
|
|
112
|
+
description: string
|
|
113
|
+
parameters: JSONSchema
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
61
117
|
#### `ExecutionBackend`
|
|
62
118
|
|
|
63
119
|
Abstraction over the execution environment.
|
|
@@ -110,117 +166,6 @@ interface ExecutionBackend {
|
|
|
110
166
|
}
|
|
111
167
|
```
|
|
112
168
|
|
|
113
|
-
#### `FileChangeEvent`
|
|
114
|
-
|
|
115
|
-
Payload emitted when a file is created, modified, or deleted structurally.
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
interface FileChangeEvent {
|
|
119
|
-
type: 'created' | 'modified' | 'deleted'
|
|
120
|
-
path: string
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
#### `FileDiffEvent`
|
|
125
|
-
|
|
126
|
-
Payload emitted when a tracked file changes contents.
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
interface FileDiffEvent {
|
|
130
|
-
path: string
|
|
131
|
-
oldContent: string | null
|
|
132
|
-
newContent: string
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
#### `GuardOptions`
|
|
137
|
-
|
|
138
|
-
Options shared by {@link guardToolExecute} and {@link guardAITool}.
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
interface GuardOptions {
|
|
142
|
-
/**
|
|
143
|
-
* Redactor applied to a THROWN error's message before it is returned to the
|
|
144
|
-
* model. Defaults to this package's `redactSecrets`.
|
|
145
|
-
*/
|
|
146
|
-
redactError?: (message: string) => string
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
#### `NormalizableSchema`
|
|
151
|
-
|
|
152
|
-
The JSON-Schema-ish shape every tool in this package declares.
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
interface NormalizableSchema {
|
|
156
|
-
name: string
|
|
157
|
-
parameters?: {
|
|
158
|
-
type?: string
|
|
159
|
-
properties?: Record<string, { type?: string; description?: string }>
|
|
160
|
-
required?: string[]
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
#### `NormalizedInput`
|
|
166
|
-
|
|
167
|
-
The result of normalizing one tool call's input.
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
interface NormalizedInput {
|
|
171
|
-
/** The input to hand the handler, with aliases moved onto the declared names. */
|
|
172
|
-
input: Record<string, unknown>
|
|
173
|
-
/** Declared-required parameters still absent after aliasing. */
|
|
174
|
-
missing: string[]
|
|
175
|
-
/** `alias→declared` pairs that were moved, for logging. */
|
|
176
|
-
aliased: string[]
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
#### `PromptContext`
|
|
181
|
-
|
|
182
|
-
Context for building a composable system prompt.
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
185
|
-
interface PromptContext {
|
|
186
|
-
/** Agent identity (e.g. 'Synthase', 'Polish Agent'). */
|
|
187
|
-
agentName: string
|
|
188
|
-
|
|
189
|
-
/** Project root path. */
|
|
190
|
-
projectRoot: string
|
|
191
|
-
|
|
192
|
-
/** Names of available tools (for the tool listing section). */
|
|
193
|
-
tools: string[]
|
|
194
|
-
|
|
195
|
-
/** Project-specific rules (AGENTS.md or CLAUDE.md content). */
|
|
196
|
-
projectDocs?: string
|
|
197
|
-
|
|
198
|
-
/** Additional skill/reference content to inject. */
|
|
199
|
-
skills?: string[]
|
|
200
|
-
|
|
201
|
-
/** Discovered skills to list in the prompt (use load_skill to read on demand). */
|
|
202
|
-
discoveredSkills?: SkillEntry[]
|
|
203
|
-
|
|
204
|
-
/** Custom sections to append to the prompt. */
|
|
205
|
-
customSections?: string[]
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
#### `SkillEntry`
|
|
210
|
-
|
|
211
|
-
Metadata for a discovered skill (used in PromptContext).
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
interface SkillEntry {
|
|
215
|
-
/** Skill name. */
|
|
216
|
-
name: string
|
|
217
|
-
/** Short description. */
|
|
218
|
-
description: string
|
|
219
|
-
/** Relative path to the SKILL.md file. */
|
|
220
|
-
path: string
|
|
221
|
-
}
|
|
222
|
-
```
|
|
223
|
-
|
|
224
169
|
#### `ToolBuildConfig`
|
|
225
170
|
|
|
226
171
|
Configuration for building the tool set.
|
|
@@ -308,15 +253,70 @@ interface ToolBuildConfig {
|
|
|
308
253
|
}
|
|
309
254
|
```
|
|
310
255
|
|
|
311
|
-
#### `
|
|
256
|
+
#### `FileDiffEvent`
|
|
312
257
|
|
|
313
|
-
|
|
258
|
+
Payload emitted when a tracked file changes contents.
|
|
314
259
|
|
|
315
260
|
```typescript
|
|
316
|
-
interface
|
|
261
|
+
interface FileDiffEvent {
|
|
262
|
+
path: string
|
|
263
|
+
oldContent: string | null
|
|
264
|
+
newContent: string
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### `FileChangeEvent`
|
|
269
|
+
|
|
270
|
+
Payload emitted when a file is created, modified, or deleted structurally.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
interface FileChangeEvent {
|
|
274
|
+
type: 'created' | 'modified' | 'deleted'
|
|
275
|
+
path: string
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### `SkillEntry`
|
|
280
|
+
|
|
281
|
+
Metadata for a discovered skill (used in PromptContext).
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
interface SkillEntry {
|
|
285
|
+
/** Skill name. */
|
|
317
286
|
name: string
|
|
287
|
+
/** Short description. */
|
|
318
288
|
description: string
|
|
319
|
-
|
|
289
|
+
/** Relative path to the SKILL.md file. */
|
|
290
|
+
path: string
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### `PromptContext`
|
|
295
|
+
|
|
296
|
+
Context for building a composable system prompt.
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
interface PromptContext {
|
|
300
|
+
/** Agent identity (e.g. 'Synthase', 'Polish Agent'). */
|
|
301
|
+
agentName: string
|
|
302
|
+
|
|
303
|
+
/** Project root path. */
|
|
304
|
+
projectRoot: string
|
|
305
|
+
|
|
306
|
+
/** Names of available tools (for the tool listing section). */
|
|
307
|
+
tools: string[]
|
|
308
|
+
|
|
309
|
+
/** Project-specific rules (AGENTS.md or CLAUDE.md content). */
|
|
310
|
+
projectDocs?: string
|
|
311
|
+
|
|
312
|
+
/** Additional skill/reference content to inject. */
|
|
313
|
+
skills?: string[]
|
|
314
|
+
|
|
315
|
+
/** Discovered skills to list in the prompt (use load_skill to read on demand). */
|
|
316
|
+
discoveredSkills?: SkillEntry[]
|
|
317
|
+
|
|
318
|
+
/** Custom sections to append to the prompt. */
|
|
319
|
+
customSections?: string[]
|
|
320
320
|
}
|
|
321
321
|
```
|
|
322
322
|
|
|
@@ -338,112 +338,117 @@ A tool call the handler refuses with a message meant for the model as is —
|
|
|
338
338
|
thrown from deep inside a handler (a path check), returned by the guard as the
|
|
339
339
|
call's `error` without the generic "check your parameters" wrapping.
|
|
340
340
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
```typescript
|
|
342
|
+
class ToolInputError extends Error {}
|
|
343
|
+
```
|
|
344
344
|
|
|
345
|
-
|
|
345
|
+
### Functions
|
|
346
346
|
|
|
347
|
-
|
|
347
|
+
#### `createLocalBackend(projectRoot)`
|
|
348
348
|
|
|
349
|
-
|
|
350
|
-
- Available tools listing
|
|
351
|
-
- Coding best practices
|
|
352
|
-
- Tool argument formatting guidance
|
|
353
|
-
- Project docs (if provided)
|
|
354
|
-
- Discovered skills listing (if provided)
|
|
355
|
-
- Inline skills (if provided)
|
|
356
|
-
- Custom sections (if provided)
|
|
349
|
+
Create an ExecutionBackend that operates on the local filesystem.
|
|
357
350
|
|
|
358
351
|
```typescript
|
|
359
|
-
function
|
|
352
|
+
function createLocalBackend(projectRoot: string): ExecutionBackend
|
|
360
353
|
```
|
|
361
354
|
|
|
362
|
-
- `
|
|
355
|
+
- `projectRoot` — Absolute path to the project root directory
|
|
363
356
|
|
|
364
|
-
**Returns:**
|
|
357
|
+
**Returns:** A backend wired to `fs/promises` and guarded subprocess calls.
|
|
365
358
|
|
|
366
|
-
#### `
|
|
359
|
+
#### `createSandboxBackend(sandbox, projectRoot)`
|
|
367
360
|
|
|
368
|
-
|
|
361
|
+
Create an ExecutionBackend that delegates to a Docker sandbox instance.
|
|
362
|
+
The sandbox.exec method is inherently safe — it runs inside an isolated Docker container.
|
|
369
363
|
|
|
370
364
|
```typescript
|
|
371
|
-
function
|
|
365
|
+
function createSandboxBackend(sandbox: SandboxLike, projectRoot?: string): ExecutionBackend
|
|
372
366
|
```
|
|
373
367
|
|
|
374
|
-
- `
|
|
375
|
-
- `
|
|
368
|
+
- `sandbox` — A running Sandbox instance from `@molecule/api-code-sandbox`
|
|
369
|
+
- `projectRoot` — Root directory inside the sandbox (default: '/workspace')
|
|
376
370
|
|
|
377
|
-
**Returns:**
|
|
371
|
+
**Returns:** A backend that proxies all filesystem calls into the sandbox.
|
|
378
372
|
|
|
379
|
-
#### `
|
|
373
|
+
#### `normalizeToolInput(schema, raw)`
|
|
380
374
|
|
|
381
|
-
|
|
375
|
+
Move known aliases onto the declared parameter names and report what is still
|
|
376
|
+
missing. Unknown keys are left in place — handlers ignore them, and dropping
|
|
377
|
+
them would hide a model's intent from anything reading the call log.
|
|
382
378
|
|
|
383
379
|
```typescript
|
|
384
|
-
function
|
|
380
|
+
function normalizeToolInput(schema: NormalizableSchema, raw: unknown): NormalizedInput
|
|
385
381
|
```
|
|
386
382
|
|
|
387
|
-
- `
|
|
383
|
+
- `schema` — The tool's declared schema.
|
|
384
|
+
- `raw` — Whatever the model sent as the tool input.
|
|
388
385
|
|
|
389
|
-
**Returns:**
|
|
386
|
+
**Returns:** The normalized input plus the missing-required and aliased lists.
|
|
390
387
|
|
|
391
|
-
#### `
|
|
388
|
+
#### `missingParamError(schema, input, missing)`
|
|
392
389
|
|
|
393
|
-
|
|
390
|
+
The error a tool returns when a required parameter is still absent after
|
|
391
|
+
aliasing. Model-facing, so it names the right parameter, what was actually
|
|
392
|
+
sent, and the shape of a correct call — everything needed to fix it in one
|
|
393
|
+
turn instead of concluding the tool is broken.
|
|
394
394
|
|
|
395
395
|
```typescript
|
|
396
|
-
function
|
|
396
|
+
function missingParamError(
|
|
397
|
+
schema: NormalizableSchema,
|
|
398
|
+
input: Record<string, unknown>,
|
|
399
|
+
missing: string[],
|
|
400
|
+
): string
|
|
397
401
|
```
|
|
398
402
|
|
|
399
|
-
- `
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
#### `createSandboxBackend(sandbox, projectRoot)`
|
|
404
|
-
|
|
405
|
-
Create an ExecutionBackend that delegates to a Docker sandbox instance.
|
|
406
|
-
The sandbox.exec method is inherently safe — it runs inside an isolated Docker container.
|
|
407
|
-
|
|
408
|
-
```typescript
|
|
409
|
-
function createSandboxBackend(sandbox: SandboxLike, projectRoot?: string): ExecutionBackend
|
|
410
|
-
```
|
|
403
|
+
- `schema` — The tool's declared schema.
|
|
404
|
+
- `input` — The normalized input (used to list the keys that were sent).
|
|
405
|
+
- `missing` — The required parameters still absent.
|
|
411
406
|
|
|
412
|
-
|
|
413
|
-
- `projectRoot` — Root directory inside the sandbox (default: '/workspace')
|
|
407
|
+
**Returns:** A single-sentence-per-clause error string.
|
|
414
408
|
|
|
415
|
-
|
|
409
|
+
#### `guardToolExecute(schema, impl)`
|
|
416
410
|
|
|
417
|
-
|
|
411
|
+
Wrap a tool handler so every call is normalized first and a handler that
|
|
412
|
+
THROWS returns something the model can act on.
|
|
418
413
|
|
|
419
|
-
The
|
|
420
|
-
|
|
421
|
-
|
|
414
|
+
The guard deliberately does NOT pre-empt the handler when a required
|
|
415
|
+
parameter looks absent: several handlers accept a documented older shape
|
|
416
|
+
(`edit_file`'s top-level `old_string`/`new_string`) or answer a missing
|
|
417
|
+
parameter with far better guidance than a generic message could (`edit_file`
|
|
418
|
+
telling the model to re-read the file). It steps in only where the handler
|
|
419
|
+
would otherwise crash — and when it does, a still-missing required parameter
|
|
420
|
+
is the accurate diagnosis for that crash, so it is reported as one.
|
|
422
421
|
|
|
423
422
|
```typescript
|
|
424
|
-
function
|
|
423
|
+
function guardToolExecute(
|
|
424
|
+
schema: NormalizableSchema,
|
|
425
|
+
impl: (input: Record<string, unknown>, ...rest: never[]) => Promise<unknown>,
|
|
426
|
+
options?: GuardOptions,
|
|
427
|
+
): (input: unknown, ...rest: never[]) => Promise<unknown>
|
|
425
428
|
```
|
|
426
429
|
|
|
427
|
-
- `
|
|
428
|
-
- `
|
|
430
|
+
- `schema` — The tool's declared schema.
|
|
431
|
+
- `impl` — The raw handler.
|
|
429
432
|
|
|
430
|
-
**Returns:**
|
|
433
|
+
**Returns:** A handler with the same signature, guarded.
|
|
431
434
|
|
|
432
|
-
#### `
|
|
435
|
+
#### `guardAITool(tool)`
|
|
433
436
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
437
|
+
Apply {@link guardToolExecute} to a ready-made tool object (the
|
|
438
|
+
`@molecule/api-ai` `AITool` shape: `{ name, description, parameters,
|
|
439
|
+
execute }`), returning a copy whose `execute` is guarded.
|
|
440
|
+
|
|
441
|
+
Use it at the point a consumer hands its full tool list to the model, so
|
|
442
|
+
tools built outside this package get the same treatment as the ones built
|
|
443
|
+
inside it.
|
|
438
444
|
|
|
439
445
|
```typescript
|
|
440
|
-
function
|
|
446
|
+
function guardAITool(tool: T, options?: GuardOptions): T
|
|
441
447
|
```
|
|
442
448
|
|
|
443
|
-
- `
|
|
444
|
-
- `path` — The resolved path that was targeted.
|
|
449
|
+
- `tool` — The tool to guard.
|
|
445
450
|
|
|
446
|
-
**Returns:**
|
|
451
|
+
**Returns:** A copy with a guarded `execute`.
|
|
447
452
|
|
|
448
453
|
#### `discoverSkills(backend)`
|
|
449
454
|
|
|
@@ -460,139 +465,141 @@ function discoverSkills(backend: ExecutionBackend): Promise<SkillEntry[]>
|
|
|
460
465
|
|
|
461
466
|
**Returns:** Array of discovered skills with name, description, and path
|
|
462
467
|
|
|
463
|
-
#### `
|
|
468
|
+
#### `buildAgentPrompt(ctx)`
|
|
464
469
|
|
|
465
|
-
|
|
466
|
-
`@molecule/api-ai` `AITool` shape: `{ name, description, parameters,
|
|
467
|
-
execute }`), returning a copy whose `execute` is guarded.
|
|
470
|
+
Build a coding-focused system prompt from composable sections.
|
|
468
471
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
+
Returns a string that includes:
|
|
473
|
+
|
|
474
|
+
- Agent identity
|
|
475
|
+
- Available tools listing
|
|
476
|
+
- Coding best practices
|
|
477
|
+
- Tool argument formatting guidance
|
|
478
|
+
- Project docs (if provided)
|
|
479
|
+
- Discovered skills listing (if provided)
|
|
480
|
+
- Inline skills (if provided)
|
|
481
|
+
- Custom sections (if provided)
|
|
472
482
|
|
|
473
483
|
```typescript
|
|
474
|
-
function
|
|
484
|
+
function buildAgentPrompt(ctx: PromptContext): string
|
|
475
485
|
```
|
|
476
486
|
|
|
477
|
-
- `
|
|
487
|
+
- `ctx` — Prompt construction inputs (tools, docs, skills, etc.).
|
|
478
488
|
|
|
479
|
-
**Returns:**
|
|
489
|
+
**Returns:** Fully assembled system prompt text for the coding agent.
|
|
480
490
|
|
|
481
|
-
#### `
|
|
491
|
+
#### `buildTools(backend, config)`
|
|
482
492
|
|
|
483
|
-
|
|
484
|
-
THROWS returns something the model can act on.
|
|
493
|
+
Build a complete set of AI agent tools bound to an execution backend.
|
|
485
494
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
495
|
+
```typescript
|
|
496
|
+
function buildTools(backend: ExecutionBackend, config?: ToolBuildConfig): AITool[]
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
- `backend` — The execution environment (sandbox or local filesystem)
|
|
500
|
+
- `config` — Optional configuration for security, callbacks, and tool selection
|
|
501
|
+
|
|
502
|
+
**Returns:** Array of AITool objects ready to pass to an AI provider
|
|
503
|
+
|
|
504
|
+
#### `shellQuote(s)`
|
|
505
|
+
|
|
506
|
+
Shell-safe quoting using single quotes. Unlike JSON.stringify (double quotes),
|
|
507
|
+
single-quoted strings prevent command substitution ($(), backticks) and variable expansion.
|
|
493
508
|
|
|
494
509
|
```typescript
|
|
495
|
-
function
|
|
496
|
-
schema: NormalizableSchema,
|
|
497
|
-
impl: (input: Record<string, unknown>, ...rest: never[]) => Promise<unknown>,
|
|
498
|
-
options?: GuardOptions,
|
|
499
|
-
): (input: unknown, ...rest: never[]) => Promise<unknown>
|
|
510
|
+
function shellQuote(s: string): string
|
|
500
511
|
```
|
|
501
512
|
|
|
502
|
-
- `
|
|
503
|
-
- `impl` — The raw handler.
|
|
513
|
+
- `s` — Raw string to wrap for POSIX shell single-quoted context.
|
|
504
514
|
|
|
505
|
-
**Returns:** A
|
|
515
|
+
**Returns:** A single-quoted shell literal representing `s`.
|
|
506
516
|
|
|
507
|
-
#### `
|
|
517
|
+
#### `stripControlChars(s)`
|
|
508
518
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
`.env`, `.env.<suffix>`, and `<name>.env`.
|
|
519
|
+
Strip C0 control chars (except tab, newline, CR) that break PostgreSQL JSONB
|
|
520
|
+
and can cause rendering issues.
|
|
512
521
|
|
|
513
522
|
```typescript
|
|
514
|
-
function
|
|
523
|
+
function stripControlChars(s: string): string
|
|
515
524
|
```
|
|
516
525
|
|
|
517
|
-
- `
|
|
526
|
+
- `s` — Arbitrary text that may contain disallowed control characters.
|
|
518
527
|
|
|
519
|
-
**Returns:** `
|
|
528
|
+
**Returns:** A copy of `s` with unsafe control characters removed.
|
|
520
529
|
|
|
521
|
-
#### `
|
|
530
|
+
#### `redactSecrets(s)`
|
|
522
531
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
532
|
+
Redact values of common secret/credential patterns in text output.
|
|
533
|
+
|
|
534
|
+
ENV-DUMP GRADE — includes the JSON `KEY: 'value'` passes, which key off the
|
|
535
|
+
NAME beside the value and therefore cannot tell a credential from ordinary
|
|
536
|
+
code that happens to use a keyword-ish identifier. Use this for `.env` reads
|
|
537
|
+
and command output (where an env dump is the actual threat); use
|
|
538
|
+
{@link redactSecretsInCode} for source-file content.
|
|
529
539
|
|
|
530
540
|
```typescript
|
|
531
|
-
function
|
|
541
|
+
function redactSecrets(s: string): string
|
|
532
542
|
```
|
|
533
543
|
|
|
534
|
-
- `
|
|
535
|
-
- `projectRoot` — The project root.
|
|
544
|
+
- `s` — Log or command output that may contain `.env`-style secrets.
|
|
536
545
|
|
|
537
|
-
**Returns:**
|
|
546
|
+
**Returns:** A redacted copy safe to surface to end users or models.
|
|
538
547
|
|
|
539
|
-
#### `
|
|
548
|
+
#### `redactSecretsInCode(s)`
|
|
540
549
|
|
|
541
|
-
|
|
542
|
-
|
|
550
|
+
CODE-SAFE redaction — the env-assignment pass of {@link redactSecrets} WITHOUT
|
|
551
|
+
the JSON `KEY: 'value'` passes.
|
|
543
552
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
553
|
+
Those passes match on the NAME next to a quoted value, so over source code they
|
|
554
|
+
replace legitimate content at enormous scale: `forgotPasswordEndpoint:
|
|
555
|
+
'/users/forgot-password'`, `apiKeys: 'API keys'`, and every localized "Show
|
|
556
|
+
password" string all became `'[REDACTED]'`. Because the agent writes back the
|
|
557
|
+
content it reads, that token then lands in the user's project — measured at
|
|
558
|
+
10,952 of 27,919 flagship template files before this split.
|
|
559
|
+
|
|
560
|
+
No value heuristic can fix that: a legitimate `password = 'TestPass123!'` in a
|
|
561
|
+
test helper is indistinguishable from a real credential by shape. So the
|
|
562
|
+
name-keyed passes simply do not run over code. Credentials in source are still
|
|
563
|
+
caught by the env-assignment pass here, and consumers layer VALUE-SHAPE
|
|
564
|
+
detection (vendor prefixes, PEM blocks, credentials in a URL authority) on top —
|
|
565
|
+
which is what actually catches a secret sitting under an innocuous name.
|
|
552
566
|
|
|
553
567
|
```typescript
|
|
554
|
-
function
|
|
568
|
+
function redactSecretsInCode(s: string): string
|
|
555
569
|
```
|
|
556
570
|
|
|
557
|
-
- `
|
|
571
|
+
- `s` — Source-file content or other code-shaped text.
|
|
558
572
|
|
|
559
|
-
**Returns:**
|
|
573
|
+
**Returns:** A redacted copy that preserves ordinary code verbatim.
|
|
560
574
|
|
|
561
|
-
#### `
|
|
575
|
+
#### `isEnvFilePath(path)`
|
|
562
576
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
turn instead of concluding the tool is broken.
|
|
577
|
+
Whether a path is an env file, for which {@link redactSecrets}' full env-dump
|
|
578
|
+
treatment is appropriate rather than {@link redactSecretsInCode}. Matches
|
|
579
|
+
`.env`, `.env.<suffix>`, and `<name>.env`.
|
|
567
580
|
|
|
568
581
|
```typescript
|
|
569
|
-
function
|
|
570
|
-
schema: NormalizableSchema,
|
|
571
|
-
input: Record<string, unknown>,
|
|
572
|
-
missing: string[],
|
|
573
|
-
): string
|
|
582
|
+
function isEnvFilePath(path: string): boolean
|
|
574
583
|
```
|
|
575
584
|
|
|
576
|
-
- `
|
|
577
|
-
- `input` — The normalized input (used to list the keys that were sent).
|
|
578
|
-
- `missing` — The required parameters still absent.
|
|
585
|
+
- `path` — A workspace-relative or absolute file path.
|
|
579
586
|
|
|
580
|
-
**Returns:**
|
|
587
|
+
**Returns:** `true` when the file is an env file.
|
|
581
588
|
|
|
582
|
-
#### `
|
|
589
|
+
#### `declaredBudgetSeconds(command, timeoutParam)`
|
|
583
590
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
591
|
+
The time budget a COMMAND declares for itself — a `timeout <seconds>` prefix
|
|
592
|
+
anywhere in it, or the tool call's own `timeout` (ms) parameter, whichever is
|
|
593
|
+
larger. Zero when it declares none.
|
|
587
594
|
|
|
588
595
|
```typescript
|
|
589
|
-
function
|
|
596
|
+
function declaredBudgetSeconds(command: string, timeoutParam: unknown): number
|
|
590
597
|
```
|
|
591
598
|
|
|
592
|
-
- `
|
|
593
|
-
- `
|
|
599
|
+
- `command` — The shell command.
|
|
600
|
+
- `timeoutParam` — The tool call's `timeout` input, in milliseconds.
|
|
594
601
|
|
|
595
|
-
**Returns:** The
|
|
602
|
+
**Returns:** The declared budget in seconds, or 0.
|
|
596
603
|
|
|
597
604
|
#### `outputIsWithheldUntilExit(command)`
|
|
598
605
|
|
|
@@ -629,126 +636,127 @@ function outputRedirectTarget(command: string): string | null
|
|
|
629
636
|
|
|
630
637
|
**Returns:** The target as written, or null (`/dev/null` and `&1`/`&2` are not files).
|
|
631
638
|
|
|
632
|
-
#### `
|
|
639
|
+
#### `streamingBackgroundCommand(command)`
|
|
633
640
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
641
|
+
Rewrite a command about to run in the background so its log grows while it
|
|
642
|
+
runs. Two shapes left the log empty until exit, and an empty log is what
|
|
643
|
+
`wait_for_task` reads as "stuck", so working suites were reported stuck and
|
|
644
|
+
killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
645
|
+
|
|
646
|
+
- a trailing `| tail -N`, which holds everything back until the command ends.
|
|
647
|
+
It is dropped: `wait_for_task` already returns the end of the log.
|
|
648
|
+
- `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
649
|
+
often `html`, which prints nothing per test. `--reporter=line` is added
|
|
650
|
+
when the playwright run is the command's last step and nothing is piped or
|
|
651
|
+
redirected from it ( aside); the results are the same, printed as they happen.
|
|
637
652
|
|
|
638
653
|
```typescript
|
|
639
|
-
function
|
|
654
|
+
function streamingBackgroundCommand(command: string): { command: string; changes: string[] }
|
|
640
655
|
```
|
|
641
656
|
|
|
642
|
-
- `
|
|
657
|
+
- `command` — The command as the executor sent it.
|
|
643
658
|
|
|
644
|
-
**Returns:** The command
|
|
659
|
+
**Returns:** The command to run and one sentence per change made (empty when none).
|
|
645
660
|
|
|
646
|
-
#### `
|
|
661
|
+
#### `checkBlockedCommand(command)`
|
|
647
662
|
|
|
648
|
-
|
|
649
|
-
passed or could not run (no parser available is not a syntax error).
|
|
663
|
+
Check if a command is blocked for security reasons. Returns error message or null if allowed.
|
|
650
664
|
|
|
651
665
|
```typescript
|
|
652
|
-
function
|
|
653
|
-
stdout: string
|
|
654
|
-
stderr: string
|
|
655
|
-
exitCode: number
|
|
656
|
-
}): string | null
|
|
666
|
+
function checkBlockedCommand(command: string): string | null
|
|
657
667
|
```
|
|
658
668
|
|
|
659
|
-
- `
|
|
669
|
+
- `command` — Shell command string proposed for execution.
|
|
660
670
|
|
|
661
|
-
**Returns:**
|
|
671
|
+
**Returns:** A human-readable block reason, or `null` when the command is allowed.
|
|
662
672
|
|
|
663
|
-
#### `
|
|
673
|
+
#### `resolvePath(path, projectRoot)`
|
|
664
674
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
"Cannot read properties of undefined (reading 'replace')" — wasting executor
|
|
669
|
-
turns. Returns an actionable message, or null when the path is usable.
|
|
675
|
+
Normalize a path to be absolute within the project root.
|
|
676
|
+
Empty string and '/' both resolve to projectRoot.
|
|
677
|
+
Rejects paths that escape via traversal or absolute paths outside root.
|
|
670
678
|
|
|
671
679
|
```typescript
|
|
672
|
-
function
|
|
680
|
+
function resolvePath(path: string, projectRoot: string): string
|
|
673
681
|
```
|
|
674
682
|
|
|
675
|
-
- `path` —
|
|
676
|
-
- `
|
|
677
|
-
|
|
678
|
-
**Returns:** An actionable error string, or null when `path` is a non-empty string.
|
|
683
|
+
- `path` — Relative or absolute path inside the workspace.
|
|
684
|
+
- `projectRoot` — Absolute filesystem root for the active project.
|
|
679
685
|
|
|
680
|
-
|
|
686
|
+
**Returns:** A normalized absolute path confined to `projectRoot`.
|
|
681
687
|
|
|
682
|
-
|
|
688
|
+
#### `isOutsideRoot(path, projectRoot)`
|
|
683
689
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
690
|
+
Whether a tool path points outside the project root once normalized (an
|
|
691
|
+
absolute path elsewhere, or a `..` that climbs out). {@link resolvePath}
|
|
692
|
+
clamps such a path to the root; a file tool must refuse it instead of
|
|
693
|
+
answering about the root — a `list_files /tmp/x` used to return the
|
|
694
|
+
workspace listing as if it were `/tmp/x` (X1 runs sonnet-m17 and sol-m05,
|
|
695
|
+
2026-10-14).
|
|
689
696
|
|
|
690
697
|
```typescript
|
|
691
|
-
function
|
|
698
|
+
function isOutsideRoot(path: string, projectRoot: string): boolean
|
|
692
699
|
```
|
|
693
700
|
|
|
694
|
-
- `
|
|
695
|
-
|
|
696
|
-
**Returns:** A redacted copy safe to surface to end users or models.
|
|
701
|
+
- `path` — The path the tool was given.
|
|
702
|
+
- `projectRoot` — The project root.
|
|
697
703
|
|
|
698
|
-
|
|
704
|
+
**Returns:** True when the path leaves the root.
|
|
699
705
|
|
|
700
|
-
|
|
701
|
-
the JSON `KEY: 'value'` passes.
|
|
706
|
+
#### `isValidGlob(pattern)`
|
|
702
707
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
'/users/forgot-password'`, `apiKeys: 'API keys'`, and every localized "Show
|
|
706
|
-
password" string all became `'[REDACTED]'`. Because the agent writes back the
|
|
707
|
-
content it reads, that token then lands in the user's project — measured at
|
|
708
|
-
10,952 of 27,919 flagship template files before this split.
|
|
708
|
+
Validate that a glob/include pattern is safe (no shell metacharacters that could
|
|
709
|
+
inject). Allows alphanumeric, `* ? . _ - /` and the bracket/paren glob chars `[] ()`.
|
|
709
710
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
711
|
+
The brackets/parens matter for real frameworks: Next.js App Router names route
|
|
712
|
+
directories `[id]`, `[...slug]`, `(group)`, `[[...optional]]`, so without them the
|
|
713
|
+
executor cannot `find_files`/`search_files` its own routes on any Next.js project — a
|
|
714
|
+
hard block observed on live imports. They are injection-safe here because every caller
|
|
715
|
+
passes the pattern through `shellQuote` before it reaches `find -name`/`grep --include`,
|
|
716
|
+
where inside single quotes `[]()` are literal (a subshell `(...)` only starts UNquoted);
|
|
717
|
+
to the glob engine `[abc]` is a normal character class. The genuinely dangerous
|
|
718
|
+
metacharacters (`; | & $ \` > < \n` space) remain disallowed.
|
|
716
719
|
|
|
717
720
|
```typescript
|
|
718
|
-
function
|
|
721
|
+
function isValidGlob(pattern: string): boolean
|
|
719
722
|
```
|
|
720
723
|
|
|
721
|
-
- `
|
|
724
|
+
- `pattern` — User-supplied glob fragment for search/list operations.
|
|
722
725
|
|
|
723
|
-
**Returns:**
|
|
726
|
+
**Returns:** `true` when the pattern contains only allowed characters.
|
|
724
727
|
|
|
725
|
-
#### `
|
|
728
|
+
#### `pathArgError(path, tool)`
|
|
726
729
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
+
Validate a file tool's `path` argument is a non-empty string. A weak model
|
|
731
|
+
sometimes omits it or passes a non-string, which would otherwise crash
|
|
732
|
+
`resolvePath` (`path.replace` on undefined) with the cryptic, unactionable
|
|
733
|
+
"Cannot read properties of undefined (reading 'replace')" — wasting executor
|
|
734
|
+
turns. Returns an actionable message, or null when the path is usable.
|
|
730
735
|
|
|
731
736
|
```typescript
|
|
732
|
-
function
|
|
737
|
+
function pathArgError(path: unknown, tool: string): string | null
|
|
733
738
|
```
|
|
734
739
|
|
|
735
|
-
- `path` —
|
|
736
|
-
- `
|
|
740
|
+
- `path` — The raw `path` argument from the tool input.
|
|
741
|
+
- `tool` — The tool name, for the error message (e.g. 'read_file').
|
|
737
742
|
|
|
738
|
-
**Returns:**
|
|
743
|
+
**Returns:** An actionable error string, or null when `path` is a non-empty string.
|
|
739
744
|
|
|
740
|
-
#### `
|
|
745
|
+
#### `directoryReadHint(message, path)`
|
|
741
746
|
|
|
742
|
-
|
|
743
|
-
|
|
747
|
+
Detect a "read/edit targeted a directory, not a file" failure from a backend
|
|
748
|
+
error message (local fs `EISDIR` or the sandbox's `cat: X: Is a directory`),
|
|
749
|
+
and return an actionable message steering the model to `list_files`. Returns
|
|
750
|
+
null when the error is not a directory error.
|
|
744
751
|
|
|
745
752
|
```typescript
|
|
746
|
-
function
|
|
753
|
+
function directoryReadHint(message: string, path: string): string | null
|
|
747
754
|
```
|
|
748
755
|
|
|
749
|
-
- `
|
|
756
|
+
- `message` — The backend error message.
|
|
757
|
+
- `path` — The resolved path that was targeted.
|
|
750
758
|
|
|
751
|
-
**Returns:**
|
|
759
|
+
**Returns:** An actionable directory-error string, or null.
|
|
752
760
|
|
|
753
761
|
#### `sliceLines(content, window)`
|
|
754
762
|
|
|
@@ -772,41 +780,6 @@ function sliceLines(
|
|
|
772
780
|
|
|
773
781
|
**Returns:** The window plus its position, or null when neither was given.
|
|
774
782
|
|
|
775
|
-
#### `streamingBackgroundCommand(command)`
|
|
776
|
-
|
|
777
|
-
Rewrite a command about to run in the background so its log grows while it
|
|
778
|
-
runs. Two shapes left the log empty until exit, and an empty log is what
|
|
779
|
-
`wait_for_task` reads as "stuck", so working suites were reported stuck and
|
|
780
|
-
killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
781
|
-
|
|
782
|
-
- a trailing `| tail -N`, which holds everything back until the command ends.
|
|
783
|
-
It is dropped: `wait_for_task` already returns the end of the log.
|
|
784
|
-
- `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
785
|
-
often `html`, which prints nothing per test. `--reporter=line` is added
|
|
786
|
-
when the playwright run is the command's last step and nothing is piped or
|
|
787
|
-
redirected from it ( aside); the results are the same, printed as they happen.
|
|
788
|
-
|
|
789
|
-
```typescript
|
|
790
|
-
function streamingBackgroundCommand(command: string): { command: string; changes: string[] }
|
|
791
|
-
```
|
|
792
|
-
|
|
793
|
-
- `command` — The command as the executor sent it.
|
|
794
|
-
|
|
795
|
-
**Returns:** The command to run and one sentence per change made (empty when none).
|
|
796
|
-
|
|
797
|
-
#### `stripControlChars(s)`
|
|
798
|
-
|
|
799
|
-
Strip C0 control chars (except tab, newline, CR) that break PostgreSQL JSONB
|
|
800
|
-
and can cause rendering issues.
|
|
801
|
-
|
|
802
|
-
```typescript
|
|
803
|
-
function stripControlChars(s: string): string
|
|
804
|
-
```
|
|
805
|
-
|
|
806
|
-
- `s` — Arbitrary text that may contain disallowed control characters.
|
|
807
|
-
|
|
808
|
-
**Returns:** A copy of `s` with unsafe control characters removed.
|
|
809
|
-
|
|
810
783
|
#### `truncate(s, maxLength)`
|
|
811
784
|
|
|
812
785
|
Truncate a string to a max length with a truncation notice.
|
|
@@ -870,57 +843,61 @@ function whitespaceTolerantReplace(
|
|
|
870
843
|
|
|
871
844
|
**Returns:** The new content if a unique fuzzy run matched, else null.
|
|
872
845
|
|
|
873
|
-
|
|
846
|
+
#### `parseCheckCommand(path)`
|
|
874
847
|
|
|
875
|
-
|
|
848
|
+
The shell command that parses one file and exits non-zero with the error
|
|
849
|
+
when it does not parse: `node --check` for JavaScript, `JSON.parse` for
|
|
850
|
+
JSON, esbuild's transform (present wherever Vite is) for TypeScript.
|
|
876
851
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
852
|
+
```typescript
|
|
853
|
+
function parseCheckCommand(path: string): string | null
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
- `path` — The file's absolute path.
|
|
857
|
+
|
|
858
|
+
**Returns:** The command, or null when the file type has no cheap parser.
|
|
859
|
+
|
|
860
|
+
#### `parseCheckProblem(result)`
|
|
861
|
+
|
|
862
|
+
What a failed parse check says to the executor, or null when the check
|
|
863
|
+
passed or could not run (no parser available is not a syntax error).
|
|
883
864
|
|
|
884
865
|
```typescript
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
'.hg',
|
|
891
|
-
'CVS',
|
|
892
|
-
'dist',
|
|
893
|
-
'.next',
|
|
894
|
-
'.vite',
|
|
895
|
-
'molecule',
|
|
896
|
-
]
|
|
866
|
+
function parseCheckProblem(result: {
|
|
867
|
+
stdout: string
|
|
868
|
+
stderr: string
|
|
869
|
+
exitCode: number
|
|
870
|
+
}): string | null
|
|
897
871
|
```
|
|
898
872
|
|
|
899
|
-
|
|
873
|
+
- `result` — The check command's result.
|
|
900
874
|
|
|
901
|
-
|
|
902
|
-
|
|
875
|
+
**Returns:** The message for the tool result, or null.
|
|
876
|
+
|
|
877
|
+
### Constants
|
|
878
|
+
|
|
879
|
+
#### `TOOL_SCHEMAS`
|
|
880
|
+
|
|
881
|
+
Canonical tool schemas shared by the agent runtime and documentation.
|
|
903
882
|
|
|
904
883
|
```typescript
|
|
905
|
-
const
|
|
884
|
+
const TOOL_SCHEMAS: Record<string, ToolSchema>
|
|
906
885
|
```
|
|
907
886
|
|
|
908
|
-
#### `
|
|
887
|
+
#### `MAX_READ_SIZE`
|
|
909
888
|
|
|
910
|
-
|
|
911
|
-
of a large tree cannot swallow the turn's context in one result; the tool
|
|
912
|
-
reports where it stopped so the model continues from there.
|
|
889
|
+
Max file size for read_file (5MB).
|
|
913
890
|
|
|
914
891
|
```typescript
|
|
915
|
-
const
|
|
892
|
+
const MAX_READ_SIZE: number
|
|
916
893
|
```
|
|
917
894
|
|
|
918
|
-
#### `
|
|
895
|
+
#### `MAX_WRITE_SIZE`
|
|
919
896
|
|
|
920
|
-
Max
|
|
897
|
+
Max content size for write_file (10MB).
|
|
921
898
|
|
|
922
899
|
```typescript
|
|
923
|
-
const
|
|
900
|
+
const MAX_WRITE_SIZE: number
|
|
924
901
|
```
|
|
925
902
|
|
|
926
903
|
#### `MAX_OUTPUT_SIZE`
|
|
@@ -931,6 +908,35 @@ Max command output size (100KB per stream).
|
|
|
931
908
|
const MAX_OUTPUT_SIZE: number
|
|
932
909
|
```
|
|
933
910
|
|
|
911
|
+
#### `MAX_SEARCH_CONTEXT_LINES`
|
|
912
|
+
|
|
913
|
+
Most lines of surrounding context `search_files` will return per match.
|
|
914
|
+
Bounded so a broad pattern with a generous context cannot pull a whole tree
|
|
915
|
+
into one reply.
|
|
916
|
+
|
|
917
|
+
```typescript
|
|
918
|
+
const MAX_SEARCH_CONTEXT_LINES: 40
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
#### `MAX_BATCH_READ_FILES`
|
|
922
|
+
|
|
923
|
+
Most files one batched `read_file` call returns. The cap exists so a survey
|
|
924
|
+
of a large tree cannot swallow the turn's context in one result; the tool
|
|
925
|
+
reports where it stopped so the model continues from there.
|
|
926
|
+
|
|
927
|
+
```typescript
|
|
928
|
+
const MAX_BATCH_READ_FILES: 25
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
#### `MAX_BATCH_READ_BYTES`
|
|
932
|
+
|
|
933
|
+
Total content bytes one batched `read_file` call returns, across all files.
|
|
934
|
+
The per-file {@link MAX_READ_SIZE} still applies to each one.
|
|
935
|
+
|
|
936
|
+
```typescript
|
|
937
|
+
const MAX_BATCH_READ_BYTES: number
|
|
938
|
+
```
|
|
939
|
+
|
|
934
940
|
#### `MAX_READ_RETURN_CHARS`
|
|
935
941
|
|
|
936
942
|
The most one read_file call returns for ONE file when no window was asked
|
|
@@ -948,24 +954,6 @@ needs.
|
|
|
948
954
|
const MAX_READ_RETURN_CHARS: number
|
|
949
955
|
```
|
|
950
956
|
|
|
951
|
-
#### `MAX_READ_SIZE`
|
|
952
|
-
|
|
953
|
-
Max file size for read_file (5MB).
|
|
954
|
-
|
|
955
|
-
```typescript
|
|
956
|
-
const MAX_READ_SIZE: number
|
|
957
|
-
```
|
|
958
|
-
|
|
959
|
-
#### `MAX_SEARCH_CONTEXT_LINES`
|
|
960
|
-
|
|
961
|
-
Most lines of surrounding context `search_files` will return per match.
|
|
962
|
-
Bounded so a broad pattern with a generous context cannot pull a whole tree
|
|
963
|
-
into one reply.
|
|
964
|
-
|
|
965
|
-
```typescript
|
|
966
|
-
const MAX_SEARCH_CONTEXT_LINES: 40
|
|
967
|
-
```
|
|
968
|
-
|
|
969
957
|
#### `MAX_SEARCH_RESULTS`
|
|
970
958
|
|
|
971
959
|
Max search results.
|
|
@@ -974,28 +962,44 @@ Max search results.
|
|
|
974
962
|
const MAX_SEARCH_RESULTS: 50
|
|
975
963
|
```
|
|
976
964
|
|
|
977
|
-
#### `
|
|
965
|
+
#### `MAX_FIND_RESULTS`
|
|
978
966
|
|
|
979
|
-
Max
|
|
967
|
+
Max find results.
|
|
980
968
|
|
|
981
969
|
```typescript
|
|
982
|
-
const
|
|
970
|
+
const MAX_FIND_RESULTS: 100
|
|
983
971
|
```
|
|
984
972
|
|
|
985
|
-
#### `
|
|
973
|
+
#### `DEFAULT_SEARCH_EXCLUDED_DIRS`
|
|
986
974
|
|
|
987
|
-
|
|
975
|
+
Default directory names `search_files`/`find_files` skip — VS Code's
|
|
976
|
+
`search.exclude` + `files.exclude` defaults (node_modules, bower_components,
|
|
977
|
+
VCS dirs) plus the platform's vendored/build dirs. Overridable per consumer
|
|
978
|
+
via `ToolBuildConfig.searchExcludedDirs` (a per-project, user-editable
|
|
979
|
+
setting in molecule.dev — keep the APP-SIDE copy in
|
|
980
|
+
`@molecule/app-ide-react`'s search types in sync with this list).
|
|
988
981
|
|
|
989
982
|
```typescript
|
|
990
|
-
const
|
|
983
|
+
const DEFAULT_SEARCH_EXCLUDED_DIRS: readonly [
|
|
984
|
+
'node_modules',
|
|
985
|
+
'bower_components',
|
|
986
|
+
'.git',
|
|
987
|
+
'.svn',
|
|
988
|
+
'.hg',
|
|
989
|
+
'CVS',
|
|
990
|
+
'dist',
|
|
991
|
+
'.next',
|
|
992
|
+
'.vite',
|
|
993
|
+
'molecule',
|
|
994
|
+
]
|
|
991
995
|
```
|
|
992
996
|
|
|
993
|
-
#### `
|
|
997
|
+
#### `PARSE_CHECKABLE`
|
|
994
998
|
|
|
995
|
-
|
|
999
|
+
Files a parse check can vouch for cheaply right after a write.
|
|
996
1000
|
|
|
997
1001
|
```typescript
|
|
998
|
-
const
|
|
1002
|
+
const PARSE_CHECKABLE: RegExp
|
|
999
1003
|
```
|
|
1000
1004
|
|
|
1001
1005
|
## Injection Notes
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA8B9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAwCnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA8B9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAwCnE;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CA8/CxF"}
|
package/dist/tools.js
CHANGED
|
@@ -1039,8 +1039,11 @@ export function buildTools(backend, config) {
|
|
|
1039
1039
|
// behind `| tail` it returns nothing (X1 flash-m29 lost a 290 s run that way).
|
|
1040
1040
|
// A short one still comes back as a foreground result, through the grace below.
|
|
1041
1041
|
const overCeiling = commandBudgetMs !== undefined &&
|
|
1042
|
-
outputIsWithheldUntilExit(command) &&
|
|
1043
|
-
|
|
1042
|
+
((outputIsWithheldUntilExit(command) &&
|
|
1043
|
+
(declaredSeconds > ceilingSeconds || /\bplaywright\s+test\b/.test(command))) ||
|
|
1044
|
+
// A redirected Playwright run shows nothing either (`> out.txt`), and was killed at
|
|
1045
|
+
// the ceiling with 38 tests unrun (X1 flash-m36).
|
|
1046
|
+
(/\bplaywright\s+test\b/.test(command) && outputRedirectTarget(command) !== null));
|
|
1044
1047
|
if (input.run_in_background === true || overCeiling) {
|
|
1045
1048
|
const id = `mol-bg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1046
1049
|
const log = `/tmp/${id}.log`;
|
package/dist/utilities.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAS5C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,GAAG,MAAM,KAAG,MAEE,CAAA;
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
|
package/dist/utilities.js
CHANGED
|
@@ -70,8 +70,10 @@ const SECRET_ENV_ASSIGNMENT = new RegExp(
|
|
|
70
70
|
const SECRET_JSON_DQ = new RegExp(
|
|
71
71
|
// A value ends at its closing quote OR the end of its line: cut off mid-value (`head -c`),
|
|
72
72
|
// the old pattern ran on to a quote on a LATER line and swallowed the lines between (flash-m32).
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
// The key starts at a real boundary: a package name ending in a keyword ("@molecule/app-auth": "1.2.0")
|
|
74
|
+
// is not a secret, and matching from its tail masked the version (flash-m35).
|
|
75
|
+
`((?<![\\w@/.-])['"]?(?:\\w*(?:${SECRET_KEYWORDS})\\w*)['"]?\\s*[:=]\\s*)"(?:[^"\\\\\\n]|\\\\.)*(?:"|(?=\\n)|$)`, 'gi');
|
|
76
|
+
const SECRET_JSON_SQ = new RegExp(`((?<![\\w@/.-])['"]?(?:\\w*(?:${SECRET_KEYWORDS})\\w*)['"]?\\s*[:=]\\s*)'(?:[^'\\\\\\n]|\\\\.)*(?:'|(?=\\n)|$)`, 'gi');
|
|
75
77
|
/**
|
|
76
78
|
* Exact VALUES that are UI vocabulary, never credentials — kept verbatim even when they
|
|
77
79
|
* sit next to a keyword-looking name. Frontend auth code is full of these: a JSX ternary
|
|
@@ -239,6 +241,13 @@ export function streamingBackgroundCommand(command) {
|
|
|
239
241
|
changes.push(`Dropped the trailing \`${tail[0].trim()}\`: it holds all output back until the command ends, ` +
|
|
240
242
|
'and wait_for_task returns the end of the log anyway.');
|
|
241
243
|
}
|
|
244
|
+
// A Playwright run behind `| head -N` loses its tally, which prints last (X1
|
|
245
|
+
// flash-m32 counted ✓/✘ marks by hand); the full log comes back anyway.
|
|
246
|
+
const head = /\s*\|\s*head(?:\s+-n)?\s+-?\d+\s*$/.exec(out);
|
|
247
|
+
if (head && /\bplaywright\s+test\b/.test(out)) {
|
|
248
|
+
out = out.slice(0, head.index);
|
|
249
|
+
changes.push(`Dropped the trailing \`${head[0].trim()}\`: Playwright prints its pass/fail count last, and it would be cut.`);
|
|
250
|
+
}
|
|
242
251
|
const lastStep = out.split(/&&|\|\||;/).at(-1) ?? '';
|
|
243
252
|
if (/\bplaywright\s+test\b/.test(lastStep) &&
|
|
244
253
|
!/--reporter\b/.test(lastStep) &&
|