@molecule/api-ai-tools 1.11.1 → 1.12.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/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-21T08:55:11.822Z
6
+ Generated: 2026-10-21T20:10:49.315Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -444,6 +444,35 @@ interface DiagnosisRunContext {
444
444
  }
445
445
  ```
446
446
 
447
+ #### `DeferredToolCatalogOptions`
448
+
449
+ Options for exposing a small tool set while retaining access to other allowed tools.
450
+
451
+ ```typescript
452
+ interface DeferredToolCatalogOptions {
453
+ /** The caller's current permission/mode-filtered tools. Discovery never grants access. */
454
+ available: () => readonly AITool[]
455
+ /** Tools that should be offered without a discovery call. */
456
+ initialNames: ReadonlySet<string>
457
+ /** Previously loaded names, in load order; useful across turns and compaction. */
458
+ loadedNames?: readonly string[]
459
+ /** Persist names after a successful load. No tool content is passed to this callback. */
460
+ onLoad?: (names: string[]) => void
461
+ }
462
+ ```
463
+
464
+ #### `DeferredToolCatalog`
465
+
466
+ A provider-independent deferred catalog. The caller still executes and authorizes tools.
467
+
468
+ ```typescript
469
+ interface DeferredToolCatalog {
470
+ loader: AITool
471
+ /** Initial tools, loader, then requested tools in stable load order. */
472
+ select: () => AITool[]
473
+ }
474
+ ```
475
+
447
476
  #### `InstalledPackageFacts`
448
477
 
449
478
  What the filesystem says about a write target under `node_modules` — the half
@@ -2231,7 +2260,8 @@ function pipelineExitCodeNote(command: string, exitCode: number, output: string)
2231
2260
  Whether a command, read from its TEXT alone, starts a server that stays up in the foreground.
2232
2261
 
2233
2262
  The over-budget reader's shape: at that point the command has already run, and only its text is
2234
- left to say whether "run a smaller unit" was ever the right advice.
2263
+ left to say whether "run a smaller unit" was ever the right advice. Inline/stdin programs
2264
+ remain unclassified and use the normal bounded command runner.
2235
2265
 
2236
2266
  ```typescript
2237
2267
  function startsServerProgram(command: string): boolean
@@ -2244,7 +2274,9 @@ function startsServerProgram(command: string): boolean
2244
2274
  #### `foregroundServerCommand(command, readScript)`
2245
2275
 
2246
2276
  A FOREGROUND command that starts a server, including one that only names a script whose SOURCE
2247
- imports the app's server and calls its `create()`/`listen()`.
2277
+ imports the app's server and calls its `create()`/`listen()`. Inline/stdin programs
2278
+ (`node -e …`, `python3 -c …`) use normal bounded execution: interpreting arbitrary
2279
+ program text is outside this filename/script preflight's contract.
2248
2280
 
2249
2281
  The script read is best-effort: a path the backend will not answer for is a command this reading
2250
2282
  cannot classify, never a refusal. A backgrounded launch, a test runner and a test file are all
@@ -2539,6 +2571,24 @@ function buildAgentPrompt(ctx: PromptContext): string
2539
2571
 
2540
2572
  **Returns:** Fully assembled system prompt text for the coding agent.
2541
2573
 
2574
+ #### `createDeferredToolCatalog(options)`
2575
+
2576
+ Offer common tools and let the model load other schemas by exact name.
2577
+
2578
+ This is ordinary allowlist selection, not semantic routing or authorization.
2579
+ Pass tools already filtered by the current mode and permissions. Loading never
2580
+ executes a tool; the caller must keep its normal execution-time guards. Loaded
2581
+ schemas append in request order and stay available, avoiding an LRU that changes
2582
+ the schema prefix on every request. Only names need persistence across turns.
2583
+
2584
+ ```typescript
2585
+ function createDeferredToolCatalog(options: DeferredToolCatalogOptions): DeferredToolCatalog
2586
+ ```
2587
+
2588
+ - `options` — Allowed tools, initial selection and optional durable load state.
2589
+
2590
+ **Returns:** A loader tool and the current provider-facing selection.
2591
+
2542
2592
  #### `taskStopCommand(backend, taskId)`
2543
2593
 
2544
2594
  The command that stops a running background task, read from the sandbox's own pid files.
@@ -2996,6 +3046,24 @@ function redactSecretsInCode(s: string): string
2996
3046
 
2997
3047
  **Returns:** A redacted copy that preserves ordinary code verbatim.
2998
3048
 
3049
+ #### `addedRedactionMask(next, previous)`
3050
+
3051
+ The redaction mask `next` adds over `previous`, or null when it adds none.
3052
+
3053
+ `previous` is the file's previous content for `write_file`, and the replacement's own
3054
+ `old_string` for `edit_file` — an edit that carries an existing mask through (a file that
3055
+ already had one, read back and rewritten) adds no occurrence. A new occurrence may
3056
+ be copied output or intentional source; the caller declares the latter explicitly.
3057
+
3058
+ ```typescript
3059
+ function addedRedactionMask(next: string, previous: string): string | null
3060
+ ```
3061
+
3062
+ - `next` — The content about to be written (or the replacement's `new_string`).
3063
+ - `previous` — The content it replaces, already on disk (or the `old_string`).
3064
+
3065
+ **Returns:** The added mask as written (`'[REDACTED]'`, `"[REDACTED]"`, `=[REDACTED]`), or null.
3066
+
2999
3067
  #### `printsOnlySource(command)`
3000
3068
 
3001
3069
  Whether a shell command only PRINTS source files (`cat a.tsx`, `sed -n '1,40p' x.ts`,
@@ -3012,6 +3080,35 @@ function printsOnlySource(command: string): boolean
3012
3080
 
3013
3081
  **Returns:** True when the command prints source files, with only literal headings and filters.
3014
3082
 
3083
+ #### `isReadOnlyInspection(command)`
3084
+
3085
+ Whether a shell command only INSPECTS the workspace WITHOUT printing a file's contents:
3086
+ it prints source files (a pure literal read, {@link printsOnlySource}), lists names
3087
+ (`ls`, `find`), or counts lines (`wc`) — joined by `;`, `&&` or `|`, with literal
3088
+ `echo`/`printf` headings and `cd`.
3089
+
3090
+ Its output is code or names, not an env dump, so it gets the code-safe redaction
3091
+ ({@link redactSecretsInCode}) instead of the name-keyed env-dump passes. Without this,
3092
+ ordinary code values such as `tokenKey: 'jwtToken'` in a mixed source read and
3093
+ `ls | head` command would be masked by the environment-dump rules.
3094
+
3095
+ A RECURSIVE SEARCH IS NOT INSPECTION (`grep -rn x .`, `rg x src/`): its output is the
3096
+ content of whichever files matched, including `.env` files and JSON secret dumps, so it
3097
+ keeps the full grade. A path with no extension is not evidence that it is a directory —
3098
+ `/dev/stdin` and an ordinary `secrets` file read the same way.
3099
+
3100
+ Env dumps keep the full grade: `.env` anywhere in the command, `env`/`printenv`, a
3101
+ non-literal or redirecting form, and an interpreter one-liner (`node -e`, `python -c`)
3102
+ all return false.
3103
+
3104
+ ```typescript
3105
+ function isReadOnlyInspection(command: string): boolean
3106
+ ```
3107
+
3108
+ - `command` — The shell command.
3109
+
3110
+ **Returns:** True when the command only reads or lists workspace content.
3111
+
3015
3112
  #### `isEnvFilePath(path)`
3016
3113
 
3017
3114
  Whether a path is an env file, for which {@link redactSecrets}' full env-dump
@@ -4310,7 +4407,10 @@ const BACKGROUNDED: RegExp
4310
4407
  A program that SERVES: the scaffold's entry (`server.ts`/`server.js`), a package manager's
4311
4408
  `start`/`dev`/`serve`/`preview` script, a Vite dev or preview server, `next start|dev`, or a
4312
4409
  Python WSGI server. Matched against a command segment's own text, and against a script's SOURCE
4313
- when the command only names the script file.
4410
+ when the command only names the script file — but NEVER against an inline program's code
4411
+ (`node -e …`, `python3 -c …`), where this text is the user's program rather than a file being
4412
+ run: `require('…/node_modules/vite')` imports a module, it does not start a dev server
4413
+ (xr-molecule-flash-m391 +13:13, refused as "node starts a server" for exactly that line).
4314
4414
 
4315
4415
  ```typescript
4316
4416
  const SERVER_PROGRAM: RegExp
@@ -4915,6 +5015,11 @@ Peer dependencies:
4915
5015
  as a broken tool and routes around, taking its verification with it. Use
4916
5016
  `guardAITool` to give tools built elsewhere the same treatment, passing
4917
5017
  `redactError` so a thrown message is masked by your own redactor.
5018
+ - **Defer occasional tools** with `createDeferredToolCatalog`: pass your current
5019
+ permission-filtered tools and a small initial name set, offer `catalog.select()`
5020
+ to the model, and execute `catalog.loader` like any other tool. Loading only
5021
+ exposes schemas, never grants permission or runs a tool. Persist its loaded
5022
+ names with `onLoad` to keep them available across turns and compaction.
4918
5023
  - **Scope the tool set per agent** with `include`/`exclude` — a read-only agent
4919
5024
  should not receive `write_file`/`exec_command`.
4920
5025
  - Outputs are size-capped (`MAX_READ_SIZE`, `MAX_OUTPUT_SIZE`, …) and searches
package/dist/index.d.ts CHANGED
@@ -70,6 +70,11 @@
70
70
  * as a broken tool and routes around, taking its verification with it. Use
71
71
  * `guardAITool` to give tools built elsewhere the same treatment, passing
72
72
  * `redactError` so a thrown message is masked by your own redactor.
73
+ * - **Defer occasional tools** with `createDeferredToolCatalog`: pass your current
74
+ * permission-filtered tools and a small initial name set, offer `catalog.select()`
75
+ * to the model, and execute `catalog.loader` like any other tool. Loading only
76
+ * exposes schemas, never grants permission or runs a tool. Persist its loaded
77
+ * names with `onLoad` to keep them available across turns and compaction.
73
78
  * - **Scope the tool set per agent** with `include`/`exclude` — a read-only agent
74
79
  * should not receive `write_file`/`exec_command`.
75
80
  * - Outputs are size-capped (`MAX_READ_SIZE`, `MAX_OUTPUT_SIZE`, …) and searches
@@ -147,6 +152,7 @@ export * from './server-command.js';
147
152
  export * from './sleep-peek.js';
148
153
  export * from './suite-overlap.js';
149
154
  export * from './system-prompt.js';
155
+ export * from './tool-catalog.js';
150
156
  export * from './tools.js';
151
157
  export * from './trace-artifacts.js';
152
158
  export * from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuIG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -70,6 +70,11 @@
70
70
  * as a broken tool and routes around, taking its verification with it. Use
71
71
  * `guardAITool` to give tools built elsewhere the same treatment, passing
72
72
  * `redactError` so a thrown message is masked by your own redactor.
73
+ * - **Defer occasional tools** with `createDeferredToolCatalog`: pass your current
74
+ * permission-filtered tools and a small initial name set, offer `catalog.select()`
75
+ * to the model, and execute `catalog.loader` like any other tool. Loading only
76
+ * exposes schemas, never grants permission or runs a tool. Persist its loaded
77
+ * names with `onLoad` to keep them available across turns and compaction.
73
78
  * - **Scope the tool set per agent** with `include`/`exclude` — a read-only agent
74
79
  * should not receive `write_file`/`exec_command`.
75
80
  * - Outputs are size-capped (`MAX_READ_SIZE`, `MAX_OUTPUT_SIZE`, …) and searches
@@ -147,6 +152,7 @@ export * from './server-command.js';
147
152
  export * from './sleep-peek.js';
148
153
  export * from './suite-overlap.js';
149
154
  export * from './system-prompt.js';
155
+ export * from './tool-catalog.js';
150
156
  export * from './tools.js';
151
157
  export * from './trace-artifacts.js';
152
158
  export * from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CA8V1C,CAAA"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAwW1C,CAAA"}
package/dist/schemas.js CHANGED
@@ -71,6 +71,10 @@ export const TOOL_SCHEMAS = {
71
71
  parameters: {
72
72
  type: 'object',
73
73
  properties: {
74
+ intentional_redaction_placeholder: {
75
+ type: 'boolean',
76
+ description: 'Set true only when intentionally authoring a literal [REDACTED] placeholder. Default false: newly copied output placeholders are refused. This never disables secret-output masking.',
77
+ },
74
78
  path: {
75
79
  type: 'string',
76
80
  description: 'Path to the file to write.',
@@ -89,6 +93,10 @@ export const TOOL_SCHEMAS = {
89
93
  parameters: {
90
94
  type: 'object',
91
95
  properties: {
96
+ intentional_redaction_placeholder: {
97
+ type: 'boolean',
98
+ description: 'Set true only when intentionally authoring a literal [REDACTED] placeholder. Default false: newly copied output placeholders are refused. This never disables secret-output masking.',
99
+ },
92
100
  path: {
93
101
  type: 'string',
94
102
  description: 'Path to the file to edit.',
@@ -26,14 +26,18 @@ export declare const BACKGROUNDED: RegExp;
26
26
  * A program that SERVES: the scaffold's entry (`server.ts`/`server.js`), a package manager's
27
27
  * `start`/`dev`/`serve`/`preview` script, a Vite dev or preview server, `next start|dev`, or a
28
28
  * Python WSGI server. Matched against a command segment's own text, and against a script's SOURCE
29
- * when the command only names the script file.
29
+ * when the command only names the script file — but NEVER against an inline program's code
30
+ * (`node -e …`, `python3 -c …`), where this text is the user's program rather than a file being
31
+ * run: `require('…/node_modules/vite')` imports a module, it does not start a dev server
32
+ * (xr-molecule-flash-m391 +13:13, refused as "node starts a server" for exactly that line).
30
33
  */
31
34
  export declare const SERVER_PROGRAM: RegExp;
32
35
  /**
33
36
  * Whether a command, read from its TEXT alone, starts a server that stays up in the foreground.
34
37
  *
35
38
  * The over-budget reader's shape: at that point the command has already run, and only its text is
36
- * left to say whether "run a smaller unit" was ever the right advice.
39
+ * left to say whether "run a smaller unit" was ever the right advice. Inline/stdin programs
40
+ * remain unclassified and use the normal bounded command runner.
37
41
  *
38
42
  * @param command - The command as the executor sent it.
39
43
  * @returns True when a foreground statement of the command starts a server.
@@ -46,7 +50,9 @@ export interface ForegroundServer {
46
50
  }
47
51
  /**
48
52
  * A FOREGROUND command that starts a server, including one that only names a script whose SOURCE
49
- * imports the app's server and calls its `create()`/`listen()`.
53
+ * imports the app's server and calls its `create()`/`listen()`. Inline/stdin programs
54
+ * (`node -e …`, `python3 -c …`) use normal bounded execution: interpreting arbitrary
55
+ * program text is outside this filename/script preflight's contract.
50
56
  *
51
57
  * The script read is best-effort: a path the backend will not answer for is a command this reading
52
58
  * cannot classify, never a refusal. A backgrounded launch, a test runner and a test file are all
@@ -1 +1 @@
1
- {"version":3,"file":"server-command.d.ts","sourceRoot":"","sources":["../src/server-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,sBAAsB,EAAyB,MAAM,oBAAoB,CAAA;AAKvF;;;GAGG;AACH,eAAO,MAAM,YAAY,QAA6C,CAAA;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QACmP,CAAA;AAmF9Q;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAC5C,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAmBlC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAC5C,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAiBxC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAO5F;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,QAG0B,CAAA"}
1
+ {"version":3,"file":"server-command.d.ts","sourceRoot":"","sources":["../src/server-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,sBAAsB,EAAyB,MAAM,oBAAoB,CAAA;AAKvF;;;GAGG;AACH,eAAO,MAAM,YAAY,QAA6C,CAAA;AAEtE;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,QACmP,CAAA;AA8G9Q;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAC5C,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAmBlC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAC5C,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAiBxC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAO5F;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,QAG0B,CAAA"}
@@ -28,7 +28,10 @@ export const BACKGROUNDED = /(?:^|[^&>])&(?!&|>)|\b(?:nohup|setsid)\b/;
28
28
  * A program that SERVES: the scaffold's entry (`server.ts`/`server.js`), a package manager's
29
29
  * `start`/`dev`/`serve`/`preview` script, a Vite dev or preview server, `next start|dev`, or a
30
30
  * Python WSGI server. Matched against a command segment's own text, and against a script's SOURCE
31
- * when the command only names the script file.
31
+ * when the command only names the script file — but NEVER against an inline program's code
32
+ * (`node -e …`, `python3 -c …`), where this text is the user's program rather than a file being
33
+ * run: `require('…/node_modules/vite')` imports a module, it does not start a dev server
34
+ * (xr-molecule-flash-m391 +13:13, refused as "node starts a server" for exactly that line).
32
35
  */
33
36
  export const SERVER_PROGRAM = /\bserver\.[cm]?[jt]s\b|\b(?:npm|pnpm|yarn|bun)\s+(?:run\s+)?(?:start|dev|serve|preview)\b|\bvite\s+(?:preview|dev|serve)\b|\bvite(?![.\w-])(?!\s+(?:build|optimize)\b)|\bnext\s+(?:start|dev)\b|\b(?:uvicorn|gunicorn)\b|\bflask\s+run\b|\bpython\d?\s+-m\s+http\.server\b/;
34
37
  /** Programs that run a script FILE, so the file's own source decides whether it serves. */
@@ -66,6 +69,26 @@ const SERVE_SCRIPTS = /^(?:start|dev|serve|preview)$/;
66
69
  const TEST_RUNNERS = /^(?:hurl|jest|mocha|playwright|vitest)$/;
67
70
  /** A script's SOURCE that binds a listener even when it does not name a server file. */
68
71
  const STARTS_LISTENING = /\b(?:server|app)\.listen\s*\(/;
72
+ /** Node inline-program flags; the shell parser already separated their arguments. */
73
+ const NODE_INLINE_FLAG = /^(?:-[A-Za-z]*[ep]|--(?:eval|print)(?:=|$))/;
74
+ /** Python inline programs use -c, including combined interpreter flags. */
75
+ const PYTHON_INLINE_FLAG = /^-[A-Za-z]*c$/;
76
+ /**
77
+ * Inline/stdin programs have no server filename to classify. Their source is arbitrary
78
+ * code; the normal bounded command runner, rather than another partial JS/Python
79
+ * parser, owns their execution. Named script and package-server checks remain below.
80
+ * @param segment - One parsed shell statement.
81
+ * @returns Whether the interpreter reads an inline/stdin program.
82
+ */
83
+ function isInlineProgram(segment) {
84
+ const flag = /^python(?:3(?:\.\d+)?)?$/.test(segment.program)
85
+ ? PYTHON_INLINE_FLAG
86
+ : NODE_INLINE_FLAG;
87
+ return segment.args.some((word) => {
88
+ const arg = bare(word);
89
+ return arg === '-' || flag.test(arg);
90
+ });
91
+ }
69
92
  /** A word with its shell quotes taken off (`'src/server.ts'` → `src/server.ts`). */
70
93
  function bare(word) {
71
94
  const match = /^(['"])(.*)\1$/s.exec(word);
@@ -75,6 +98,8 @@ function bare(word) {
75
98
  * Whether one parsed statement starts a server: a package manager's serving script, or a program
76
99
  * that IS a server, named in command position (so `cat server.ts` is a read, not a launch).
77
100
  *
101
+ * Inline/stdin programs use normal bounded execution: their code is not a server filename.
102
+ *
78
103
  * @param segment - One statement of the command.
79
104
  * @returns True when the statement starts a server that does not exit.
80
105
  */
@@ -87,7 +112,11 @@ function runsServerProgram(segment) {
87
112
  if (script !== undefined && SERVE_SCRIPTS.test(script))
88
113
  return true;
89
114
  }
90
- return SERVER_PROGRAMS.has(segment.program) && SERVER_PROGRAM.test(segment.text);
115
+ if (!SERVER_PROGRAMS.has(segment.program))
116
+ return false;
117
+ if (isInlineProgram(segment))
118
+ return false;
119
+ return SERVER_PROGRAM.test(segment.text);
91
120
  }
92
121
  /**
93
122
  * The script file a runner statement executes, when it names one.
@@ -98,6 +127,9 @@ function runsServerProgram(segment) {
98
127
  function scriptPath(segment) {
99
128
  if (!SCRIPT_RUNNERS.has(segment.program))
100
129
  return null;
130
+ // An inline program (`node -e …`) is code, not a file to read.
131
+ if (isInlineProgram(segment))
132
+ return null;
101
133
  for (const arg of segment.args) {
102
134
  const word = bare(arg);
103
135
  if (word.startsWith('-'))
@@ -111,7 +143,8 @@ function scriptPath(segment) {
111
143
  * Whether a command, read from its TEXT alone, starts a server that stays up in the foreground.
112
144
  *
113
145
  * The over-budget reader's shape: at that point the command has already run, and only its text is
114
- * left to say whether "run a smaller unit" was ever the right advice.
146
+ * left to say whether "run a smaller unit" was ever the right advice. Inline/stdin programs
147
+ * remain unclassified and use the normal bounded command runner.
115
148
  *
116
149
  * @param command - The command as the executor sent it.
117
150
  * @returns True when a foreground statement of the command starts a server.
@@ -124,7 +157,9 @@ export function startsServerProgram(command) {
124
157
  }
125
158
  /**
126
159
  * A FOREGROUND command that starts a server, including one that only names a script whose SOURCE
127
- * imports the app's server and calls its `create()`/`listen()`.
160
+ * imports the app's server and calls its `create()`/`listen()`. Inline/stdin programs
161
+ * (`node -e …`, `python3 -c …`) use normal bounded execution: interpreting arbitrary
162
+ * program text is outside this filename/script preflight's contract.
128
163
  *
129
164
  * The script read is best-effort: a path the backend will not answer for is a command this reading
130
165
  * cannot classify, never a refusal. A backgrounded launch, a test runner and a test file are all
@@ -0,0 +1,32 @@
1
+ import type { AITool } from '@molecule/api-ai';
2
+ /** Options for exposing a small tool set while retaining access to other allowed tools. */
3
+ export interface DeferredToolCatalogOptions {
4
+ /** The caller's current permission/mode-filtered tools. Discovery never grants access. */
5
+ available: () => readonly AITool[];
6
+ /** Tools that should be offered without a discovery call. */
7
+ initialNames: ReadonlySet<string>;
8
+ /** Previously loaded names, in load order; useful across turns and compaction. */
9
+ loadedNames?: readonly string[];
10
+ /** Persist names after a successful load. No tool content is passed to this callback. */
11
+ onLoad?: (names: string[]) => void;
12
+ }
13
+ /** A provider-independent deferred catalog. The caller still executes and authorizes tools. */
14
+ export interface DeferredToolCatalog {
15
+ loader: AITool;
16
+ /** Initial tools, loader, then requested tools in stable load order. */
17
+ select: () => AITool[];
18
+ }
19
+ /**
20
+ * Offer common tools and let the model load other schemas by exact name.
21
+ *
22
+ * This is ordinary allowlist selection, not semantic routing or authorization.
23
+ * Pass tools already filtered by the current mode and permissions. Loading never
24
+ * executes a tool; the caller must keep its normal execution-time guards. Loaded
25
+ * schemas append in request order and stay available, avoiding an LRU that changes
26
+ * the schema prefix on every request. Only names need persistence across turns.
27
+ *
28
+ * @param options - Allowed tools, initial selection and optional durable load state.
29
+ * @returns A loader tool and the current provider-facing selection.
30
+ */
31
+ export declare function createDeferredToolCatalog(options: DeferredToolCatalogOptions): DeferredToolCatalog;
32
+ //# sourceMappingURL=tool-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-catalog.d.ts","sourceRoot":"","sources":["../src/tool-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAE9C,2FAA2F;AAC3F,MAAM,WAAW,0BAA0B;IACzC,0FAA0F;IAC1F,SAAS,EAAE,MAAM,SAAS,MAAM,EAAE,CAAA;IAClC,6DAA6D;IAC7D,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,kFAAkF;IAClF,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,yFAAyF;IACzF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACnC;AAED,+FAA+F;AAC/F,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,MAAM,EAAE,MAAM,MAAM,EAAE,CAAA;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CAsErB"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Offer common tools and let the model load other schemas by exact name.
3
+ *
4
+ * This is ordinary allowlist selection, not semantic routing or authorization.
5
+ * Pass tools already filtered by the current mode and permissions. Loading never
6
+ * executes a tool; the caller must keep its normal execution-time guards. Loaded
7
+ * schemas append in request order and stay available, avoiding an LRU that changes
8
+ * the schema prefix on every request. Only names need persistence across turns.
9
+ *
10
+ * @param options - Allowed tools, initial selection and optional durable load state.
11
+ * @returns A loader tool and the current provider-facing selection.
12
+ */
13
+ export function createDeferredToolCatalog(options) {
14
+ const loaded = new Set(options.loadedNames);
15
+ const available = () => options.available().filter((tool) => tool.name !== 'load_tools');
16
+ const loader = {
17
+ name: 'load_tools',
18
+ get description() {
19
+ const deferred = available().filter((tool) => !options.initialNames.has(tool.name));
20
+ return ('Load additional tools by exact name before calling them. Loading only exposes their ' +
21
+ 'schemas; it does not run them. They remain available for later requests. Other tools: ' +
22
+ deferred
23
+ .map((tool) => `${tool.name}: ${tool.description.split(/\n|(?<=[.!?])\s/)[0].slice(0, 160)}`)
24
+ .join('; '));
25
+ },
26
+ parameters: {
27
+ type: 'object',
28
+ properties: {
29
+ names: {
30
+ type: 'array',
31
+ items: { type: 'string' },
32
+ minItems: 1,
33
+ description: 'Exact tool names to load together, for example ["git_push", "git_pull"].',
34
+ },
35
+ },
36
+ required: ['names'],
37
+ },
38
+ async execute(input) {
39
+ const names = input?.names;
40
+ if (!Array.isArray(names) ||
41
+ names.length === 0 ||
42
+ names.some((name) => typeof name !== 'string')) {
43
+ return { error: 'names must be a nonempty array of exact tool names. Nothing was loaded.' };
44
+ }
45
+ const permitted = new Set(available().map((tool) => tool.name));
46
+ const refused = names.filter((name) => !permitted.has(name));
47
+ if (refused.length > 0) {
48
+ return {
49
+ error: `Tools unavailable in the current mode: ${refused.join(', ')}. Nothing was loaded.`,
50
+ };
51
+ }
52
+ for (const name of names)
53
+ loaded.add(name);
54
+ options.onLoad?.([...loaded]);
55
+ return {
56
+ loaded: [...new Set(names)],
57
+ message: 'Schemas loaded. Call these tools with their declared arguments.',
58
+ };
59
+ },
60
+ };
61
+ return {
62
+ loader,
63
+ select() {
64
+ const tools = available();
65
+ const byName = new Map(tools.map((tool) => [tool.name, tool]));
66
+ return [
67
+ ...tools.filter((tool) => options.initialNames.has(tool.name)),
68
+ loader,
69
+ ...[...loaded].flatMap((name) => {
70
+ const tool = byName.get(name);
71
+ return tool && !options.initialNames.has(name) ? [tool] : [];
72
+ }),
73
+ ];
74
+ },
75
+ };
76
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA4O9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAudD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA8HnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AA2DlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA2GD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAi5FxF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA4O9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAudD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA+HnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AA2DlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA2GD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CA27FxF"}
package/dist/tools.js CHANGED
@@ -663,7 +663,7 @@ async function backgroundTaskState(backend, command, seconds, ceilingMs) {
663
663
  }
664
664
  import { suiteCommandTarget } from './suite-overlap.js';
665
665
  import { diagnosisTraceCommand } from './trace-artifacts.js';
666
- import { BRACE_GLOB_HINT, checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, earlyReturnCause, emptyCallError, expandBraceGlob, failureCausesNote, findPathArgs, findPatternArgs, fusedLine, htmlOutline, isCommandTimeout, isEnvFilePath, isOutsideRoot, isPlaywrightRunCommand, isSuiteRunCommand, linesWithinSerialized, literalDirPrefix, logShowsInlineFailureBodies, MAX_BATCH_READ_FILES, MAX_FIND_RESULTS, MAX_HTML_INLINE_CHARS, MAX_OUTPUT_SIZE, MAX_READ_CALL_CHARS, MAX_READ_RETURN_CHARS, MAX_READ_SIZE, MAX_SEARCH_CONTEXT_LINES, MAX_SEARCH_RESULTS, MAX_WRITE_SIZE, outputIsWithheldUntilExit, outputRedirectTarget, parseCheckCommand, parseCheckProblem, pathArgError, printsOnlySource, READ_RESULT_ENVELOPE_CHARS, redactSecrets, redactSecretsInCode, repeatedSuiteRunError, repeatingFailure, repeatingFailureNote, resolvePath, RUNNING_FAILURE_LINES, runningCauseCommand, runningOutputSliceCommand, searchTimeoutError, serializedChars, shellQuote, sliceLines, SMALL_FILE_WHOLE_CHARS, streamingBackgroundCommand, stripControlChars, suiteRunBudgetCommand, suiteRunConfigCommand, suiteRunPipelinePlacement, suiteRunPriorityLaunch, TOOL_RESULT_CHARS, truncateMiddle, universalCause, whitespaceTolerantReplace, withoutSuiteTimeout, } from './utilities.js';
666
+ import { addedRedactionMask, BRACE_GLOB_HINT, checkBlockedCommand, declaredBudgetSeconds, DEFAULT_SEARCH_EXCLUDED_DIRS, directoryReadHint, earlyReturnCause, emptyCallError, expandBraceGlob, failureCausesNote, findPathArgs, findPatternArgs, fusedLine, htmlOutline, isCommandTimeout, isEnvFilePath, isOutsideRoot, isPlaywrightRunCommand, isReadOnlyInspection, isSuiteRunCommand, linesWithinSerialized, literalDirPrefix, logShowsInlineFailureBodies, MAX_BATCH_READ_FILES, MAX_FIND_RESULTS, MAX_HTML_INLINE_CHARS, MAX_OUTPUT_SIZE, MAX_READ_CALL_CHARS, MAX_READ_RETURN_CHARS, MAX_READ_SIZE, MAX_SEARCH_CONTEXT_LINES, MAX_SEARCH_RESULTS, MAX_WRITE_SIZE, outputIsWithheldUntilExit, outputRedirectTarget, parseCheckCommand, parseCheckProblem, pathArgError, READ_RESULT_ENVELOPE_CHARS, redactSecrets, redactSecretsInCode, repeatedSuiteRunError, repeatingFailure, repeatingFailureNote, resolvePath, RUNNING_FAILURE_LINES, runningCauseCommand, runningOutputSliceCommand, searchTimeoutError, serializedChars, shellQuote, sliceLines, SMALL_FILE_WHOLE_CHARS, streamingBackgroundCommand, stripControlChars, suiteRunBudgetCommand, suiteRunConfigCommand, suiteRunPipelinePlacement, suiteRunPriorityLaunch, TOOL_RESULT_CHARS, truncateMiddle, universalCause, whitespaceTolerantReplace, withoutSuiteTimeout, } from './utilities.js';
667
667
  /**
668
668
  * How long exec_command waits for a command it backgrounded only because the
669
669
  * command asked for more than the tool's ceiling, before handing back a task id.
@@ -1219,6 +1219,23 @@ export function buildTools(backend, config) {
1219
1219
  result = isEnvFilePath(path) ? redactSecrets(result) : redactSecretsInCode(result);
1220
1220
  return result;
1221
1221
  }
1222
+ /**
1223
+ * The refusal for a write that would put the output filter's placeholder into a file.
1224
+ *
1225
+ * A placeholder may have been copied from filtered output or intentionally authored.
1226
+ * Ask the caller to recover the source value or explicitly declare intentional use;
1227
+ * the guard cannot infer the literal's origin from its bytes.
1228
+ *
1229
+ * @param path - The file the write targets.
1230
+ * @param mask - The added mask, exactly as the content writes it.
1231
+ * @returns The error message shown to the model.
1232
+ */
1233
+ function redactionMaskError(path, mask) {
1234
+ return (`Refused: the new content adds ${mask}, which may be the tool output filter's placeholder ` +
1235
+ `rather than the original value. Use read_file (${path} itself, or the source of the value) ` +
1236
+ 'to recover the original. If the application intentionally defines this redaction literal, ' +
1237
+ 'retry with intentional_redaction_placeholder: true.');
1238
+ }
1222
1239
  // ── Binary reads ───────────────────────────────────────────────
1223
1240
  /** Extensions whose files are never text: a `read_file` on one is refused by name. */
1224
1241
  const BINARY_FILE_EXTENSIONS = new Set([
@@ -1823,6 +1840,13 @@ export function buildTools(backend, config) {
1823
1840
  catch (_error) {
1824
1841
  /* file doesn't exist yet — oldContent stays null */
1825
1842
  }
1843
+ // A mask the output filter produced is not a value: refuse writing a NEW one into the
1844
+ // project, while allowing a file that already carries one to be rewritten unchanged.
1845
+ if (doRedact && input.intentional_redaction_placeholder !== true) {
1846
+ const mask = addedRedactionMask(content, oldContent ?? '');
1847
+ if (mask !== null)
1848
+ return { error: redactionMaskError(path, mask) };
1849
+ }
1826
1850
  if (onFileDiff)
1827
1851
  onFileDiff({ path, oldContent, newContent: content });
1828
1852
  await backend.writeFile(path, content);
@@ -1969,6 +1993,19 @@ export function buildTools(backend, config) {
1969
1993
  });
1970
1994
  continue;
1971
1995
  }
1996
+ // Same guard as write_file, judged per replacement against its own old_string: an
1997
+ // edit that carries an existing mask through is fine, one that ADDS a mask is refused.
1998
+ if (doRedact && input.intentional_redaction_placeholder !== true) {
1999
+ const mask = addedRedactionMask(newString, oldString);
2000
+ if (mask !== null) {
2001
+ failures.push({
2002
+ index: index + 1,
2003
+ start: startOf(oldString),
2004
+ message: redactionMaskError(path, mask),
2005
+ });
2006
+ continue;
2007
+ }
2008
+ }
1972
2009
  const count = content.split(oldString).length - 1;
1973
2010
  // The edit is ALREADY in the file: old_string is gone and a distinctive
1974
2011
  // new_string is there exactly once. The executor re-sends an edit it
@@ -3043,9 +3080,12 @@ export function buildTools(backend, config) {
3043
3080
  // truncateMiddle (not truncate): a failing build/test/migration puts its
3044
3081
  // error at the TAIL, so keep the head AND the tail — head-only truncation
3045
3082
  // strands the executor with passing progress and no failure reason.
3046
- // A command that only prints source files returns file content: the code-safe grade,
3047
- // as read_file uses (utilities.ts printsOnlySource).
3048
- const grade = printsOnlySource(command)
3083
+ // A command that only INSPECTS the workspace without printing arbitrary file content
3084
+ // (a pure source read, `ls`/`find`/`wc`) returns code, not an env dump: the code-safe
3085
+ // grade, as read_file uses (utilities.ts isReadOnlyInspection). A recursive search
3086
+ // (`.env` and JSON secret dumps are in its match set), an `.env` read, `env`/`printenv`
3087
+ // and an interpreter one-liner all keep the full name-keyed grade.
3088
+ const grade = isReadOnlyInspection(command)
3049
3089
  ? (s) => sanitizeFileContent(s, 'printed.ts')
3050
3090
  : sanitizeOutput;
3051
3091
  const stdout = grade(truncateMiddle(result.stdout, MAX_OUTPUT_SIZE));
@@ -57,6 +57,19 @@ export declare function redactSecrets(s: string): string;
57
57
  * @returns A redacted copy that preserves ordinary code verbatim.
58
58
  */
59
59
  export declare function redactSecretsInCode(s: string): string;
60
+ /**
61
+ * The redaction mask `next` adds over `previous`, or null when it adds none.
62
+ *
63
+ * `previous` is the file's previous content for `write_file`, and the replacement's own
64
+ * `old_string` for `edit_file` — an edit that carries an existing mask through (a file that
65
+ * already had one, read back and rewritten) adds no occurrence. A new occurrence may
66
+ * be copied output or intentional source; the caller declares the latter explicitly.
67
+ *
68
+ * @param next - The content about to be written (or the replacement's `new_string`).
69
+ * @param previous - The content it replaces, already on disk (or the `old_string`).
70
+ * @returns The added mask as written (`'[REDACTED]'`, `"[REDACTED]"`, `=[REDACTED]`), or null.
71
+ */
72
+ export declare function addedRedactionMask(next: string, previous: string): string | null;
60
73
  /**
61
74
  * Whether a shell command only PRINTS source files (`cat a.tsx`, `sed -n '1,40p' x.ts`,
62
75
  * `head -50 b.hurl`): its output is file content and gets the code-safe redaction, like
@@ -68,6 +81,30 @@ export declare function redactSecretsInCode(s: string): string;
68
81
  * @returns True when the command prints source files, with only literal headings and filters.
69
82
  */
70
83
  export declare function printsOnlySource(command: string): boolean;
84
+ /**
85
+ * Whether a shell command only INSPECTS the workspace WITHOUT printing a file's contents:
86
+ * it prints source files (a pure literal read, {@link printsOnlySource}), lists names
87
+ * (`ls`, `find`), or counts lines (`wc`) — joined by `;`, `&&` or `|`, with literal
88
+ * `echo`/`printf` headings and `cd`.
89
+ *
90
+ * Its output is code or names, not an env dump, so it gets the code-safe redaction
91
+ * ({@link redactSecretsInCode}) instead of the name-keyed env-dump passes. Without this,
92
+ * ordinary code values such as `tokenKey: 'jwtToken'` in a mixed source read and
93
+ * `ls | head` command would be masked by the environment-dump rules.
94
+ *
95
+ * A RECURSIVE SEARCH IS NOT INSPECTION (`grep -rn x .`, `rg x src/`): its output is the
96
+ * content of whichever files matched, including `.env` files and JSON secret dumps, so it
97
+ * keeps the full grade. A path with no extension is not evidence that it is a directory —
98
+ * `/dev/stdin` and an ordinary `secrets` file read the same way.
99
+ *
100
+ * Env dumps keep the full grade: `.env` anywhere in the command, `env`/`printenv`, a
101
+ * non-literal or redirecting form, and an interpreter one-liner (`node -e`, `python -c`)
102
+ * all return false.
103
+ *
104
+ * @param command - The shell command.
105
+ * @returns True when the command only reads or lists workspace content.
106
+ */
107
+ export declare function isReadOnlyInspection(command: string): boolean;
71
108
  /**
72
109
  * Whether a path is an env file, for which {@link redactSecrets}' full env-dump
73
110
  * treatment is appropriate rather than {@link redactSecretsInCode}. Matches
@@ -1 +1 @@
1
- {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
package/dist/utilities.js CHANGED
@@ -163,8 +163,41 @@ export function redactSecrets(s) {
163
163
  export function redactSecretsInCode(s) {
164
164
  return s.replace(SECRET_ENV_ASSIGNMENT, '$1=[REDACTED]');
165
165
  }
166
+ /**
167
+ * The placeholder the output filter substitutes for a hidden value. Copying it into
168
+ * application configuration changes the value rather than recovering it. The write
169
+ * tools check for added occurrences ({@link addedRedactionMask}); intentional literals
170
+ * require the caller's explicit per-call declaration.
171
+ *
172
+ * Only the shapes a value can take count: quoted (`'[REDACTED]'`, `"[REDACTED]"`) or
173
+ * assigned (`=[REDACTED]`). Prose that mentions the token is ordinary text.
174
+ */
175
+ const REDACTION_MASK = /'\[REDACTED\]'|"\[REDACTED\]"|=[ \t]*\[REDACTED\]/g;
176
+ /**
177
+ * The redaction mask `next` adds over `previous`, or null when it adds none.
178
+ *
179
+ * `previous` is the file's previous content for `write_file`, and the replacement's own
180
+ * `old_string` for `edit_file` — an edit that carries an existing mask through (a file that
181
+ * already had one, read back and rewritten) adds no occurrence. A new occurrence may
182
+ * be copied output or intentional source; the caller declares the latter explicitly.
183
+ *
184
+ * @param next - The content about to be written (or the replacement's `new_string`).
185
+ * @param previous - The content it replaces, already on disk (or the `old_string`).
186
+ * @returns The added mask as written (`'[REDACTED]'`, `"[REDACTED]"`, `=[REDACTED]`), or null.
187
+ */
188
+ export function addedRedactionMask(next, previous) {
189
+ const before = previous.match(REDACTION_MASK)?.length ?? 0;
190
+ const after = next.match(REDACTION_MASK) ?? [];
191
+ if (after.length <= before)
192
+ return null;
193
+ return after[before] ?? after[0] ?? '[REDACTED]';
194
+ }
166
195
  /** Source-file extensions a printing command's output is read as code for. */
167
196
  const SOURCE_FILE_RE = /\.(?:[cm]?[jt]sx?|css|scss|html|vue|svelte|md|sql|hurl)$/;
197
+ /** Programs whose output is file NAMES or counts, never another file's content. */
198
+ const INSPECTION_PROGRAMS = new Set(['find', 'ls', 'wc']);
199
+ /** `find` options that run a program or write a file — not read-only inspection. */
200
+ const FIND_NOT_INSPECTION = /^-(?:exec|execdir|ok|okdir|delete|fls|fprint|fprint0|fprintf)/;
168
201
  /**
169
202
  * A literal argument, not a shell expansion. The shared parser owns statement boundaries;
170
203
  * this deliberately small word grammar only decides whether an argument can read other data.
@@ -253,9 +286,46 @@ function sourcePrintFiles(program, args) {
253
286
  * @returns True when the command prints source files, with only literal headings and filters.
254
287
  */
255
288
  export function printsOnlySource(command) {
289
+ return printsOnly(command, false);
290
+ }
291
+ /**
292
+ * Whether a shell command only INSPECTS the workspace WITHOUT printing a file's contents:
293
+ * it prints source files (a pure literal read, {@link printsOnlySource}), lists names
294
+ * (`ls`, `find`), or counts lines (`wc`) — joined by `;`, `&&` or `|`, with literal
295
+ * `echo`/`printf` headings and `cd`.
296
+ *
297
+ * Its output is code or names, not an env dump, so it gets the code-safe redaction
298
+ * ({@link redactSecretsInCode}) instead of the name-keyed env-dump passes. Without this,
299
+ * ordinary code values such as `tokenKey: 'jwtToken'` in a mixed source read and
300
+ * `ls | head` command would be masked by the environment-dump rules.
301
+ *
302
+ * A RECURSIVE SEARCH IS NOT INSPECTION (`grep -rn x .`, `rg x src/`): its output is the
303
+ * content of whichever files matched, including `.env` files and JSON secret dumps, so it
304
+ * keeps the full grade. A path with no extension is not evidence that it is a directory —
305
+ * `/dev/stdin` and an ordinary `secrets` file read the same way.
306
+ *
307
+ * Env dumps keep the full grade: `.env` anywhere in the command, `env`/`printenv`, a
308
+ * non-literal or redirecting form, and an interpreter one-liner (`node -e`, `python -c`)
309
+ * all return false.
310
+ *
311
+ * @param command - The shell command.
312
+ * @returns True when the command only reads or lists workspace content.
313
+ */
314
+ export function isReadOnlyInspection(command) {
315
+ return printsOnly(command, true);
316
+ }
317
+ /**
318
+ * The one segment grammar both grades share: literal words only, no wrapper or group, no
319
+ * backgrounding, and every byte between segments a separator.
320
+ *
321
+ * @param command - The shell command.
322
+ * @param inspection - Also accept name/count listing (`ls`, `find`, `wc`).
323
+ * @returns True when every segment is allowed and at least one prints something.
324
+ */
325
+ function printsOnly(command, inspection) {
256
326
  if (/\.env\b/.test(command))
257
327
  return false;
258
- let readsSource = false;
328
+ let prints = false;
259
329
  let previousEnd = 0;
260
330
  for (const located of locatedCommandSegments(command)) {
261
331
  const { segment, start, end, programOffset, separator, terminator } = located;
@@ -302,6 +372,13 @@ export function printsOnlySource(command) {
302
372
  return false;
303
373
  }
304
374
  }
375
+ else if (inspection && INSPECTION_PROGRAMS.has(program) && separator !== '|') {
376
+ // Names and counts only — nothing here can be another file's content. `find` is the
377
+ // exception that can run a program or write a file.
378
+ if (program === 'find' && args.some((arg) => FIND_NOT_INSPECTION.test(arg)))
379
+ return false;
380
+ prints = true;
381
+ }
305
382
  else {
306
383
  const filter = separator === '|';
307
384
  if (!(filter ? /^(?:head|tail|sort|uniq|wc|cut|nl|grep)$/ : /^(?:cat|head|tail|nl|sed|grep|rg)$/).test(program)) {
@@ -319,11 +396,11 @@ export function printsOnlySource(command) {
319
396
  !files.every((file) => !file.startsWith('-') && SOURCE_FILE_RE.test(file))) {
320
397
  return false;
321
398
  }
322
- readsSource = true;
399
+ prints = true;
323
400
  }
324
401
  }
325
402
  }
326
- return readsSource && /^[\s;]*$/.test(command.slice(previousEnd));
403
+ return prints && /^[\s;]*$/.test(command.slice(previousEnd));
327
404
  }
328
405
  /**
329
406
  * Whether a path is an env file, for which {@link redactSecrets}' full env-dump
@@ -3980,11 +4057,8 @@ export function repeatingFailureNote(found, o) {
3980
4057
  `repeats this one cause. Stop it and fix that cause first: \`exec_command: ${o.stop}\`, ` +
3981
4058
  `then run the whole suite again. It is still going (${where}).${reproduce}`);
3982
4059
  }
3983
- // Everything else is a note on a run the wait is still waiting for, and both its shapes end the
3984
- // same way: the run finishes, because it is the only thing that names the causes this finding is
3985
- // not. What it does NOT carry is the "Stop it if every test fails this way" clause — that one
3986
- // belongs to a PROVEN cause the run is still walking (the sentence below), never to a lead:
3987
- // xr-molecule-flash-m99's executor read it on a shared duration and voided the run.
4060
+ // The same predicate controls both an early return and stop advice. Without
4061
+ // that verdict, neither a repeated error nor a shared duration asks for a stop.
3988
4062
  const keepGoing = `Let the rest of the run finish — it is the only thing that will name the causes that are NOT ` +
3989
4063
  `this one, and a run stopped at its first repeating cause costs a second whole run to find ` +
3990
4064
  `them. It is still going (${where}).`;
@@ -3992,10 +4066,9 @@ export function repeatingFailureNote(found, o) {
3992
4066
  return (`${found.count} different tests in this run have already failed the same way — ${signature} — ` +
3993
4067
  `so one cause is repeating:\n${rows}${more}\n` +
3994
4068
  (o.editsInvalidateRun
3995
- ? `Work out the fix now: apply it when the run ends, not while it walks. Stop it only if every test it walks `
3996
- : `Start fixing it now, while the run keeps walking. Stop it only if every test it walks `) +
3997
- `fails this same way (the app unreachable, a 5xx on every request, the same selector timing ` +
3998
- `out on every test of every file so far).${reproduce} ${keepGoing}${thenRun}`);
4069
+ ? `Work out the fix now: apply it when the run ends, not while it walks.`
4070
+ : `Start fixing it now, while the run keeps walking.`) +
4071
+ `${reproduce} ${keepGoing}${thenRun}`);
3999
4072
  return (`${found.count} different tests in this run each failed after ~${found.seconds}s — the same ` +
4000
4073
  `duration to within half a second. A shared duration is a lead, not a cause: a suite whose ` +
4001
4074
  `config sets a timeout spends that timeout on every failure that waits for anything, so ` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.11.1",
3
+ "version": "1.12.0",
4
4
  "description": "Shared AI agent tools with backend abstraction for sandbox and local execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",