@mjasnikovs/pi-task 0.38.28 → 0.38.30
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/dist/config/config.d.ts +70 -70
- package/dist/config/config.js +26 -35
- package/dist/config/extension-list.d.ts +6 -5
- package/dist/config/extension-list.js +3 -2
- package/dist/config/reasoning-args.d.ts +9 -7
- package/dist/config/reasoning-args.js +12 -10
- package/dist/config/reasoning.d.ts +44 -105
- package/dist/config/reasoning.js +27 -704
- package/dist/config/register.d.ts +34 -48
- package/dist/config/register.js +41 -51
- package/dist/config/tool-list.d.ts +16 -16
- package/dist/config/tool-list.js +1 -1
- package/dist/remote/bridge.d.ts +19 -10
- package/dist/remote/bridge.js +3 -2
- package/dist/remote/broadcast.js +3 -1
- package/dist/remote/events.js +12 -11
- package/dist/remote/history.d.ts +1 -1
- package/dist/remote/protocol.d.ts +6 -3
- package/dist/remote/protocol.js +2 -1
- package/dist/remote/push.d.ts +16 -16
- package/dist/remote/push.js +27 -27
- package/dist/remote/register.d.ts +3 -3
- package/dist/remote/register.js +17 -19
- package/dist/remote/server.d.ts +9 -8
- package/dist/remote/server.js +15 -14
- package/dist/remote/session-state.d.ts +5 -4
- package/dist/remote/session-state.js +8 -5
- package/dist/remote/sw.d.ts +7 -6
- package/dist/remote/sw.js +7 -6
- package/dist/remote/tailscale.d.ts +4 -2
- package/dist/remote/tailscale.js +4 -2
- package/dist/remote/ui-highlight.js +6 -5
- package/dist/remote/ui-render.js +4 -4
- package/dist/remote/ui-script.js +24 -24
- package/dist/remote/ui-styles.d.ts +1 -1
- package/dist/remote/ui-styles.js +10 -13
- package/dist/remote/ui-tools.js +9 -6
- package/dist/shared/child-extensions.d.ts +29 -17
- package/dist/shared/child-extensions.js +29 -17
- package/dist/shared/child-output.d.ts +30 -24
- package/dist/shared/child-output.js +25 -17
- package/dist/shared/child-process.d.ts +47 -40
- package/dist/shared/child-process.js +50 -59
- package/dist/shared/command-watchdog.d.ts +22 -16
- package/dist/shared/command-watchdog.js +28 -21
- package/dist/shared/fs-text.d.ts +16 -10
- package/dist/shared/fs-text.js +16 -10
- package/dist/shared/git-runner.d.ts +25 -25
- package/dist/shared/git-runner.js +25 -25
- package/dist/shared/leaked-tool-call.d.ts +17 -11
- package/dist/shared/leaked-tool-call.js +23 -15
- package/dist/shared/model-endpoint.d.ts +29 -16
- package/dist/shared/model-endpoint.js +33 -21
- package/dist/shared/pi-invocation.d.ts +7 -4
- package/dist/shared/pi-invocation.js +12 -7
- package/dist/shared/pkg-version.d.ts +13 -5
- package/dist/shared/pkg-version.js +13 -5
- package/dist/shared/reasoning-capability.d.ts +35 -24
- package/dist/shared/reasoning-capability.js +35 -24
- package/dist/shared/stream-watchdog.d.ts +60 -44
- package/dist/shared/stream-watchdog.js +62 -45
- package/dist/task/accept-debt.d.ts +41 -43
- package/dist/task/accept-debt.js +73 -65
- package/dist/task/api-synthesis.d.ts +24 -21
- package/dist/task/api-synthesis.js +32 -26
- package/dist/task/apis-contract.d.ts +32 -64
- package/dist/task/apis-contract.js +32 -64
- package/dist/task/artifact-closure.d.ts +27 -13
- package/dist/task/artifact-closure.js +95 -67
- package/dist/task/auto-commit.d.ts +46 -35
- package/dist/task/auto-commit.js +51 -38
- package/dist/task/auto-io.d.ts +45 -25
- package/dist/task/auto-io.js +57 -29
- package/dist/task/auto-orchestrator.d.ts +26 -24
- package/dist/task/auto-orchestrator.js +178 -162
- package/dist/task/auto-prompts.d.ts +36 -24
- package/dist/task/auto-prompts.js +40 -26
- package/dist/task/autofix-ledger.d.ts +27 -25
- package/dist/task/autofix-ledger.js +29 -26
- package/dist/task/batch-test-task.d.ts +20 -12
- package/dist/task/batch-test-task.js +67 -60
- package/dist/task/boot-probe.d.ts +60 -44
- package/dist/task/boot-probe.js +91 -72
- package/dist/task/cancel-input.d.ts +30 -16
- package/dist/task/cancel-input.js +20 -11
- package/dist/task/cancel-points.d.ts +27 -20
- package/dist/task/cancel-points.js +30 -22
- package/dist/task/child-runner.d.ts +46 -51
- package/dist/task/child-runner.js +48 -49
- package/dist/task/child-status.d.ts +23 -16
- package/dist/task/child-status.js +23 -16
- package/dist/task/clamp-output.js +12 -5
- package/dist/task/command-run.d.ts +31 -28
- package/dist/task/command-run.js +44 -35
- package/dist/task/command-shrink.d.ts +25 -18
- package/dist/task/command-shrink.js +37 -31
- package/dist/task/command-watchdog.d.ts +9 -6
- package/dist/task/command-watchdog.js +21 -15
- package/dist/task/context-attribution.d.ts +34 -26
- package/dist/task/context-attribution.js +34 -26
- package/dist/task/context-silence.d.ts +39 -29
- package/dist/task/context-silence.js +35 -25
- package/dist/task/context-usage.d.ts +25 -7
- package/dist/task/context-usage.js +21 -6
- package/dist/task/contracts.d.ts +8 -4
- package/dist/task/contracts.js +25 -17
- package/dist/task/coverage-loop.d.ts +22 -18
- package/dist/task/coverage-loop.js +35 -30
- package/dist/task/critique-probes.d.ts +13 -14
- package/dist/task/critique-probes.js +50 -39
- package/dist/task/debug-log.d.ts +13 -5
- package/dist/task/debug-log.js +32 -20
- package/dist/task/decompose-fidelity.d.ts +11 -9
- package/dist/task/decompose-fidelity.js +38 -33
- package/dist/task/decompose-granularity.d.ts +41 -38
- package/dist/task/decompose-granularity.js +41 -38
- package/dist/task/deep-render-check.d.ts +22 -14
- package/dist/task/deep-render-check.js +40 -31
- package/dist/task/dropped-input.d.ts +12 -7
- package/dist/task/dropped-input.js +5 -2
- package/dist/task/enforce-attribution.d.ts +38 -47
- package/dist/task/enforce-attribution.js +46 -52
- package/dist/task/enforce-guidelines.d.ts +31 -20
- package/dist/task/enforce-guidelines.js +32 -21
- package/dist/task/enrichment.d.ts +7 -2
- package/dist/task/enrichment.js +26 -14
- package/dist/task/env-notes.d.ts +16 -7
- package/dist/task/env-notes.js +48 -31
- package/dist/task/env-template-closure.d.ts +4 -4
- package/dist/task/env-template-closure.js +42 -34
- package/dist/task/external-context.d.ts +28 -21
- package/dist/task/external-context.js +17 -12
- package/dist/task/failure-classifier.d.ts +4 -5
- package/dist/task/failure-classifier.js +6 -7
- package/dist/task/file-inventory.d.ts +15 -11
- package/dist/task/file-inventory.js +25 -22
- package/dist/task/final-gate-fix.d.ts +74 -86
- package/dist/task/final-gate-fix.js +97 -116
- package/dist/task/final-gate-progress.d.ts +29 -46
- package/dist/task/final-gate-progress.js +40 -51
- package/dist/task/final-gate.d.ts +64 -97
- package/dist/task/final-gate.js +192 -199
- package/dist/task/fix-child.d.ts +21 -27
- package/dist/task/fix-child.js +21 -27
- package/dist/task/foreign-path.d.ts +6 -5
- package/dist/task/foreign-path.js +0 -0
- package/dist/task/frozen-conflict.d.ts +9 -10
- package/dist/task/frozen-conflict.js +61 -64
- package/dist/task/frozen-path-guard.d.ts +35 -14
- package/dist/task/frozen-path-guard.js +56 -39
- package/dist/task/gate-child.d.ts +27 -28
- package/dist/task/gate-child.js +37 -35
- package/dist/task/gate-deps.d.ts +34 -27
- package/dist/task/gate-deps.js +169 -159
- package/dist/task/gate-tally.d.ts +77 -80
- package/dist/task/gate-tally.js +65 -68
- package/dist/task/git-state-guard.d.ts +15 -11
- package/dist/task/git-state-guard.js +76 -66
- package/dist/task/impl-widget.d.ts +25 -16
- package/dist/task/impl-widget.js +27 -17
- package/dist/task/implementation-thinking.d.ts +33 -31
- package/dist/task/implementation-thinking.js +5 -6
- package/dist/task/implementation-turn.d.ts +34 -31
- package/dist/task/implementation-turn.js +29 -27
- package/dist/task/inline-markdown.d.ts +20 -7
- package/dist/task/inline-markdown.js +15 -6
- package/dist/task/launch-config-gap.js +25 -39
- package/dist/task/launch-contract.d.ts +18 -21
- package/dist/task/launch-contract.js +28 -30
- package/dist/task/launch-manifest.d.ts +6 -2
- package/dist/task/launch-manifest.js +35 -34
- package/dist/task/ledger.js +16 -14
- package/dist/task/lint-fix.d.ts +6 -8
- package/dist/task/lint-fix.js +67 -69
- package/dist/task/loop-detector.d.ts +9 -8
- package/dist/task/loop-detector.js +16 -12
- package/dist/task/mid-run-input.d.ts +17 -15
- package/dist/task/mid-run-input.js +17 -15
- package/dist/task/orchestrator.d.ts +24 -28
- package/dist/task/orchestrator.js +62 -64
- package/dist/task/orientation.d.ts +18 -23
- package/dist/task/orientation.js +24 -31
- package/dist/task/owned-freeze-conflict.d.ts +21 -20
- package/dist/task/owned-freeze-conflict.js +52 -85
- package/dist/task/owned-freeze-reassign.d.ts +40 -60
- package/dist/task/owned-freeze-reassign.js +41 -61
- package/dist/task/parsers.d.ts +4 -2
- package/dist/task/parsers.js +4 -4
- package/dist/task/phases.d.ts +41 -48
- package/dist/task/phases.js +180 -248
- package/dist/task/plan-io.d.ts +6 -7
- package/dist/task/plan-io.js +6 -7
- package/dist/task/plan-orchestrator.d.ts +10 -8
- package/dist/task/plan-orchestrator.js +14 -10
- package/dist/task/plan-prompts.d.ts +6 -5
- package/dist/task/plan-prompts.js +6 -5
- package/dist/task/plan-readonly.d.ts +4 -5
- package/dist/task/plan-readonly.js +4 -5
- package/dist/task/plan-rounds.d.ts +17 -29
- package/dist/task/plan-rounds.js +21 -34
- package/dist/task/plan-session.d.ts +58 -72
- package/dist/task/plan-session.js +61 -83
- package/dist/task/probe-gaming.d.ts +28 -27
- package/dist/task/probe-gaming.js +0 -0
- package/dist/task/prohibition-probe.d.ts +14 -16
- package/dist/task/prompts.d.ts +3 -4
- package/dist/task/prompts.js +17 -26
- package/dist/task/qa-transcript.d.ts +15 -22
- package/dist/task/qa-transcript.js +15 -21
- package/dist/task/question-box.d.ts +17 -13
- package/dist/task/question-box.js +19 -15
- package/dist/task/question-dedup.d.ts +6 -7
- package/dist/task/question-dedup.js +13 -14
- package/dist/task/question-dialog.d.ts +22 -32
- package/dist/task/question-dialog.js +22 -32
- package/dist/task/question-source.d.ts +18 -44
- package/dist/task/question-source.js +22 -51
- package/dist/task/refuted-constraint.d.ts +11 -31
- package/dist/task/refuted-constraint.js +27 -51
- package/dist/task/regenerable-artifacts.d.ts +12 -31
- package/dist/task/regenerable-artifacts.js +12 -31
- package/dist/task/render-check.d.ts +11 -22
- package/dist/task/render-check.js +33 -46
- package/dist/task/repo-health-check.d.ts +10 -14
- package/dist/task/repo-health-check.js +17 -23
- package/dist/task/requirements.d.ts +38 -71
- package/dist/task/requirements.js +78 -126
- package/dist/task/research-fanout-budget.d.ts +51 -88
- package/dist/task/research-fanout-budget.js +51 -88
- package/dist/task/research-worker.d.ts +33 -36
- package/dist/task/research-worker.js +39 -61
- package/dist/task/resume-gap.d.ts +14 -15
- package/dist/task/root-cause-repair.d.ts +9 -9
- package/dist/task/root-cause-repair.js +28 -40
- package/dist/task/run-bracket.d.ts +10 -13
- package/dist/task/run-end.d.ts +12 -22
- package/dist/task/run-end.js +8 -16
- package/dist/task/run-final-gate.d.ts +19 -21
- package/dist/task/run-final-gate.js +62 -80
- package/dist/task/runner-globs.d.ts +12 -13
- package/dist/task/runner-globs.js +12 -13
- package/dist/task/runner-resolve.d.ts +9 -9
- package/dist/task/runner-resolve.js +22 -23
- package/dist/task/script-escape.d.ts +10 -12
- package/dist/task/script-escape.js +13 -14
- package/dist/task/serve-entry.d.ts +1 -1
- package/dist/task/serve-entry.js +22 -25
- package/dist/task/service-blocks.js +4 -2
- package/dist/task/shipped-source.d.ts +11 -29
- package/dist/task/shipped-source.js +11 -29
- package/dist/task/skip-escape.js +10 -14
- package/dist/task/spec-urls.d.ts +26 -65
- package/dist/task/spec-urls.js +26 -65
- package/dist/task/spec-validation.d.ts +17 -20
- package/dist/task/spec-validation.js +17 -20
- package/dist/task/stall-detector.d.ts +23 -30
- package/dist/task/stall-detector.js +23 -30
- package/dist/task/stream-watchdog.d.ts +14 -12
- package/dist/task/stream-watchdog.js +14 -12
- package/dist/task/substitution-probe.d.ts +17 -20
- package/dist/task/substitution-probe.js +17 -20
- package/dist/task/task-gates.d.ts +36 -41
- package/dist/task/task-gates.js +95 -106
- package/dist/task/task-io.d.ts +4 -4
- package/dist/task/task-io.js +4 -4
- package/dist/task/task-parsers.js +4 -3
- package/dist/task/task-provenance.d.ts +2 -2
- package/dist/task/task-provenance.js +11 -13
- package/dist/task/task-types.d.ts +4 -3
- package/dist/task/terminal-outcome.d.ts +14 -16
- package/dist/task/terminal-outcome.js +12 -14
- package/dist/task/test-assembly.d.ts +13 -20
- package/dist/task/test-assembly.js +13 -20
- package/dist/task/timings.d.ts +5 -3
- package/dist/task/timings.js +5 -3
- package/dist/task/title-label.d.ts +9 -4
- package/dist/task/title-label.js +9 -4
- package/dist/task/type-only-answer.d.ts +44 -52
- package/dist/task/type-only-answer.js +44 -52
- package/dist/task/unfailable-command.d.ts +18 -24
- package/dist/task/unfailable-command.js +21 -27
- package/dist/task/unknown-routing.d.ts +10 -4
- package/dist/task/unknown-routing.js +10 -4
- package/dist/task/user-directives.d.ts +5 -8
- package/dist/task/user-directives.js +5 -8
- package/dist/task/verify-quality.d.ts +18 -22
- package/dist/task/verify-quality.js +45 -46
- package/dist/task/verify-reconcile.d.ts +15 -10
- package/dist/task/verify-reconcile.js +45 -43
- package/dist/task/verify-resolution.d.ts +24 -20
- package/dist/task/verify-resolution.js +51 -50
- package/dist/task/verify-work.d.ts +59 -66
- package/dist/task/verify-work.js +101 -138
- package/dist/task/widget.d.ts +15 -14
- package/dist/task/widget.js +22 -17
- package/dist/task/wiring-claims.d.ts +25 -32
- package/dist/task/wiring-claims.js +30 -35
- package/dist/task/write-guard.d.ts +39 -39
- package/dist/task/write-guard.js +48 -51
- package/dist/task/yolo.d.ts +34 -30
- package/dist/task/yolo.js +42 -37
- package/dist/workers/abstention.d.ts +21 -41
- package/dist/workers/abstention.js +27 -48
- package/dist/workers/brave-search.d.ts +4 -3
- package/dist/workers/brave-search.js +5 -2
- package/dist/workers/brave-warning.d.ts +7 -4
- package/dist/workers/brave-warning.js +19 -7
- package/dist/workers/ddg-search.d.ts +6 -6
- package/dist/workers/ddg-search.js +18 -12
- package/dist/workers/docs-cache.js +5 -2
- package/dist/workers/docs-chunk.d.ts +30 -37
- package/dist/workers/docs-chunk.js +37 -41
- package/dist/workers/docs-core.d.ts +28 -44
- package/dist/workers/docs-core.js +25 -44
- package/dist/workers/docs-index.js +4 -3
- package/dist/workers/docs-lookup.d.ts +15 -22
- package/dist/workers/docs-lookup.js +12 -21
- package/dist/workers/docs-project.d.ts +15 -9
- package/dist/workers/docs-project.js +17 -10
- package/dist/workers/docs-resolve.d.ts +19 -20
- package/dist/workers/docs-resolve.js +35 -32
- package/dist/workers/docs-retrieve.d.ts +5 -6
- package/dist/workers/docs-retrieve.js +18 -15
- package/dist/workers/exa-search.d.ts +9 -6
- package/dist/workers/exa-search.js +23 -12
- package/dist/workers/fetch-core.d.ts +13 -16
- package/dist/workers/fetch-core.js +23 -23
- package/dist/workers/focused-extractor.d.ts +12 -12
- package/dist/workers/focused-extractor.js +16 -19
- package/dist/workers/html-clean.js +24 -14
- package/dist/workers/http-request.d.ts +28 -20
- package/dist/workers/http-request.js +22 -17
- package/dist/workers/npm-version.d.ts +28 -11
- package/dist/workers/npm-version.js +24 -15
- package/dist/workers/phantom-imports.d.ts +15 -12
- package/dist/workers/phantom-imports.js +30 -24
- package/dist/workers/pi-worker-core.d.ts +86 -54
- package/dist/workers/pi-worker-core.js +112 -112
- package/dist/workers/pi-worker-docs.d.ts +24 -19
- package/dist/workers/pi-worker-docs.js +67 -76
- package/dist/workers/pi-worker-fetch.d.ts +7 -3
- package/dist/workers/pi-worker-fetch.js +27 -19
- package/dist/workers/pi-worker-search.js +12 -8
- package/dist/workers/pi-worker.d.ts +9 -4
- package/dist/workers/pi-worker.js +23 -10
- package/dist/workers/reasoning-warning.d.ts +18 -17
- package/dist/workers/reasoning-warning.js +22 -20
- package/dist/workers/research-cache.js +50 -78
- package/dist/workers/search-core.js +7 -5
- package/dist/workers/search-types.d.ts +10 -9
- package/dist/workers/search-types.js +9 -8
- package/dist/workers/session-hint.d.ts +13 -14
- package/dist/workers/session-hint.js +8 -9
- package/dist/workers/shared.d.ts +21 -25
- package/dist/workers/shared.js +0 -0
- package/dist/workers/single-read-extension.d.ts +14 -7
- package/dist/workers/single-read-extension.js +14 -7
- package/dist/workers/single-read-guard.d.ts +25 -28
- package/dist/workers/single-read-guard.js +32 -32
- package/dist/workers/typeonly-log.d.ts +12 -9
- package/dist/workers/typeonly-log.js +29 -33
- package/dist/workers/worker-channels.d.ts +15 -23
- package/dist/workers/worker-channels.js +15 -23
- package/dist/workers/worker-failure.d.ts +38 -46
- package/dist/workers/worker-failure.js +31 -39
- package/dist/workers/worker-kill.d.ts +25 -26
- package/dist/workers/worker-kill.js +16 -19
- package/dist/workers/worker-profiles.d.ts +43 -53
- package/dist/workers/worker-profiles.js +30 -38
- package/package.json +10 -8
|
@@ -35,16 +35,17 @@ export declare function hasTypeFiles(root: string): boolean;
|
|
|
35
35
|
* lines, and the pointer lines a redirect stub is made of (`/// <reference .. />`
|
|
36
36
|
* and `export * from "X"`).
|
|
37
37
|
*
|
|
38
|
-
* This is the discriminator `detectTypesRedirect` needs
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* declarations.
|
|
43
|
-
*
|
|
38
|
+
* This is the discriminator `detectTypesRedirect` needs. A redirect stub has
|
|
39
|
+
* nothing in it but the pointer and counts 0. A real API surface that merely
|
|
40
|
+
* declares an AMBIENT DEPENDENCY on another types package —
|
|
41
|
+
* `/// <reference types="node" />` above its own declarations — counts those
|
|
42
|
+
* declarations and is not a stub. A `.d.ts` FILE count cannot tell the two apart:
|
|
43
|
+
* both ship exactly one file.
|
|
44
44
|
*
|
|
45
|
-
* Deliberately lexical, not a TypeScript parse:
|
|
46
|
-
*
|
|
47
|
-
* declaration found
|
|
45
|
+
* Deliberately lexical, not a TypeScript parse: `typescript` is a devDependency
|
|
46
|
+
* here, so the shipped worker has no compiler to call. Over-counting is the safe
|
|
47
|
+
* direction — a declaration found means not a stub, so the package keeps its own
|
|
48
|
+
* types.
|
|
48
49
|
*/
|
|
49
50
|
export declare function countEntryDeclarations(content: string): number;
|
|
50
51
|
/** When a package is a pure pointer to another types package — a single-file
|
|
@@ -57,18 +58,16 @@ export declare function detectTypesRedirect(pkg: ResolvedPackage): string | null
|
|
|
57
58
|
/**
|
|
58
59
|
* Follow the `@types/<name>` + triple-slash `<reference types>` redirect chain from
|
|
59
60
|
* a package that ships no usable types of its own to the one that actually holds
|
|
60
|
-
* the declarations — `bun` → `@types/bun` → `bun-types`. Bounded to three hops
|
|
61
|
-
*
|
|
61
|
+
* the declarations — `bun` → `@types/bun` → `bun-types`. Bounded to three hops:
|
|
62
|
+
* a chain of pure stubs stops after exactly three. The `visited` set cuts a cycle,
|
|
63
|
+
* and the package it started from comes back when no better source is found.
|
|
62
64
|
*
|
|
63
|
-
* This is what the four predicates above
|
|
64
|
-
*
|
|
65
|
-
* byte-identical copies — `docs-core.ts` and `phantom-imports.ts` — and NEITHER was
|
|
66
|
-
* covered: both of their tests pin only the zero-hop case, so the multi-hop
|
|
67
|
-
* behaviour cited by name in five doc comments was asserted nowhere.
|
|
65
|
+
* This is what the four predicates above exist for, and the walk is written once
|
|
66
|
+
* for its two callers.
|
|
68
67
|
*
|
|
69
|
-
* `resolveHop` is the one thing
|
|
70
|
-
*
|
|
71
|
-
* phantom-
|
|
72
|
-
*
|
|
68
|
+
* `resolveHop` is the one thing those callers genuinely disagree about: docs-core
|
|
69
|
+
* resolves the next hop through an auto-installing async lookup, while
|
|
70
|
+
* phantom-imports wraps a bare sync `resolvePackage` that must never install.
|
|
71
|
+
* Returning null stops the walk.
|
|
73
72
|
*/
|
|
74
73
|
export declare function resolveTypeSource(start: ResolvedPackage, seed: string, resolveHop: (name: string) => Promise<ResolvedPackage | null>): Promise<ResolvedPackage>;
|
|
@@ -22,10 +22,11 @@ function isValidModuleName(name) {
|
|
|
22
22
|
}
|
|
23
23
|
// Runtimes whose builtin `<runtime>:<sub>` imports are typed by the runtime's own
|
|
24
24
|
// types package, not by a literal package named "<runtime>:<sub>". `node:fs` and
|
|
25
|
-
// `bun:sqlite` are real imports
|
|
26
|
-
// bun-types
|
|
27
|
-
//
|
|
28
|
-
// lookup target is the runtime, never
|
|
25
|
+
// `bun:sqlite` are real imports whose declarations live in @types/node and
|
|
26
|
+
// bun-types. `bun:sql` is a phantom — importing it fails with "Cannot find
|
|
27
|
+
// package 'sql'" — and the only way to disprove it is to resolve the runtime and
|
|
28
|
+
// find the symbol absent. Either way the docs lookup target is the runtime, never
|
|
29
|
+
// the colon-name.
|
|
29
30
|
const RUNTIME_NAMESPACES = new Set(['bun', 'node', 'deno']);
|
|
30
31
|
/**
|
|
31
32
|
* Split a runtime builtin specifier (`bun:sql`, `node:fs/promises`) into its
|
|
@@ -120,7 +121,9 @@ export function resolvePackage(moduleName, cwd) {
|
|
|
120
121
|
throw new ResolveError('invalid_name', `Invalid module name: "${moduleName}"`);
|
|
121
122
|
}
|
|
122
123
|
const parent = parentPackageName(moduleName);
|
|
123
|
-
// First try:
|
|
124
|
+
// First try: `createRequire`. It only works when the package EXPORTS
|
|
125
|
+
// `./package.json`; a package that does not gives ERR_PACKAGE_PATH_NOT_EXPORTED
|
|
126
|
+
// and falls through. Any other resolve error is rethrown.
|
|
124
127
|
const requireFromCwd = createRequire(path.join(cwd, '__pi-worker-docs-sentinel__'));
|
|
125
128
|
let pkgJsonPath = null;
|
|
126
129
|
try {
|
|
@@ -130,9 +133,10 @@ export function resolvePackage(moduleName, cwd) {
|
|
|
130
133
|
const code = err.code;
|
|
131
134
|
if (code !== 'MODULE_NOT_FOUND' && code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED')
|
|
132
135
|
throw err;
|
|
133
|
-
// Fall through to direct filesystem fallback below
|
|
134
136
|
}
|
|
135
|
-
// Second try: walk node_modules
|
|
137
|
+
// Second try: walk node_modules upward from cwd. This is what handles a package
|
|
138
|
+
// that does not export its package.json, and it is the only path that reports
|
|
139
|
+
// `not_installed`.
|
|
136
140
|
if (!pkgJsonPath) {
|
|
137
141
|
const direct = findPackageJsonInNodeModules(parent, cwd);
|
|
138
142
|
if (!direct) {
|
|
@@ -230,16 +234,17 @@ const DECLARATION_RE = /^\s*(?:export\s+(?:default\s+)?)?(?:declare\s+)?(?:abstr
|
|
|
230
234
|
* lines, and the pointer lines a redirect stub is made of (`/// <reference .. />`
|
|
231
235
|
* and `export * from "X"`).
|
|
232
236
|
*
|
|
233
|
-
* This is the discriminator `detectTypesRedirect` needs
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* declarations.
|
|
238
|
-
*
|
|
237
|
+
* This is the discriminator `detectTypesRedirect` needs. A redirect stub has
|
|
238
|
+
* nothing in it but the pointer and counts 0. A real API surface that merely
|
|
239
|
+
* declares an AMBIENT DEPENDENCY on another types package —
|
|
240
|
+
* `/// <reference types="node" />` above its own declarations — counts those
|
|
241
|
+
* declarations and is not a stub. A `.d.ts` FILE count cannot tell the two apart:
|
|
242
|
+
* both ship exactly one file.
|
|
239
243
|
*
|
|
240
|
-
* Deliberately lexical, not a TypeScript parse:
|
|
241
|
-
*
|
|
242
|
-
* declaration found
|
|
244
|
+
* Deliberately lexical, not a TypeScript parse: `typescript` is a devDependency
|
|
245
|
+
* here, so the shipped worker has no compiler to call. Over-counting is the safe
|
|
246
|
+
* direction — a declaration found means not a stub, so the package keeps its own
|
|
247
|
+
* types.
|
|
243
248
|
*/
|
|
244
249
|
export function countEntryDeclarations(content) {
|
|
245
250
|
const stripped = content.replace(BLOCK_COMMENT_RE, '');
|
|
@@ -295,11 +300,11 @@ export function detectTypesRedirect(pkg) {
|
|
|
295
300
|
if (!target)
|
|
296
301
|
return null;
|
|
297
302
|
// A pointer line is not a redirect when the file it sits in also declares an
|
|
298
|
-
// API. `/// <reference types="node" />`
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
+
// API. `/// <reference types="node" />` above a package's own declarations
|
|
304
|
+
// means "my types NEED node's", not "my types ARE node's". Following it would
|
|
305
|
+
// answer every question about that package out of @types/node while its own
|
|
306
|
+
// surface sat one file away — and the .d.ts FILE count cannot see the
|
|
307
|
+
// difference, because a stub and a single-file API surface both count 1.
|
|
303
308
|
if (countEntryDeclarations(content) > 0)
|
|
304
309
|
return null;
|
|
305
310
|
return target;
|
|
@@ -307,19 +312,17 @@ export function detectTypesRedirect(pkg) {
|
|
|
307
312
|
/**
|
|
308
313
|
* Follow the `@types/<name>` + triple-slash `<reference types>` redirect chain from
|
|
309
314
|
* a package that ships no usable types of its own to the one that actually holds
|
|
310
|
-
* the declarations — `bun` → `@types/bun` → `bun-types`. Bounded to three hops
|
|
311
|
-
*
|
|
315
|
+
* the declarations — `bun` → `@types/bun` → `bun-types`. Bounded to three hops:
|
|
316
|
+
* a chain of pure stubs stops after exactly three. The `visited` set cuts a cycle,
|
|
317
|
+
* and the package it started from comes back when no better source is found.
|
|
312
318
|
*
|
|
313
|
-
* This is what the four predicates above
|
|
314
|
-
*
|
|
315
|
-
* byte-identical copies — `docs-core.ts` and `phantom-imports.ts` — and NEITHER was
|
|
316
|
-
* covered: both of their tests pin only the zero-hop case, so the multi-hop
|
|
317
|
-
* behaviour cited by name in five doc comments was asserted nowhere.
|
|
319
|
+
* This is what the four predicates above exist for, and the walk is written once
|
|
320
|
+
* for its two callers.
|
|
318
321
|
*
|
|
319
|
-
* `resolveHop` is the one thing
|
|
320
|
-
*
|
|
321
|
-
* phantom-
|
|
322
|
-
*
|
|
322
|
+
* `resolveHop` is the one thing those callers genuinely disagree about: docs-core
|
|
323
|
+
* resolves the next hop through an auto-installing async lookup, while
|
|
324
|
+
* phantom-imports wraps a bare sync `resolvePackage` that must never install.
|
|
325
|
+
* Returning null stops the walk.
|
|
323
326
|
*/
|
|
324
327
|
export async function resolveTypeSource(start, seed, resolveHop) {
|
|
325
328
|
const visited = new Set([start.name, seed]);
|
|
@@ -13,13 +13,12 @@ export interface RetrieveOptions {
|
|
|
13
13
|
contentBudget?: number;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* How many chunks a retrieval returns, per corpus.
|
|
16
|
+
* How many chunks a retrieval returns, per corpus. An npm package gets 8 and
|
|
17
|
+
* project source gets 50.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* a retrieval-policy change with its own A/B, not a tidy-up. Before this they were
|
|
22
|
-
* three declarations across three files, so the divergence was invisible.
|
|
19
|
+
* Nothing in this repo records WHY they differ. They are stated here, together,
|
|
20
|
+
* so the divergence is at least visible — and changing either is a
|
|
21
|
+
* retrieval-policy change, not a tidy-up.
|
|
23
22
|
*/
|
|
24
23
|
export declare const PACKAGE_RETRIEVE_LIMIT = 8;
|
|
25
24
|
export declare const PROJECT_RETRIEVE_LIMIT = 50;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* How many chunks a retrieval returns, per corpus.
|
|
2
|
+
* How many chunks a retrieval returns, per corpus. An npm package gets 8 and
|
|
3
|
+
* project source gets 50.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* a retrieval-policy change with its own A/B, not a tidy-up. Before this they were
|
|
8
|
-
* three declarations across three files, so the divergence was invisible.
|
|
5
|
+
* Nothing in this repo records WHY they differ. They are stated here, together,
|
|
6
|
+
* so the divergence is at least visible — and changing either is a
|
|
7
|
+
* retrieval-policy change, not a tidy-up.
|
|
9
8
|
*/
|
|
10
9
|
export const PACKAGE_RETRIEVE_LIMIT = 8;
|
|
11
10
|
export const PROJECT_RETRIEVE_LIMIT = 50;
|
|
12
11
|
/** Character budget for the assembled chunk text. The same for both corpora. */
|
|
13
12
|
export const RETRIEVE_CONTENT_BUDGET = 24_000;
|
|
14
|
-
// Both callers
|
|
15
|
-
//
|
|
13
|
+
// Both callers pass `limit` and `contentBudget` explicitly — docs-core with the
|
|
14
|
+
// package pair, docs-project with the project pair — so these defaults are only a
|
|
15
|
+
// backstop for a third caller that does not.
|
|
16
16
|
const DEFAULT_LIMIT = PROJECT_RETRIEVE_LIMIT;
|
|
17
17
|
const DEFAULT_BUDGET = RETRIEVE_CONTENT_BUDGET;
|
|
18
18
|
const MIN_TOKEN_LEN = 2;
|
|
@@ -25,13 +25,11 @@ const FALLBACK_README_CHARS = 4_000;
|
|
|
25
25
|
* multi-part identifiers into one string that occurs nowhere in the corpus:
|
|
26
26
|
* "src/server/routes/auth.ts" -> "srcserverroutesauthts"
|
|
27
27
|
* "Bun.password.hash" -> "Bunpasswordhash"
|
|
28
|
-
* Because buildFtsQuery ORs the tokens,
|
|
29
|
-
* single most informative term in the query — the path, or the dotted API
|
|
30
|
-
* dropped and
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* discriminative-symbol recall 89.5% -> 96.4%.
|
|
34
|
-
* See scripts/live-project-docs-retrieval-ab.ts and scripts/live-npm-tokenizer-regression.ts.
|
|
28
|
+
* Because buildFtsQuery ORs the tokens, a welded token contributes no MATCH at all.
|
|
29
|
+
* The single most informative term in the query — the path, or the dotted API
|
|
30
|
+
* symbol — is then dropped, and when it was the only term the retrieval falls all
|
|
31
|
+
* the way through to `fallbackChunks`: the alphabetically-first `.d.ts` and the
|
|
32
|
+
* first README, exactly what an empty query returns.
|
|
35
33
|
*/
|
|
36
34
|
function tokenize(query) {
|
|
37
35
|
return query.split(/[^a-zA-Z0-9_]+/).filter(t => t.length >= MIN_TOKEN_LEN);
|
|
@@ -65,6 +63,11 @@ function fallbackChunks(cache, name, version) {
|
|
|
65
63
|
}
|
|
66
64
|
return out;
|
|
67
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Trim the chunk list to the character budget, in retrieval order. The FIRST
|
|
68
|
+
* chunk is always kept, whatever its size — a top-ranked chunk larger than the
|
|
69
|
+
* whole budget would otherwise return nothing at all.
|
|
70
|
+
*/
|
|
68
71
|
function enforceBudget(chunks, budget) {
|
|
69
72
|
if (!chunks.length)
|
|
70
73
|
return chunks;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web search via Exa's public MCP endpoint
|
|
2
|
+
* Web search via Exa's public MCP endpoint. No API key: search-types.ts gives
|
|
3
|
+
* `exa` an empty env-var list, and the endpoint answers an unauthenticated POST.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* separated by `---`,
|
|
5
|
+
* One JSON-RPC `tools/call` of `web_search_exa` against https://mcp.exa.ai/mcp
|
|
6
|
+
* returns the results. The response comes back `text/event-stream` — an
|
|
7
|
+
* `event: message` line and one `data:` frame — and `parseRpcBody` also accepts a
|
|
8
|
+
* plain JSON body. Inside the RPC result is a single text blob of blocks
|
|
9
|
+
* separated by `---`, each carrying `Title:`, `URL:`, and then either a `Text:`
|
|
10
|
+
* label or a `Highlights:` line. `parseResultBlocks` turns that back into
|
|
11
|
+
* structured results.
|
|
9
12
|
*/
|
|
10
13
|
import { type FetchLike } from './http-request.js';
|
|
11
14
|
import type { SearchResult } from './search-types.js';
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web search via Exa's public MCP endpoint
|
|
2
|
+
* Web search via Exa's public MCP endpoint. No API key: search-types.ts gives
|
|
3
|
+
* `exa` an empty env-var list, and the endpoint answers an unauthenticated POST.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* separated by `---`,
|
|
5
|
+
* One JSON-RPC `tools/call` of `web_search_exa` against https://mcp.exa.ai/mcp
|
|
6
|
+
* returns the results. The response comes back `text/event-stream` — an
|
|
7
|
+
* `event: message` line and one `data:` frame — and `parseRpcBody` also accepts a
|
|
8
|
+
* plain JSON body. Inside the RPC result is a single text blob of blocks
|
|
9
|
+
* separated by `---`, each carrying `Title:`, `URL:`, and then either a `Text:`
|
|
10
|
+
* label or a `Highlights:` line. `parseResultBlocks` turns that back into
|
|
11
|
+
* structured results.
|
|
9
12
|
*/
|
|
10
13
|
import { httpRequest, HttpRequestError } from './http-request.js';
|
|
11
14
|
const EXA_MCP_ENDPOINT = 'https://mcp.exa.ai/mcp';
|
|
@@ -31,7 +34,10 @@ export async function exaSearch(query, opts = {}) {
|
|
|
31
34
|
...(opts.fetchImpl === undefined ? {} : { fetchImpl: opts.fetchImpl })
|
|
32
35
|
}, count, query);
|
|
33
36
|
}
|
|
34
|
-
/** The Exa-specific half:
|
|
37
|
+
/** The Exa-specific half: the JSON-RPC body it posts, its status policy, and its
|
|
38
|
+
* error type. Every failure leaves here as an ExaSearchError — `http` for a
|
|
39
|
+
* non-2xx, `protocol` for an RPC error / an `isError` result / no text content /
|
|
40
|
+
* an unparseable body, and `network` or `aborted` for a transport fault. */
|
|
35
41
|
async function request(bounds, count, query) {
|
|
36
42
|
try {
|
|
37
43
|
return await httpRequest(EXA_MCP_ENDPOINT, {
|
|
@@ -83,9 +89,10 @@ async function request(bounds, count, query) {
|
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
/**
|
|
86
|
-
* The endpoint answers
|
|
87
|
-
*
|
|
88
|
-
* JSON-RPC result or error
|
|
92
|
+
* The endpoint answers as a text/event-stream (`data: {json}` lines) in practice,
|
|
93
|
+
* but a plain JSON body parses too. Take the FIRST `data:` frame that carries a
|
|
94
|
+
* JSON-RPC `result` or `error` — frames without either (a bare
|
|
95
|
+
* `{"jsonrpc":"2.0"}`) are skipped, not treated as the answer.
|
|
89
96
|
*/
|
|
90
97
|
function parseRpcBody(body) {
|
|
91
98
|
for (const line of body.split('\n')) {
|
|
@@ -116,8 +123,12 @@ function parseRpcBody(body) {
|
|
|
116
123
|
/**
|
|
117
124
|
* Split the tool's text payload into `Title:`/`URL:` blocks. The per-result
|
|
118
125
|
* content lives after a `Text:` label (full text) or a `Highlights:` line
|
|
119
|
-
* (snippet mode); either becomes the description, whitespace-collapsed
|
|
120
|
-
*
|
|
126
|
+
* (snippet mode); either becomes the description, whitespace-collapsed, its
|
|
127
|
+
* trailing `---` removed, and capped at MAX_DESCRIPTION_CHARS so a result line
|
|
128
|
+
* stays a snippet, not a page dump.
|
|
129
|
+
*
|
|
130
|
+
* A block with no `URL:` is dropped entirely. A block with an empty `Title:`
|
|
131
|
+
* keeps the URL as its title, so a result is never nameless.
|
|
121
132
|
*/
|
|
122
133
|
function parseResultBlocks(text) {
|
|
123
134
|
const blocks = text.split(/(?=^Title: )/m).filter(b => b.trim().length > 0);
|
|
@@ -17,10 +17,9 @@ export interface FetchRawResult {
|
|
|
17
17
|
}
|
|
18
18
|
export declare function fetchRaw(input: FetchRawInput): Promise<FetchRawResult>;
|
|
19
19
|
/**
|
|
20
|
-
* How the page content is turned into the child's prompt.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* Production always uses {@link shippedStrategy}.
|
|
20
|
+
* How the page content is turned into the child's prompt. A seam, so a harness can run a
|
|
21
|
+
* variant selection or prompt against the shipped one in the SAME process. Nothing in this
|
|
22
|
+
* repo overrides it: {@link shippedStrategy} is the only implementation.
|
|
24
23
|
*/
|
|
25
24
|
export interface PromptStrategy {
|
|
26
25
|
selectContent(markdown: string, requestedUrl: string): SelectedContent;
|
|
@@ -47,25 +46,23 @@ export interface FetchFocusedResult {
|
|
|
47
46
|
excerpt?: string;
|
|
48
47
|
excerptVerified?: boolean;
|
|
49
48
|
/**
|
|
50
|
-
* The page did not cover the asked-about version
|
|
49
|
+
* The page did not cover the asked-about version or topic — a DISTINCT outcome from
|
|
51
50
|
* `unclear from this page`, so the caller can pick a different URL instead of treating
|
|
52
|
-
* "page has no answer" and "answer is ambiguous" as the same thing
|
|
51
|
+
* "page has no answer" and "answer is ambiguous" as the same thing.
|
|
53
52
|
*/
|
|
54
53
|
coverageMiss: boolean;
|
|
55
54
|
/**
|
|
56
|
-
* What to do INSTEAD, present only on a coverage miss.
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* as "ask again, differently". It did — 9 of the 84 corpus fetches re-read a URL that had
|
|
60
|
-
* already returned a non-answer, one release-notes page three times with near-identical
|
|
61
|
-
* questions.
|
|
55
|
+
* What to do INSTEAD, present only on a coverage miss. Without it the worker sees only
|
|
56
|
+
* the bare sentence "not covered by this page", which reads as "ask again, differently"
|
|
57
|
+
* — and re-reading the same URL with a reworded question returns the same answer.
|
|
62
58
|
*/
|
|
63
59
|
nextStep?: string;
|
|
64
60
|
/** The #fragment slug that was anchored, when the URL carried one and it was located. */
|
|
65
61
|
anchoredSection?: string;
|
|
66
62
|
/** Retained evidence for a false `excerptVerified`, so it is diagnosable without re-fetch. */
|
|
67
63
|
excerptCheck?: ExcerptVerification;
|
|
68
|
-
/** The prompt actually handed to the child
|
|
64
|
+
/** The prompt actually handed to the child, returned so a caller can see exactly what
|
|
65
|
+
* the selection and the strategy produced. */
|
|
69
66
|
assembledPrompt: string;
|
|
70
67
|
/**
|
|
71
68
|
* Set exactly when the child failed (aborted, or non-zero exit): the standard
|
|
@@ -96,10 +93,10 @@ export interface SelectedContent {
|
|
|
96
93
|
/**
|
|
97
94
|
* Slice a markdown page down to the section its heading-anchor #fragment names — the deep
|
|
98
95
|
* link the caller actually asked for — instead of head-truncating the whole page and losing
|
|
99
|
-
* a section that sits past the head window
|
|
96
|
+
* a section that sits past the head window. Falls back to {@link truncate}
|
|
100
97
|
* when the URL has no fragment, or the fragment names no heading in THIS content (e.g. the
|
|
101
|
-
* page changed since the link was captured), so a fragment
|
|
102
|
-
* page
|
|
98
|
+
* page changed since the link was captured), so a fragment that cannot be honoured never
|
|
99
|
+
* degrades a page that could otherwise be read.
|
|
103
100
|
*/
|
|
104
101
|
export declare function selectContent(markdown: string, requestedUrl: string): SelectedContent;
|
|
105
102
|
/** The shipped strategy: fragment-aware selection + the recalibrated prompt. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { fetchAndClean as defaultFetchAndClean } from './html-clean.js';
|
|
2
2
|
import { runFocusedExtraction } from './focused-extractor.js';
|
|
3
3
|
import { abstentionSentence } from './abstention.js';
|
|
4
|
+
import {} from '../shared/child-output.js';
|
|
4
5
|
import { groupThinkingArgs } from '../config/reasoning-args.js';
|
|
5
6
|
const CONTENT_BUDGET = 30_000;
|
|
6
7
|
const HEAD_CHARS = 25_000;
|
|
@@ -14,19 +15,15 @@ export const NOT_COVERED_ANSWER = 'not covered by this page';
|
|
|
14
15
|
* answer — anchored, not a substring search. A substring search misreads the opposite case:
|
|
15
16
|
* rule 5 tells the child to answer partially and say what is missing, and it says it in the
|
|
16
17
|
* prompt's own words ("… `obs_add_raw_audio_callback` and `obs_remove_raw_audio_callback`
|
|
17
|
-
* are not covered by this page"). That is a sourced answer, and
|
|
18
|
-
* a coverage miss.
|
|
19
|
-
* rewrite started delivering pages that could half-answer; never in the 84 recorded corpus
|
|
20
|
-
* fetches, where 11 of 11 sentinel answers are the bare sentinel — so tightening it changes
|
|
21
|
-
* no recorded verdict.
|
|
18
|
+
* are not covered by this page"). That is a sourced answer, and a loose match would file it
|
|
19
|
+
* as a coverage miss.
|
|
22
20
|
*/
|
|
23
21
|
const NOT_COVERED_RE = /^not covered by this page[.\s]*$/i;
|
|
24
22
|
/**
|
|
25
23
|
* `github.com/{owner}/{repo}/blob/{ref}/{path}` renders the file through a client-side
|
|
26
|
-
* viewer
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* same bytes as text/plain.
|
|
24
|
+
* viewer. The HTML carries GitHub chrome ("Sign in", "Appearance settings") and NOT the
|
|
25
|
+
* file: fetching one blob URL returns 282 KB of text/html that does not contain the file's
|
|
26
|
+
* bytes anywhere, while `raw.githubusercontent.com` returns the file itself as text/plain.
|
|
30
27
|
*
|
|
31
28
|
* Only the URL handed to the fetcher is rewritten — the caller's URL still keys the cache
|
|
32
29
|
* and still supplies the #fragment — so a worker that retries the raw URL by hand hits the
|
|
@@ -141,10 +138,10 @@ function fragmentOf(url) {
|
|
|
141
138
|
/**
|
|
142
139
|
* Slice a markdown page down to the section its heading-anchor #fragment names — the deep
|
|
143
140
|
* link the caller actually asked for — instead of head-truncating the whole page and losing
|
|
144
|
-
* a section that sits past the head window
|
|
141
|
+
* a section that sits past the head window. Falls back to {@link truncate}
|
|
145
142
|
* when the URL has no fragment, or the fragment names no heading in THIS content (e.g. the
|
|
146
|
-
* page changed since the link was captured), so a fragment
|
|
147
|
-
* page
|
|
143
|
+
* page changed since the link was captured), so a fragment that cannot be honoured never
|
|
144
|
+
* degrades a page that could otherwise be read.
|
|
148
145
|
*/
|
|
149
146
|
export function selectContent(markdown, requestedUrl) {
|
|
150
147
|
const frag = fragmentOf(requestedUrl);
|
|
@@ -159,9 +156,10 @@ function escapeRegExp(s) {
|
|
|
159
156
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
160
157
|
}
|
|
161
158
|
/** Find the heading whose anchor is `#<frag>` and return that heading's section: from the
|
|
162
|
-
* heading line up to the next heading of the same or
|
|
163
|
-
* the heading line in both the Docusaurus
|
|
164
|
-
* (`## [Title](#slug)`) shapes
|
|
159
|
+
* heading line up to the next heading of the same or HIGHER level, so a `##` section keeps
|
|
160
|
+
* its `###` subsections. Anchors are matched on the heading line in both the Docusaurus
|
|
161
|
+
* (`### Title[](#slug "…")`) and GitHub (`## [Title](#slug)`) shapes, and the trailing
|
|
162
|
+
* `(?![a-z0-9-])` is what keeps `#foo` from matching `#foobar`. */
|
|
165
163
|
function sliceSection(markdown, frag) {
|
|
166
164
|
const lines = markdown.split('\n');
|
|
167
165
|
const anchor = new RegExp('#' + escapeRegExp(frag) + '(?![a-z0-9-])', 'i');
|
|
@@ -194,14 +192,16 @@ function truncate(md) {
|
|
|
194
192
|
return md.slice(0, HEAD_CHARS) + TRUNCATION_MARKER + md.slice(md.length - TAIL_CHARS);
|
|
195
193
|
}
|
|
196
194
|
/**
|
|
197
|
-
* The shipped extraction prompt.
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
195
|
+
* The shipped extraction prompt. Its three abstention rules are deliberately separate, and a
|
|
196
|
+
* child that collapses them loses information the caller needs:
|
|
197
|
+
* 5. answer from the content whenever it supports one, even partially — "unclear" is the
|
|
198
|
+
* wrong response merely because coverage is incomplete;
|
|
199
|
+
* 6. a page about a DIFFERENT version or topic is a coverage MISS, `NOT_COVERED_ANSWER`,
|
|
200
|
+
* which the caller turns into "try a different URL";
|
|
201
|
+
* 7. `UNCLEAR_ANSWER` is reserved for content that IS present but ambiguous — never for
|
|
202
|
+
* absence, and never as licence to invent.
|
|
203
|
+
* Rules 1 and 2, the verbatim-excerpt requirement the fabrication check rests on, are
|
|
204
|
+
* independent of all three.
|
|
205
205
|
*/
|
|
206
206
|
function buildPrompt(args) {
|
|
207
207
|
const sectionNote = args.section ?
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type SpawnFn } from '../shared/child-process.js';
|
|
2
2
|
import { type ExcerptVerification } from '../shared/child-output.js';
|
|
3
3
|
/**
|
|
4
|
-
* The argv every focused extraction child runs with: the shared child base
|
|
5
|
-
* extensions
|
|
6
|
-
*
|
|
4
|
+
* The argv every focused extraction child runs with: the shared child base — any whitelisted
|
|
5
|
+
* extensions, then `--print --no-skills --no-extensions --no-prompt-templates
|
|
6
|
+
* --no-context-files --no-session` — then the caller's thinking fragment, then `--no-tools`.
|
|
7
7
|
*
|
|
8
8
|
* `--no-tools` is the contract, not a default: the child is given all the content it may use
|
|
9
9
|
* inside its prompt, so a tool call could only reach for something unsourced.
|
|
@@ -13,11 +13,11 @@ export interface FocusedRequest {
|
|
|
13
13
|
/** The fully assembled prompt, including the content block. Delivered on stdin. */
|
|
14
14
|
prompt: string;
|
|
15
15
|
/**
|
|
16
|
-
* The text the cited excerpt is checked against — a NAMED knob, because the
|
|
17
|
-
* sites deliberately disagree and the disagreement
|
|
16
|
+
* The text the cited excerpt is checked against — a NAMED knob, because the two call
|
|
17
|
+
* sites deliberately disagree, and unnamed the disagreement is invisible.
|
|
18
18
|
*
|
|
19
|
-
* `
|
|
20
|
-
*
|
|
19
|
+
* `docsLookup` passes exactly the concatenated chunks that went into the prompt.
|
|
20
|
+
* `fetchFocused` passes the FULL cleaned page while prompting with only the
|
|
21
21
|
* anchored `#fragment` section: the slice is a substring of the page, so a genuine excerpt
|
|
22
22
|
* still verifies, and an excerpt pulled from the model's memory still fails — fragment
|
|
23
23
|
* anchoring therefore cannot change the hallucination detector's discrimination.
|
|
@@ -37,11 +37,10 @@ export interface FocusedRequest {
|
|
|
37
37
|
* An already-resolved `['--thinking', level]` fragment, or `[]`/omitted to
|
|
38
38
|
* inherit the session default.
|
|
39
39
|
*
|
|
40
|
-
* Supplied by the CALLER even though
|
|
40
|
+
* Supplied by the CALLER even though both call sites resolve the same
|
|
41
41
|
* `extraction` group. Resolving it inside this module would make
|
|
42
42
|
* `focusedChildArgs` read ambient config, and a function that reads config
|
|
43
|
-
* internally cannot be tested without the developer's own machine state
|
|
44
|
-
* which is exactly how a `getConfig()` assertion got into a unit test.
|
|
43
|
+
* internally cannot be tested without the developer's own machine state.
|
|
45
44
|
*/
|
|
46
45
|
thinking?: readonly string[];
|
|
47
46
|
}
|
|
@@ -50,7 +49,8 @@ interface FocusedChildEvidence {
|
|
|
50
49
|
exitCode: number;
|
|
51
50
|
aborted: boolean;
|
|
52
51
|
stderr: string;
|
|
53
|
-
/** The child's raw stdout, retained
|
|
52
|
+
/** The child's raw stdout, retained so a failure is diagnosable from the result alone —
|
|
53
|
+
* it is the only place a crashed child's output survives. */
|
|
54
54
|
stdout: string;
|
|
55
55
|
}
|
|
56
56
|
/** The child aborted or exited non-zero. There is deliberately no `answer` here. */
|
|
@@ -78,7 +78,7 @@ export type FocusedResult = FocusedFailure | FocusedAnswer;
|
|
|
78
78
|
* `<answer>`/`<excerpt>` and verify the excerpt against `verifyAgainst`.
|
|
79
79
|
*
|
|
80
80
|
* Never retries — a re-ask of a deterministic extraction over unchanged content is a second
|
|
81
|
-
* bill for the same answer
|
|
81
|
+
* bill for the same answer. Exactly one child is spawned per call.
|
|
82
82
|
*/
|
|
83
83
|
export declare function runFocusedExtraction(req: FocusedRequest): Promise<FocusedResult>;
|
|
84
84
|
export {};
|