@archmax-ai/harness 0.4.1 → 0.5.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 +8 -0
- package/dist/agent.d.ts +14 -0
- package/dist/agent.js.map +1 -1
- package/dist/assembly/compose.d.ts +12 -9
- package/dist/assembly/compose.js +69 -42
- package/dist/assembly/compose.js.map +1 -1
- package/dist/assembly/index.js +51 -11
- package/dist/assembly/index.js.map +1 -1
- package/dist/authoring-skill/archmax-harness/SKILL.md +2 -2
- package/dist/authoring-skill/archmax-harness/references/backend-integration.md +33 -11
- package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +2 -1
- package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +65 -8
- package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +1 -1
- package/dist/cli/bootstrap.d.ts +8 -1
- package/dist/cli/bootstrap.js +43 -3
- package/dist/cli/bootstrap.js.map +1 -1
- package/dist/cli/command.d.ts +3 -1
- package/dist/cli/command.js +1 -1
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/turn.d.ts +3 -1
- package/dist/cli/turn.js +1 -0
- package/dist/cli/turn.js.map +1 -1
- package/dist/cli.js +9 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/attachments.d.ts +64 -0
- package/dist/core/attachments.js +87 -0
- package/dist/core/attachments.js.map +1 -0
- package/dist/core/file-operations.d.ts +22 -0
- package/dist/core/file-operations.js +54 -0
- package/dist/core/file-operations.js.map +1 -1
- package/dist/core/path-mapping.js +2 -2
- package/dist/core/path-mapping.js.map +1 -1
- package/dist/core/platform-prompt.generated.js +1 -1
- package/dist/core/platform-prompt.generated.js.map +1 -1
- package/dist/core/prompt.js +3 -2
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/session-zone.d.ts +1 -1
- package/dist/core/session-zone.js +2 -2
- package/dist/core/session-zone.js.map +1 -1
- package/dist/core/workspace-router.d.ts +5 -2
- package/dist/core/workspace-router.js +14 -9
- package/dist/core/workspace-router.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/kernel/kernel.d.ts +9 -0
- package/dist/kernel/kernel.js +15 -0
- package/dist/kernel/kernel.js.map +1 -1
- package/dist/machine/delegation.d.ts +3 -3
- package/dist/machine/delegation.js +3 -3
- package/dist/machine/machine.d.ts +7 -0
- package/dist/machine/machine.js +14 -0
- package/dist/machine/machine.js.map +1 -1
- package/dist/machine/signature.d.ts +16 -5
- package/dist/machine/signature.js +25 -4
- package/dist/machine/signature.js.map +1 -1
- package/dist/machine/spec-schema.d.ts +10 -0
- package/dist/sessions/resume.d.ts +9 -0
- package/dist/sessions/resume.js +13 -0
- package/dist/sessions/resume.js.map +1 -1
- package/dist/workflow/control-tools.d.ts +12 -1
- package/dist/workflow/control-tools.js +33 -4
- package/dist/workflow/control-tools.js.map +1 -1
- package/dist/workflow/file-values.d.ts +44 -0
- package/dist/workflow/file-values.js +29 -0
- package/dist/workflow/file-values.js.map +1 -0
- package/dist/workflow/governance.d.ts +4 -2
- package/dist/workflow/governance.js +2 -27
- package/dist/workflow/governance.js.map +1 -1
- package/dist/workflow/middleware.d.ts +6 -1
- package/dist/workflow/middleware.js +25 -2
- package/dist/workflow/middleware.js.map +1 -1
- package/dist/workflow/parks.js +5 -1
- package/dist/workflow/parks.js.map +1 -1
- package/dist/workflow/returns-check.d.ts +3 -0
- package/dist/workflow/returns-check.js +1 -1
- package/dist/workflow/returns-check.js.map +1 -1
- package/dist/workflow/signature-checks.d.ts +47 -5
- package/dist/workflow/signature-checks.js +73 -9
- package/dist/workflow/signature-checks.js.map +1 -1
- package/dist/workflow/sub-workflow.d.ts +14 -2
- package/dist/workflow/sub-workflow.js +119 -24
- package/dist/workflow/sub-workflow.js.map +1 -1
- package/dist/workflow/tool-service.d.ts +4 -0
- package/dist/workflow/tool-service.js +5 -2
- package/dist/workflow/tool-service.js.map +1 -1
- package/dist/workflow/turn-boundary.d.ts +3 -0
- package/dist/workflow/turn-boundary.js +5 -2
- package/dist/workflow/turn-boundary.js.map +1 -1
- package/dist/workflow/workflow-tools.js +11 -0
- package/dist/workflow/workflow-tools.js.map +1 -1
- package/package.json +2 -2
- package/skills/archmax-harness/SKILL.md +2 -2
- package/skills/archmax-harness/references/backend-integration.md +33 -11
- package/skills/archmax-harness/references/hook-and-test-scripts.md +2 -1
- package/skills/archmax-harness/references/workflow-schema.md +65 -8
- package/skills/archmax-harness/references/workflow-yaml.md +1 -1
- package/dist/workflow/prompt-pruning.d.ts +0 -20
- package/dist/workflow/prompt-pruning.js +0 -83
- package/dist/workflow/prompt-pruning.js.map +0 -1
|
@@ -106,7 +106,7 @@ All optional (`CreateAgentParams`, `src/assembly/index.ts`):
|
|
|
106
106
|
| `checkpointer` | `BaseCheckpointSaver` | Custom-adapter escape hatch; takes precedence over the session store for checkpoint persistence. Defaults to a durable `BackendCheckpointSaver` writing through the session store. Use `MemorySaver` for ephemeral runs. |
|
|
107
107
|
| `middleware` | `AgentMiddleware[]` | Extra middleware appended after workflow instrumentation. |
|
|
108
108
|
| `onEvent` | `WorkflowEventHandler` | Subscribe to all lifecycle diagnostics; suppresses console output when set. |
|
|
109
|
-
| `promptCache` | `PromptCacheOptions` | `{ enabled?, ttl?: "5m" \| "1h" }`. Provider prompt caching for the stable prefix; on by default. Falls back to `settings.prompt_cache`, then `ARCHMAX_PROMPT_CACHE`/`_TTL`. |
|
|
109
|
+
| `promptCache` | `PromptCacheOptions` | `{ enabled?, ttl?: "5m" \| "1h" }`. Provider prompt caching for the stable prefix; on by default. Falls back to `settings.prompt_cache`, then `ARCHMAX_PROMPT_CACHE`/`_TTL`. Turning it off does not stop `ChatAnthropic` or `ChatBedrockConverse` caching: Deep Agents installs LangChain's caching middleware for them itself (5-minute lifetime). |
|
|
110
110
|
| `pricing` | `PricingTable` | USD per 1M tokens, keyed by model id (`default` matches any): `{ input?, output?, cacheRead?, cacheWrite? }`. Looked up by the id the response reported, else the id the runtime was configured to run — so a keyed table prices a workload behind a proxy that echoes no model back. Input rate applies to the input tokens the cache did not serve. Makes `costUsd` appear on usage events, run metadata, and the CLI footer. Falls back to `ARCHMAX_PRICE_*`. Unpriced → tokens only. |
|
|
111
111
|
|
|
112
112
|
Fails closed: throws `WorkflowLoadError` if the named workflow's `workflow.yaml`
|
|
@@ -333,9 +333,11 @@ turn ended in — the position, variables, transcript and files are already ther
|
|
|
333
333
|
message.
|
|
334
334
|
|
|
335
335
|
The runtime does not reposition a later turn, so nothing is injected into the
|
|
336
|
-
transcript to explain a jump. When
|
|
337
|
-
|
|
338
|
-
|
|
336
|
+
transcript to explain a jump. When the current state can serve the new message, the
|
|
337
|
+
agent answers there without a reset. That includes a terminal state that is also the
|
|
338
|
+
state the conversation began in, such as a one-state chat workflow. When a turn needs
|
|
339
|
+
a path the current state cannot reach, the agent calls `archmax_reset` to return to
|
|
340
|
+
the state the conversation began in (available in every state). To continue *mid-state* instead — inside the state
|
|
339
341
|
that stopped, with the arrival in its transcript — the turn must park rather than
|
|
340
342
|
finish.
|
|
341
343
|
|
|
@@ -378,7 +380,7 @@ const outcome = await agent.workflow!.send(sessionId, { message: "Refund the ord
|
|
|
378
380
|
|
|
379
381
|
- `signatureJsonSchema(entries)` → `{ type: "object", properties, required }`:
|
|
380
382
|
one property per entry in declaration order, every name required,
|
|
381
|
-
`date`/`date-time` as `{ type: "string", format }`, an untyped entry as `{}`,
|
|
383
|
+
`date`/`date-time`/`file` as `{ type: "string", format }`, an untyped entry as `{}`,
|
|
382
384
|
an entry's `description` carried over. It adds no `additionalProperties`; set
|
|
383
385
|
it for your own ingress.
|
|
384
386
|
- `signatureValueIssues(entries, values)` → one issue per missing name and per
|
|
@@ -387,6 +389,19 @@ const outcome = await agent.workflow!.send(sessionId, { message: "Refund the ord
|
|
|
387
389
|
`"4"` to `4` before it validates or seeds.
|
|
388
390
|
- A trigger's `description` is written for the caller. Use it as the MCP tool
|
|
389
391
|
or operation description. The session's own model never sees it.
|
|
392
|
+
- **A `file` entry** (`format: "file"` in the schema) takes a workspace path. To
|
|
393
|
+
hand a session an uploaded file, pass it on the turn rather than writing into
|
|
394
|
+
the store yourself:
|
|
395
|
+
`send(sessionId, { message, files: { invoice: { name: "invoice.pdf", content: bytes } } })`.
|
|
396
|
+
The runtime places the bytes in the session's `scratchpad/attachments/` (a taken
|
|
397
|
+
name gets `-1`, `-2`, …), seeds `invoice`, locked, with the placed path, and the
|
|
398
|
+
turn boundary then checks that the file is there and readable. `send` throws
|
|
399
|
+
`InvalidTurnFileError`, before anything is written, for a bad variable or file
|
|
400
|
+
name, a variable also given in `variables`, a session parked at a human state, or
|
|
401
|
+
bytes the store cannot hold exactly (a non-text file needs a store with
|
|
402
|
+
`uploadFiles`). `signatureValueIssues` checks only a `file` value's shape, so a
|
|
403
|
+
start form validates the path the upload will produce, or skips the entry and
|
|
404
|
+
lets `files` supply it.
|
|
390
405
|
- A host that reads specs itself must read `requires`/`returns` through
|
|
391
406
|
`normalizeSignature` (both spellings → `{ name, type?, description? }[]`),
|
|
392
407
|
never as `string[]`: an entry may be an object. Hosts must be on the release
|
|
@@ -618,6 +633,10 @@ and a delete itself. Deep Agents is handed the workspace without `delete`, so it
|
|
|
618
633
|
own recursive `delete` tool never exists: `remove_file` is the one way to delete
|
|
619
634
|
a file.
|
|
620
635
|
|
|
636
|
+
A store's `grep` receives the call's match cap as its fourth argument,
|
|
637
|
+
`maxCount` (the agent's `max_count`, else Deep Agents' 1,000). A store may stop
|
|
638
|
+
there and return `truncated: true`; the workspace caps one that ignores it.
|
|
639
|
+
|
|
621
640
|
### Host tools
|
|
622
641
|
|
|
623
642
|
A host tool built with `toolsFromMap` reaches the workspace the way the
|
|
@@ -704,7 +723,7 @@ real). A bespoke target that intercepts by other means sets
|
|
|
704
723
|
`capabilities.toolMocks` itself. Mockless cases run against any
|
|
705
724
|
workflow-governed target.
|
|
706
725
|
|
|
707
|
-
**Sub-workflows inherit the assembly.** When a workflow delegates (by
|
|
726
|
+
**Sub-workflows inherit the assembly.** When a workflow delegates (by calling
|
|
708
727
|
an `archmax_workflow_<slug>` tool), the child runtime is
|
|
709
728
|
composed from the *same* resolved inputs as the parent — model and
|
|
710
729
|
`modelFactory`, `backend` and `mounts`, `sessionStore` and `checkpointer`, host
|
|
@@ -717,11 +736,14 @@ never delegated to is never loaded, and one delegated from many places is
|
|
|
717
736
|
composed once. A child whose spec is broken surfaces as a *dispatch* failure, not
|
|
718
737
|
an assembly failure — a parent still assembles.
|
|
719
738
|
|
|
720
|
-
The child runs
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
739
|
+
The child runs as a **separate session**, `<parent>~<state>:<workflow>:<n>`, in
|
|
740
|
+
the same session store, with its own checkpoints, its own token accounting and its
|
|
741
|
+
own file space: its `scratchpad/` is not its caller's, so it can neither read nor
|
|
742
|
+
overwrite a file of its caller's. `sessions.list()` reports it beside its caller
|
|
743
|
+
with `parentSessionId` naming the caller, and `sessions.delete` removes it by its
|
|
744
|
+
own id. The only files that cross are the runtime's copies of declared `file` arguments and
|
|
745
|
+
`file` returns. `capabilities.subWorkflows` is stamped `true` for a governed
|
|
746
|
+
assembly and `false` for the plain one.
|
|
725
747
|
|
|
726
748
|
Omit both options and behavior is identical to `archmax test`. Cases run
|
|
727
749
|
sequentially (`tests.maxConcurrency` above 1 is rejected, not silently
|
|
@@ -322,7 +322,8 @@ state fails that call closed with `parked`.
|
|
|
322
322
|
Scripts still may not call `archmax_advance` (moving the state machine is the model's governed
|
|
323
323
|
decision) or `archmax_set_variables`. Concurrent calls succeed or fail **independently**, so a script
|
|
324
324
|
can act on what worked — `Promise.allSettled` is the honest shape when partial success is
|
|
325
|
-
meaningful.
|
|
325
|
+
meaningful. Each sub-run is its own session with its own `scratchpad/`, so concurrent sub-runs
|
|
326
|
+
never collide on a path; a `file` return comes back as a copy under a name no other file holds.
|
|
326
327
|
|
|
327
328
|
### Worked example: a `before` gate
|
|
328
329
|
|
|
@@ -557,7 +557,9 @@ states:
|
|
|
557
557
|
- **`type`** is one of `string`, `integer` (no fractional part), `number`
|
|
558
558
|
(finite), `boolean`, `date` (RFC 3339 `YYYY-MM-DD`, a real calendar day),
|
|
559
559
|
`date-time` (RFC 3339 with a mandatory `Z`/`±hh:mm` offset), `object` (not an
|
|
560
|
-
array)
|
|
560
|
+
array), `array` or `file` (a path from the workspace root, such as
|
|
561
|
+
`scratchpad/attachments/invoice.pdf` or `skills/billing/assets/template.pdf`; see
|
|
562
|
+
[Passing files](#passing-files)). Nothing is coerced (`"4"` is not an `integer`) and a typed
|
|
561
563
|
entry never takes `null`. It is held **at the start** (a mistyped seed is
|
|
562
564
|
refused before any model call), **at the write** (`archmax_set_variables` of a
|
|
563
565
|
mistyped typed return of the current trigger is a correctable refusal,
|
|
@@ -565,6 +567,17 @@ states:
|
|
|
565
567
|
run — in practice a script or hook write). There are no enums, item or
|
|
566
568
|
property schemas, ranges or optional inputs. An unknown `type`, an unknown
|
|
567
569
|
entry key (`default:`) or an empty `description` fails load.
|
|
570
|
+
- **A `file` value must name a readable file.** The pure rule checks only the
|
|
571
|
+
path's shape (a host runs it in a browser). At the start, at the write, at
|
|
572
|
+
completion and at a delegation call the runtime also requires a **file** (not a
|
|
573
|
+
folder) at the path that the session may read **on runtime authority** — the
|
|
574
|
+
rules a hook is bound by: zone rules (`checkpoints/`, `artifacts/`, `_specs/`
|
|
575
|
+
never) and every workflow-wide `forbid_always`, inherited ones included; the
|
|
576
|
+
state's allow list and mount/skill grants do not narrow it. So tell the agent to
|
|
577
|
+
write the file *before* it sets a `file` return: `archmax_set_variables` refuses
|
|
578
|
+
a path with nothing there. A host hands a file in with `TurnInput.files` (CLI:
|
|
579
|
+
`archmax run … --file invoice=./invoice.pdf`), which places it under
|
|
580
|
+
`scratchpad/attachments/` and seeds the path.
|
|
568
581
|
- **When to type.** Type an entry when something outside the session reads the
|
|
569
582
|
contract: a delegating model that must build the argument, a host publishing an
|
|
570
583
|
MCP tool or a start form. Leave it bare when any value will do. Typing a
|
|
@@ -1015,7 +1028,8 @@ the host at assembly (`variables`, every seed locked), the agent mid-run
|
|
|
1015
1028
|
|
|
1016
1029
|
`trigger` holds the current turn's trigger id. `title` holds a short one-line label
|
|
1017
1030
|
naming the task the run is doing; the platform system prompt asks the agent to set
|
|
1018
|
-
one as its first activity and
|
|
1031
|
+
one as its first activity, and to rename it only when the whole conversation has
|
|
1032
|
+
moved to a different subject (a follow-up on the same subject keeps it), so a
|
|
1019
1033
|
host can name a run instead of showing a session id. A sub-workflow's child is not
|
|
1020
1034
|
asked — its title names a session nothing lists and is never returned — so its
|
|
1021
1035
|
prompt leaves the step out; do not write "set the title" into a child's state
|
|
@@ -1340,7 +1354,7 @@ enrich:
|
|
|
1340
1354
|
delegation may happen is decided by the caller's `tools.allow` entry. A target
|
|
1341
1355
|
with no `manual` entry has no state to start in and fails closed. `session:` and
|
|
1342
1356
|
`message:` on that trigger are host-facing keys a delegation ignores: a sub-run
|
|
1343
|
-
|
|
1357
|
+
is its own session, derived from its caller's, and carries no message. `sub-workflow` is no longer
|
|
1344
1358
|
a trigger id — load and `validate` report it with the rename.
|
|
1345
1359
|
- **Declare the child's signature** on that trigger — the contract, enforced both
|
|
1346
1360
|
ways and at both ingresses:
|
|
@@ -1400,14 +1414,17 @@ enrich:
|
|
|
1400
1414
|
state's work. A workspace overriding the platform prompt
|
|
1401
1415
|
(`.platform/system/GRAPH_STATE.md`) keeps that by wrapping what children skip
|
|
1402
1416
|
in `<!-- top-level-only -->` … `<!-- /top-level-only -->` lines.
|
|
1403
|
-
- **Same agent, isolated context,
|
|
1417
|
+
- **Same agent, isolated context, own session.** Same model, backend, host
|
|
1404
1418
|
tools; its **own** grading rubrics, from its own spec; a fresh transcript; the child's *own* per-state
|
|
1405
|
-
`tools.allow`. It
|
|
1406
|
-
|
|
1419
|
+
`tools.allow`. It is a separate session (`<parent>~<state>:<workflow>:<n>`)
|
|
1420
|
+
with its own checkpoints and its own `scratchpad/`: a path it reads or writes
|
|
1421
|
+
resolves inside its own session, so it can neither see nor overwrite a file of
|
|
1422
|
+
its caller's, and concurrent sub-runs cannot collide on a path.
|
|
1407
1423
|
- **Nothing crosses implicitly.** Down: only the arguments the call passed —
|
|
1408
1424
|
the calling run's own variables are not copied. Up: only the result message
|
|
1409
|
-
and the
|
|
1410
|
-
|
|
1425
|
+
and the declared returns. Everything else the child sets or writes stays in its
|
|
1426
|
+
session. The only files that cross are runtime-made copies of `file` arguments
|
|
1427
|
+
and `file` returns (see "Passing files" below).
|
|
1411
1428
|
- **Bounds** — the dispatcher's `bounds: { maxDepth: 3, maxConcurrent: 4 }`. No longer a spec key: the strict schema rejects `settings.sub_workflows` by name.
|
|
1412
1429
|
Excess concurrency queues; depth and cycles are refused.
|
|
1413
1430
|
- **Params are the sub-run's initial variables** — same construction, same name
|
|
@@ -1435,6 +1452,46 @@ parent reading a field the child does not return is an **error**; a state whose
|
|
|
1435
1452
|
still carry it), and a fan-out is exempt from that warning because its
|
|
1436
1453
|
entries' keys are not knowable statically.
|
|
1437
1454
|
|
|
1455
|
+
### Passing files
|
|
1456
|
+
|
|
1457
|
+
A sub-run's `scratchpad/` is not its caller's, so a bare path string returned by a
|
|
1458
|
+
child (`returns: [result_file]`, untyped) names a file the caller **cannot
|
|
1459
|
+
read**. Type the entry `file` instead, and the runtime copies the file across:
|
|
1460
|
+
|
|
1461
|
+
```yaml
|
|
1462
|
+
# the child
|
|
1463
|
+
triggers:
|
|
1464
|
+
manual:
|
|
1465
|
+
requires: [{ name: invoice, type: file }]
|
|
1466
|
+
returns: [{ name: report, type: file }]
|
|
1467
|
+
```
|
|
1468
|
+
|
|
1469
|
+
- **Down.** The caller passes any path in its workspace (`scratchpad/inbox/a.pdf`,
|
|
1470
|
+
`skills/billing/assets/template.pdf`). Before the child starts, the runtime
|
|
1471
|
+
copies the exact bytes into the **child's** `scratchpad/attachments/` (same name;
|
|
1472
|
+
two arguments with one name take `-1`, `-2`) and seeds the child with that path,
|
|
1473
|
+
so its opening message shows it. The child edits its own copy and never the
|
|
1474
|
+
caller's file. The argument is a `read` path argument of the delegation tool, so
|
|
1475
|
+
a `paths:` guard on the allow entry and the zone and mount rules bind it. An
|
|
1476
|
+
argument naming nothing is refused `invalid-param` before the child runs. A
|
|
1477
|
+
failed call's record names the caller's path.
|
|
1478
|
+
- **Up.** On completion, each `file` return the child set is copied into the
|
|
1479
|
+
**caller's** `scratchpad/attachments/` and the result names that path. A taken
|
|
1480
|
+
name gets the lowest free `-1`, `-2`, … before the extension (`report-1.pdf`), so
|
|
1481
|
+
repeated or parallel calls never overwrite each other or the caller's files. A
|
|
1482
|
+
return whose file is gone at completion fails the call `invalid-return`.
|
|
1483
|
+
- **No laundering.** A `file` value must name a file the session may read on
|
|
1484
|
+
runtime authority, and a child inherits every ancestor's `forbid_always`. So a
|
|
1485
|
+
child cannot hand back a file its caller's workflow denies: its agent's write
|
|
1486
|
+
is refused, and a script's write is rejected at completion.
|
|
1487
|
+
- **Instructions to write.** Tell the child to write the file *first* and then set
|
|
1488
|
+
the return to its path. Tell the caller the returned path is under
|
|
1489
|
+
`scratchpad/attachments/`. Name files for what they hold (`<order_id>.json`):
|
|
1490
|
+
the name survives the copy.
|
|
1491
|
+
- **Mocks and cases.** A mocked `file` return names a file in the case's own
|
|
1492
|
+
session (seed it with `workspace:`), and it arrives copied into
|
|
1493
|
+
`scratchpad/attachments/` like a real one. Assert the copy's path.
|
|
1494
|
+
|
|
1438
1495
|
### A parked run may speak, never act
|
|
1439
1496
|
|
|
1440
1497
|
A park does not end the conversation. Two moments get a **reply-only turn** — one
|
|
@@ -50,7 +50,7 @@ states:
|
|
|
50
50
|
- { name: due, type: date, description: The day it is due. } # typed: held at the boundary
|
|
51
51
|
returns: [result_file] # variables the run guarantees on completion (a caller's result);
|
|
52
52
|
# short of them: a child returns what it set + a `note`; a top-level run is rejected
|
|
53
|
-
# entry types: string integer number boolean date date-time object array
|
|
53
|
+
# entry types: string integer number boolean date date-time object array file
|
|
54
54
|
instructions: >-
|
|
55
55
|
Record the decision in scratchpad/refund.json, then archmax_advance to
|
|
56
56
|
review; never close the case yourself.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pruning of upstream Deep Agents prompt guidance for built-in tools an
|
|
3
|
-
* assembly withholds: guidance for a tool the model cannot call only teaches it
|
|
4
|
-
* to try.
|
|
5
|
-
*/
|
|
6
|
-
/** The upstream headings that document `tool`'s guidance (empty when unknown). */
|
|
7
|
-
export declare function upstreamSectionsFor(tool: string): readonly string[];
|
|
8
|
-
export interface PruneResult {
|
|
9
|
-
/** The prompt text with matched sections removed. */
|
|
10
|
-
text: string;
|
|
11
|
-
/** Headings that were found and removed. */
|
|
12
|
-
removed: string[];
|
|
13
|
-
/**
|
|
14
|
-
* Tools whose guidance was found nowhere. A partial match is a successful
|
|
15
|
-
* prune (upstream may carry only some of a tool's sections).
|
|
16
|
-
*/
|
|
17
|
-
missingTools?: string[];
|
|
18
|
-
}
|
|
19
|
-
/** Prune the upstream guidance for every tool in `undisclosed`; tools with no known sections are ignored. */
|
|
20
|
-
export declare function pruneUndisclosedToolSections(text: string, undisclosed: readonly string[]): PruneResult;
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pruning of upstream Deep Agents prompt guidance for built-in tools an
|
|
3
|
-
* assembly withholds: guidance for a tool the model cannot call only teaches it
|
|
4
|
-
* to try.
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Upstream section headings owned by a built-in tool's guidance.
|
|
8
|
-
*
|
|
9
|
-
* `task`'s guidance is two sections, and both must be named: the spawner
|
|
10
|
-
* overview carries the bulk of it, and the notes section follows. A partial
|
|
11
|
-
* match counts as a successful prune, so listing only one of them silently ships
|
|
12
|
-
* the other.
|
|
13
|
-
*/
|
|
14
|
-
const SECTIONS_BY_TOOL = {
|
|
15
|
-
task: ["## `task` (subagent spawner)", "## Important Task Tool Usage Notes to Remember"],
|
|
16
|
-
};
|
|
17
|
-
/** The upstream headings that document `tool`'s guidance (empty when unknown). */
|
|
18
|
-
export function upstreamSectionsFor(tool) {
|
|
19
|
-
return SECTIONS_BY_TOOL[tool] ?? [];
|
|
20
|
-
}
|
|
21
|
-
/** A section spans its heading line to the next heading of the same or higher level. */
|
|
22
|
-
function sectionEnd(lines, start, level) {
|
|
23
|
-
for (let i = start + 1; i < lines.length; i++) {
|
|
24
|
-
const match = /^(#{1,6})\s/.exec(lines[i]);
|
|
25
|
-
if (match && match[1].length <= level)
|
|
26
|
-
return i;
|
|
27
|
-
}
|
|
28
|
-
return lines.length;
|
|
29
|
-
}
|
|
30
|
-
function headingLevel(heading) {
|
|
31
|
-
return /^(#{1,6})\s/.exec(heading)?.[1].length ?? 2;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Put a target heading on its own line when composition glued it to the end of
|
|
35
|
-
* the previous one.
|
|
36
|
-
*
|
|
37
|
-
* Upstream concatenates its prompt fragments without a separating newline, so a
|
|
38
|
-
* section can arrive as `…within files## \`task\` (subagent spawner)`. Matching is
|
|
39
|
-
* line-anchored (a `##` mid-sentence is prose, not a heading), so without this
|
|
40
|
-
* the section is silently kept and billed on every call. Narrow by construction:
|
|
41
|
-
* only a heading we were asked to remove is ever split out.
|
|
42
|
-
*/
|
|
43
|
-
function unglueHeadings(text, headings) {
|
|
44
|
-
let out = text;
|
|
45
|
-
for (const heading of headings) {
|
|
46
|
-
let at = out.indexOf(heading);
|
|
47
|
-
while (at > 0) {
|
|
48
|
-
if (out[at - 1] !== "\n") {
|
|
49
|
-
out = `${out.slice(0, at)}\n${out.slice(at)}`;
|
|
50
|
-
at += 1;
|
|
51
|
-
}
|
|
52
|
-
at = out.indexOf(heading, at + heading.length);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return out;
|
|
56
|
-
}
|
|
57
|
-
/** Remove each heading's section. Matching is exact on the trimmed heading line. */
|
|
58
|
-
function pruneSections(text, headings) {
|
|
59
|
-
if (!text || headings.length === 0)
|
|
60
|
-
return { text, removed: [] };
|
|
61
|
-
const removed = [];
|
|
62
|
-
let lines = unglueHeadings(text, headings).split("\n");
|
|
63
|
-
for (const heading of headings) {
|
|
64
|
-
const index = lines.findIndex((line) => line.trim() === heading);
|
|
65
|
-
if (index === -1)
|
|
66
|
-
continue;
|
|
67
|
-
const end = sectionEnd(lines, index, headingLevel(heading));
|
|
68
|
-
lines = [...lines.slice(0, index), ...lines.slice(end)];
|
|
69
|
-
removed.push(heading);
|
|
70
|
-
}
|
|
71
|
-
// Collapse the blank runs left behind so the result is byte-stable however many sections were cut.
|
|
72
|
-
return { text: lines.join("\n").replace(/\n{3,}/g, "\n\n").trim(), removed };
|
|
73
|
-
}
|
|
74
|
-
/** Prune the upstream guidance for every tool in `undisclosed`; tools with no known sections are ignored. */
|
|
75
|
-
export function pruneUndisclosedToolSections(text, undisclosed) {
|
|
76
|
-
const result = pruneSections(text, undisclosed.flatMap((tool) => [...upstreamSectionsFor(tool)]));
|
|
77
|
-
const missingTools = undisclosed.filter((tool) => {
|
|
78
|
-
const owned = upstreamSectionsFor(tool);
|
|
79
|
-
return owned.length > 0 && !owned.some((heading) => result.removed.includes(heading));
|
|
80
|
-
});
|
|
81
|
-
return { ...result, ...(missingTools.length > 0 ? { missingTools } : {}) };
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=prompt-pruning.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-pruning.js","sourceRoot":"","sources":["../../src/workflow/prompt-pruning.ts"],"names":[],"mappings":"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"}
|