@mjasnikovs/pi-task 0.40.25 → 0.40.26
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/workers/docs-chunk.js +5 -0
- package/dist/workers/pi-worker-docs.d.ts +7 -1
- package/dist/workers/pi-worker-docs.js +11 -7
- package/dist/workers/pi-worker-fetch.d.ts +1 -1
- package/dist/workers/pi-worker-fetch.js +10 -6
- package/dist/workers/shared.d.ts +5 -1
- package/dist/workers/shared.js +0 -0
- package/package.json +1 -1
|
@@ -135,6 +135,11 @@ export function headedSlices(header, body, maxBytes) {
|
|
|
135
135
|
if (Buffer.byteLength(prefixed, 'utf8') <= maxBytes)
|
|
136
136
|
return [prefixed];
|
|
137
137
|
const room = maxBytes - Buffer.byteLength(`${header}\n`, 'utf8');
|
|
138
|
+
// A header that fills the cap on its own leaves no room, and `sliceBytes` with a
|
|
139
|
+
// non-positive cap never shrinks its buffer. Slice the prefixed string instead:
|
|
140
|
+
// the first piece still names the source, which is all the header buys.
|
|
141
|
+
if (room <= 0)
|
|
142
|
+
return sliceBytes(prefixed, maxBytes);
|
|
138
143
|
return sliceBytes(body, room).map(slice => `${header}\n${slice}`);
|
|
139
144
|
}
|
|
140
145
|
/**
|
|
@@ -41,6 +41,12 @@ interface DocsDetails {
|
|
|
41
41
|
/** The project-lookup budget for this attempt is spent, so the call was refused
|
|
42
42
|
* before any work. Only set when PI_TASK_PROJECT_DOCS_BUDGET is configured. */
|
|
43
43
|
budgetSpent?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* The child declined to answer. Recorded HERE, at the one place the bare
|
|
46
|
+
* `<answer>` is in hand: the tool text a cache predicate is handed leads with a
|
|
47
|
+
* provenance header, and the anchored matcher scores that as a real answer.
|
|
48
|
+
*/
|
|
49
|
+
abstained?: boolean;
|
|
44
50
|
}
|
|
45
51
|
/**
|
|
46
52
|
* Pull `@see {@link https://…}` pointers out of retrieved .d.ts/README text.
|
|
@@ -89,7 +95,7 @@ export declare function registerPiWorkerDocs(pi: ExtensionAPI, internals?: PiWor
|
|
|
89
95
|
export declare function excerptFabricated(check: {
|
|
90
96
|
absent: readonly string[];
|
|
91
97
|
} | undefined): boolean;
|
|
92
|
-
export declare function docsCacheable(d: Pick<DocsDetails, 'typeOnly' | 'excerptVerified' | 'excerptFabricated'
|
|
98
|
+
export declare function docsCacheable(d: Pick<DocsDetails, 'typeOnly' | 'excerptVerified' | 'excerptFabricated' | 'abstained'>): boolean;
|
|
93
99
|
/** The docs cache key: a package's answer is per (module, question), with the question
|
|
94
100
|
* lowercased and its whitespace collapsed so phrasing variants share one entry. Returns
|
|
95
101
|
* null for the project-source `.` lookup, which is never cached — the working tree
|
|
@@ -219,7 +219,8 @@ export function registerPiWorkerDocs(pi, internals = {}) {
|
|
|
219
219
|
return workerAnswer(text, {
|
|
220
220
|
...baseDetails,
|
|
221
221
|
excerptVerified: verified,
|
|
222
|
-
excerptFabricated: excerptFabricated(extraction.excerptCheck)
|
|
222
|
+
excerptFabricated: excerptFabricated(extraction.excerptCheck),
|
|
223
|
+
...(isAbstention(extraction.answer) ? { abstained: true } : {})
|
|
223
224
|
});
|
|
224
225
|
}
|
|
225
226
|
// ── npm package lookup (existing path) ──────────────────────────
|
|
@@ -355,7 +356,8 @@ export function registerPiWorkerDocs(pi, internals = {}) {
|
|
|
355
356
|
...baseDetails,
|
|
356
357
|
excerptVerified: verified,
|
|
357
358
|
excerptFabricated: excerptFabricated(extraction.excerptCheck),
|
|
358
|
-
...(typeOnly.typeOnly ? { typeOnly: true } : {})
|
|
359
|
+
...(typeOnly.typeOnly ? { typeOnly: true } : {}),
|
|
360
|
+
...(isAbstention(extraction.answer) ? { abstained: true } : {})
|
|
359
361
|
});
|
|
360
362
|
},
|
|
361
363
|
renderCall(args, theme) {
|
|
@@ -384,9 +386,6 @@ export function registerPiWorkerDocs(pi, internals = {}) {
|
|
|
384
386
|
// child that ran fine and answered "unclear from this package" exits 0 — so a rule
|
|
385
387
|
// keyed on exit code would memoise that non-answer and re-serve it as a hit to
|
|
386
388
|
// every later sibling, with nothing left to re-trigger an escalation.
|
|
387
|
-
//
|
|
388
|
-
// `text` is supplied by makeWorkerTool (shared.ts) alongside details, so the
|
|
389
|
-
// content check needs no new plumbing.
|
|
390
389
|
cacheable: docsCacheable
|
|
391
390
|
});
|
|
392
391
|
}
|
|
@@ -409,7 +408,7 @@ export function registerPiWorkerDocs(pi, internals = {}) {
|
|
|
409
408
|
export function excerptFabricated(check) {
|
|
410
409
|
return check !== undefined && check.absent.length > 0;
|
|
411
410
|
}
|
|
412
|
-
export function docsCacheable(d
|
|
411
|
+
export function docsCacheable(d) {
|
|
413
412
|
// Answer QUALITY only. Whether there IS an answer is `WorkerOutcome.kind`, and
|
|
414
413
|
// `makeWorkerTool` has already refused an `unavailable` before reaching here —
|
|
415
414
|
// opening this with `childExitCode === 0` memoises an aborted lookup for the
|
|
@@ -420,7 +419,12 @@ export function docsCacheable(d, text) {
|
|
|
420
419
|
// classifier defect 18 added, 41 of 41 unverified excerpts across seven runs are
|
|
421
420
|
// STITCHED — every span verbatim, not one absent word. The gate was refusing
|
|
422
421
|
// non-contiguous quoting, and every sibling paid a fresh child for it.
|
|
423
|
-
|
|
422
|
+
//
|
|
423
|
+
// The abstention is read off DETAILS, not off the tool text. `makeWorkerTool`
|
|
424
|
+
// hands this the FINAL text, which leads with `Per <pkg>@<version>:` — and
|
|
425
|
+
// `isAbstention` is anchored, so testing that text scored every abstention as a
|
|
426
|
+
// real answer and memoised the dead end for the whole run.
|
|
427
|
+
return d.typeOnly !== true && d.excerptFabricated !== true && d.abstained !== true;
|
|
424
428
|
}
|
|
425
429
|
/** The docs cache key: a package's answer is per (module, question), with the question
|
|
426
430
|
* lowercased and its whitespace collapsed so phrasing variants share one entry. Returns
|
|
@@ -32,7 +32,7 @@ export declare function registerPiWorkerFetch(pi: ExtensionAPI, internals?: PiWo
|
|
|
32
32
|
* ABOUT that page, and re-fetching cannot change it — only the abstention sentinel is
|
|
33
33
|
* refused.
|
|
34
34
|
*/
|
|
35
|
-
export declare function fetchCacheable(
|
|
35
|
+
export declare function fetchCacheable(d: Pick<FetchDetails, 'answer'>): boolean;
|
|
36
36
|
/** The fetch cache key. URL verbatim (path case can matter), question normalised —
|
|
37
37
|
* same page, different question is a different answer. */
|
|
38
38
|
export declare function fetchCacheKey(params: {
|
|
@@ -112,12 +112,16 @@ export function registerPiWorkerFetch(pi, internals = {}) {
|
|
|
112
112
|
* ABOUT that page, and re-fetching cannot change it — only the abstention sentinel is
|
|
113
113
|
* refused.
|
|
114
114
|
*/
|
|
115
|
-
export function fetchCacheable(
|
|
116
|
-
// Answer QUALITY only — see docsCacheable.
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
|
|
115
|
+
export function fetchCacheable(d) {
|
|
116
|
+
// Answer QUALITY only — see docsCacheable. An aborted fetch is kept out of the
|
|
117
|
+
// cache by its `unavailable` outcome upstream, never by this rule; leading with
|
|
118
|
+
// `childExitCode === 0` would not work, because an aborted child settles at 0.
|
|
119
|
+
//
|
|
120
|
+
// It reads the child's bare answer, not the rendered tool text: `isAbstention` is
|
|
121
|
+
// anchored, and the text leads with an excerpt NOTE/WARNING whenever the excerpt
|
|
122
|
+
// did not verify — which, since rule 4 asks for the closest related text, is the
|
|
123
|
+
// ordinary shape of an abstention.
|
|
124
|
+
return d.answer !== undefined && !isAbstention(d.answer);
|
|
121
125
|
}
|
|
122
126
|
/** The fetch cache key. URL verbatim (path case can matter), question normalised —
|
|
123
127
|
* same page, different question is a different answer. */
|
package/dist/workers/shared.d.ts
CHANGED
|
@@ -121,8 +121,12 @@ export interface WorkerToolSpec<TParams extends TSchema, TDetails> {
|
|
|
121
121
|
* (type-only, an abstention, an unverified excerpt), never about process
|
|
122
122
|
* health. An `unavailable` outcome never reaches this: `makeWorkerTool` has
|
|
123
123
|
* already refused it. Defaults to always-cacheable when omitted.
|
|
124
|
+
*
|
|
125
|
+
* It sees `details` only. Handed the rendered tool text as well, a rule reaches
|
|
126
|
+
* for it and reads a string that leads with provenance and excerpt notes — and an
|
|
127
|
+
* anchored abstention matcher then scores every abstention as an answer.
|
|
124
128
|
*/
|
|
125
|
-
cacheable?(details: TDetails
|
|
129
|
+
cacheable?(details: TDetails): boolean;
|
|
126
130
|
}
|
|
127
131
|
/** Register a worker tool from its spec, supplying the shared registration ritual. */
|
|
128
132
|
export declare function makeWorkerTool<TParams extends TSchema, TDetails>(pi: ExtensionAPI, spec: WorkerToolSpec<TParams, TDetails>): void;
|
package/dist/workers/shared.js
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.26",
|
|
4
4
|
"description": "Deterministic task planning and spec-orchestration for local models — crash-safe /task pipelines with verify/enforce gates, a real-time remote web view, and web/docs/fetch/worker subagent tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|