@nexus-cortex/core 4.69.1 → 4.71.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/dist/adapters/ChatCompletionsAPIAdapter.d.ts +17 -2
- package/dist/adapters/ChatCompletionsAPIAdapter.d.ts.map +1 -1
- package/dist/adapters/ChatCompletionsAPIAdapter.js +26 -3
- package/dist/adapters/ChatCompletionsAPIAdapter.js.map +1 -1
- package/dist/adapters/MessagesAPIAdapter.d.ts.map +1 -1
- package/dist/adapters/MessagesAPIAdapter.js +15 -0
- package/dist/adapters/MessagesAPIAdapter.js.map +1 -1
- package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.d.ts +28 -0
- package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.d.ts.map +1 -0
- package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.js +47 -0
- package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.js.map +1 -0
- package/dist/models/cards/deepseek/index.d.ts +5 -2
- package/dist/models/cards/deepseek/index.d.ts.map +1 -1
- package/dist/models/cards/deepseek/index.js +5 -2
- package/dist/models/cards/deepseek/index.js.map +1 -1
- package/dist/models/configurators/DeepSeekConfigurator.d.ts +5 -0
- package/dist/models/configurators/DeepSeekConfigurator.d.ts.map +1 -1
- package/dist/models/configurators/DeepSeekConfigurator.js +2 -0
- package/dist/models/configurators/DeepSeekConfigurator.js.map +1 -1
- package/dist/models/configurators/XAIConfigurator.d.ts +3 -0
- package/dist/models/configurators/XAIConfigurator.d.ts.map +1 -1
- package/dist/models/configurators/XAIConfigurator.js +1 -0
- package/dist/models/configurators/XAIConfigurator.js.map +1 -1
- package/dist/models/registry/ModularModelRegistry.d.ts.map +1 -1
- package/dist/models/registry/ModularModelRegistry.js +1 -0
- package/dist/models/registry/ModularModelRegistry.js.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.d.ts +23 -0
- package/dist/orchestrator/CortexOrchestrator.d.ts.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.js +628 -22
- package/dist/orchestrator/CortexOrchestrator.js.map +1 -1
- package/dist/orchestrator/imageTtl.d.ts +37 -0
- package/dist/orchestrator/imageTtl.d.ts.map +1 -0
- package/dist/orchestrator/imageTtl.js +72 -0
- package/dist/orchestrator/imageTtl.js.map +1 -0
- package/dist/orchestrator/inactionGuard.d.ts +42 -0
- package/dist/orchestrator/inactionGuard.d.ts.map +1 -0
- package/dist/orchestrator/inactionGuard.js +47 -0
- package/dist/orchestrator/inactionGuard.js.map +1 -0
- package/dist/orchestrator/requirementsVerification.d.ts +43 -0
- package/dist/orchestrator/requirementsVerification.d.ts.map +1 -0
- package/dist/orchestrator/requirementsVerification.js +87 -0
- package/dist/orchestrator/requirementsVerification.js.map +1 -0
- package/dist/tools/ToolProfile.d.ts +9 -0
- package/dist/tools/ToolProfile.d.ts.map +1 -1
- package/dist/tools/ToolProfile.js +26 -3
- package/dist/tools/ToolProfile.js.map +1 -1
- package/dist/tools/registries/BaseToolRegistry.d.ts.map +1 -1
- package/dist/tools/registries/BaseToolRegistry.js +42 -1
- package/dist/tools/registries/BaseToolRegistry.js.map +1 -1
- package/dist/training/DecisionPriorInjector.d.ts +7 -0
- package/dist/training/DecisionPriorInjector.d.ts.map +1 -1
- package/dist/training/DecisionPriorInjector.js +22 -0
- package/dist/training/DecisionPriorInjector.js.map +1 -1
- package/dist/training/DecisionStore.d.ts +39 -0
- package/dist/training/DecisionStore.d.ts.map +1 -1
- package/dist/training/DecisionStore.js +94 -0
- package/dist/training/DecisionStore.js.map +1 -1
- package/dist/training/errorFamily.d.ts +15 -0
- package/dist/training/errorFamily.d.ts.map +1 -0
- package/dist/training/errorFamily.js +40 -0
- package/dist/training/errorFamily.js.map +1 -0
- package/dist/training/loopLadder.d.ts +35 -0
- package/dist/training/loopLadder.d.ts.map +1 -0
- package/dist/training/loopLadder.js +58 -0
- package/dist/training/loopLadder.js.map +1 -0
- package/dist/training/toolOutcome.d.ts +20 -0
- package/dist/training/toolOutcome.d.ts.map +1 -0
- package/dist/training/toolOutcome.js +100 -0
- package/dist/training/toolOutcome.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* imageTtl — request-build-time image eviction (backlog item 7 addendum,
|
|
3
|
+
* MEASURED 2026-08-25): on deepseek-v4-flash-vision-exp an image ANYWHERE in
|
|
4
|
+
* the request disables cache reads for the ENTIRE request (probe: identical
|
|
5
|
+
* repeat cached=0 while a text-only request hit the same 896-token prefix).
|
|
6
|
+
* The image's own ≤384 tokens are irrelevant — one stale image forfeits the
|
|
7
|
+
* ~31× cache-hit discount on every subsequent turn.
|
|
8
|
+
*
|
|
9
|
+
* Fix: after the image has been visible for CORTEX_IMAGE_TTL_TURNS assistant
|
|
10
|
+
* responses (default 3 — enough to look, act, and confirm), the outgoing
|
|
11
|
+
* REQUEST COPY replaces the image block with a deterministic text stub. The
|
|
12
|
+
* session history is never rewritten (append-only invariant; the model can
|
|
13
|
+
* always ReadImage again). The one-time prefix bust at the TTL boundary is
|
|
14
|
+
* the good kind: it restores caching for the rest of the session, and the
|
|
15
|
+
* stub is byte-stable so the prefix re-stabilizes immediately.
|
|
16
|
+
*
|
|
17
|
+
* Pure — applied in convertToCanonicalMessages' request pipeline. MUST NOT
|
|
18
|
+
* mutate the input blocks/arrays (cached wrappers share the content array;
|
|
19
|
+
* same contract as the repair pass: swap arrays, never edit blocks).
|
|
20
|
+
*/
|
|
21
|
+
import type { CanonicalMessage } from '../adapters/FormatAdapter.interface.js';
|
|
22
|
+
/** Resolve the TTL from env. Returns null when eviction is DISABLED
|
|
23
|
+
* ('off'/'never'/'0'); otherwise a positive integer (default 3). */
|
|
24
|
+
export declare function resolveImageTtlTurns(env?: NodeJS.ProcessEnv): number | null;
|
|
25
|
+
/** Deterministic stub — NO timestamps or counters, so the request prefix is
|
|
26
|
+
* byte-stable on every build after the eviction boundary. */
|
|
27
|
+
export declare function imageEvictionStub(): {
|
|
28
|
+
type: 'text';
|
|
29
|
+
text: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Replace image blocks older than `ttl` assistant responses with the stub,
|
|
33
|
+
* on a request copy. An image's age = number of assistant-role messages
|
|
34
|
+
* appearing AFTER its message in the array.
|
|
35
|
+
*/
|
|
36
|
+
export declare function applyImageTtlForRequest(messages: CanonicalMessage[], ttl?: number | null): CanonicalMessage[];
|
|
37
|
+
//# sourceMappingURL=imageTtl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageTtl.d.ts","sourceRoot":"","sources":["../../src/orchestrator/imageTtl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAE/E;qEACqE;AACrE,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAKxF;AAED;8DAC8D;AAC9D,wBAAgB,iBAAiB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAKlE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,GAAG,GAAE,MAAM,GAAG,IAA6B,GAC1C,gBAAgB,EAAE,CAsBpB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* imageTtl — request-build-time image eviction (backlog item 7 addendum,
|
|
3
|
+
* MEASURED 2026-08-25): on deepseek-v4-flash-vision-exp an image ANYWHERE in
|
|
4
|
+
* the request disables cache reads for the ENTIRE request (probe: identical
|
|
5
|
+
* repeat cached=0 while a text-only request hit the same 896-token prefix).
|
|
6
|
+
* The image's own ≤384 tokens are irrelevant — one stale image forfeits the
|
|
7
|
+
* ~31× cache-hit discount on every subsequent turn.
|
|
8
|
+
*
|
|
9
|
+
* Fix: after the image has been visible for CORTEX_IMAGE_TTL_TURNS assistant
|
|
10
|
+
* responses (default 3 — enough to look, act, and confirm), the outgoing
|
|
11
|
+
* REQUEST COPY replaces the image block with a deterministic text stub. The
|
|
12
|
+
* session history is never rewritten (append-only invariant; the model can
|
|
13
|
+
* always ReadImage again). The one-time prefix bust at the TTL boundary is
|
|
14
|
+
* the good kind: it restores caching for the rest of the session, and the
|
|
15
|
+
* stub is byte-stable so the prefix re-stabilizes immediately.
|
|
16
|
+
*
|
|
17
|
+
* Pure — applied in convertToCanonicalMessages' request pipeline. MUST NOT
|
|
18
|
+
* mutate the input blocks/arrays (cached wrappers share the content array;
|
|
19
|
+
* same contract as the repair pass: swap arrays, never edit blocks).
|
|
20
|
+
*/
|
|
21
|
+
/** Resolve the TTL from env. Returns null when eviction is DISABLED
|
|
22
|
+
* ('off'/'never'/'0'); otherwise a positive integer (default 3). */
|
|
23
|
+
export function resolveImageTtlTurns(env = process.env) {
|
|
24
|
+
const raw = (env.CORTEX_IMAGE_TTL_TURNS ?? '').trim().toLowerCase();
|
|
25
|
+
if (raw === 'off' || raw === 'never' || raw === '0')
|
|
26
|
+
return null;
|
|
27
|
+
if (/^\d+$/.test(raw) && Number(raw) > 0)
|
|
28
|
+
return Number(raw);
|
|
29
|
+
return 3;
|
|
30
|
+
}
|
|
31
|
+
/** Deterministic stub — NO timestamps or counters, so the request prefix is
|
|
32
|
+
* byte-stable on every build after the eviction boundary. */
|
|
33
|
+
export function imageEvictionStub() {
|
|
34
|
+
return {
|
|
35
|
+
type: 'text',
|
|
36
|
+
text: '[image evicted from context to restore prompt caching — run ReadImage on the file again if you need to see it]',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Replace image blocks older than `ttl` assistant responses with the stub,
|
|
41
|
+
* on a request copy. An image's age = number of assistant-role messages
|
|
42
|
+
* appearing AFTER its message in the array.
|
|
43
|
+
*/
|
|
44
|
+
export function applyImageTtlForRequest(messages, ttl = resolveImageTtlTurns()) {
|
|
45
|
+
if (ttl === null)
|
|
46
|
+
return messages;
|
|
47
|
+
// Suffix counts of assistant messages, computed once.
|
|
48
|
+
const assistantsAfter = new Array(messages.length);
|
|
49
|
+
let count = 0;
|
|
50
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
51
|
+
assistantsAfter[i] = count;
|
|
52
|
+
if (messages[i].role === 'assistant')
|
|
53
|
+
count++;
|
|
54
|
+
}
|
|
55
|
+
let changed = false;
|
|
56
|
+
const out = messages.map((msg, i) => {
|
|
57
|
+
if (msg.role !== 'user')
|
|
58
|
+
return msg;
|
|
59
|
+
if (assistantsAfter[i] < ttl)
|
|
60
|
+
return msg;
|
|
61
|
+
if (!msg.content.some((b) => b.type === 'image'))
|
|
62
|
+
return msg;
|
|
63
|
+
changed = true;
|
|
64
|
+
// Swap the content ARRAY; never mutate shared blocks (cache contract).
|
|
65
|
+
return {
|
|
66
|
+
...msg,
|
|
67
|
+
content: msg.content.map((b) => (b.type === 'image' ? imageEvictionStub() : b)),
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
return changed ? out : messages;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=imageTtl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageTtl.js","sourceRoot":"","sources":["../../src/orchestrator/imageTtl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH;qEACqE;AACrE,MAAM,UAAU,oBAAoB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACvE,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpE,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IACjE,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC;AACX,CAAC;AAED;8DAC8D;AAC9D,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,gHAAgH;KACvH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAA4B,EAC5B,MAAqB,oBAAoB,EAAE;IAE3C,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAC;IAClC,sDAAsD;IACtD,MAAM,eAAe,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QAC3B,IAAI,QAAQ,CAAC,CAAC,CAAE,CAAC,IAAI,KAAK,WAAW;YAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAClC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,GAAG,CAAC;QACpC,IAAI,eAAe,CAAC,CAAC,CAAE,GAAG,GAAG;YAAE,OAAO,GAAG,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;YAAE,OAAO,GAAG,CAAC;QAC7D,OAAO,GAAG,IAAI,CAAC;QACf,uEAAuE;QACvE,OAAO;YACL,GAAG,GAAG;YACN,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChF,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inactionGuard — the loop ladder's INVERSE (docs/HARNESS_IMPROVEMENT_BACKLOG.md
|
|
3
|
+
* item 2). TB2 2×2 evidence: persist-frame arms produced never-acted /
|
|
4
|
+
* over-deliberated failures (5 pro-persist, 2 each flash arm, 0 pro-lifted) —
|
|
5
|
+
* the model reasons to the output wall with ZERO tool calls, so every
|
|
6
|
+
* existing guard (which all count tool calls) is blind to it.
|
|
7
|
+
*
|
|
8
|
+
* Mechanism: extends the R18b/R32 empty-response-retry precedent to
|
|
9
|
+
* ACTLESS-VERBOSE responses — one injected "act first" steering retry,
|
|
10
|
+
* bounded, fallback-accept. Default OFF (`CORTEX_INACTION_NUDGE=true` arms
|
|
11
|
+
* it; bench/server profiles arm, interactive CLI stays off until specificity
|
|
12
|
+
* is proven broadly).
|
|
13
|
+
*/
|
|
14
|
+
export interface InactionCheckInput {
|
|
15
|
+
/** Total visible text+thinking characters of the final assistant response. */
|
|
16
|
+
responseChars: number;
|
|
17
|
+
/** Tool_use blocks in THIS assistant response (0 at the natural exit). */
|
|
18
|
+
toolUseBlocksThisResponse: number;
|
|
19
|
+
/** Tool calls executed across the ENTIRE turn so far. */
|
|
20
|
+
executedToolCallsThisTurn: number;
|
|
21
|
+
/** Tools offered on the request (0 = pure-chat, guard never fires). */
|
|
22
|
+
toolsOffered: number;
|
|
23
|
+
/** Orchestrator turn counter (0 = first turn of the session). v1 gate:
|
|
24
|
+
* only the first turn — later turns of a conversation are much more
|
|
25
|
+
* likely to be legitimately analytic follow-ups. */
|
|
26
|
+
turnNumber: number;
|
|
27
|
+
/** Single-nudge bound (mirrors emptyResponseRetryUsed). */
|
|
28
|
+
alreadyNudged: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** Resolve arming + threshold from env. Default OFF; threshold default 4000
|
|
31
|
+
* chars (the TB2 never-acted signature was multi-thousand-char reasoning
|
|
32
|
+
* dumps — short direct answers must never trigger). */
|
|
33
|
+
export declare function resolveInactionConfig(env?: NodeJS.ProcessEnv): {
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
minChars: number;
|
|
36
|
+
};
|
|
37
|
+
/** Should the inaction nudge fire? Pure — all state passed in. */
|
|
38
|
+
export declare function shouldNudgeInaction(input: InactionCheckInput, env?: NodeJS.ProcessEnv): boolean;
|
|
39
|
+
/** The injected steering text (system-reminder-wrapped by the caller's
|
|
40
|
+
* standard synthetic-user-message shape). */
|
|
41
|
+
export declare function formatInactionNudge(): string;
|
|
42
|
+
//# sourceMappingURL=inactionGuard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inactionGuard.d.ts","sourceRoot":"","sources":["../../src/orchestrator/inactionGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,yBAAyB,EAAE,MAAM,CAAC;IAClC,yDAAyD;IACzD,yBAAyB,EAAE,MAAM,CAAC;IAClC,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB;;yDAEqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,aAAa,EAAE,OAAO,CAAC;CACxB;AAED;;wDAEwD;AACxD,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAKA;AAED,kEAAkE;AAClE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,kBAAkB,EACzB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAST;AAED;8CAC8C;AAC9C,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inactionGuard — the loop ladder's INVERSE (docs/HARNESS_IMPROVEMENT_BACKLOG.md
|
|
3
|
+
* item 2). TB2 2×2 evidence: persist-frame arms produced never-acted /
|
|
4
|
+
* over-deliberated failures (5 pro-persist, 2 each flash arm, 0 pro-lifted) —
|
|
5
|
+
* the model reasons to the output wall with ZERO tool calls, so every
|
|
6
|
+
* existing guard (which all count tool calls) is blind to it.
|
|
7
|
+
*
|
|
8
|
+
* Mechanism: extends the R18b/R32 empty-response-retry precedent to
|
|
9
|
+
* ACTLESS-VERBOSE responses — one injected "act first" steering retry,
|
|
10
|
+
* bounded, fallback-accept. Default OFF (`CORTEX_INACTION_NUDGE=true` arms
|
|
11
|
+
* it; bench/server profiles arm, interactive CLI stays off until specificity
|
|
12
|
+
* is proven broadly).
|
|
13
|
+
*/
|
|
14
|
+
/** Resolve arming + threshold from env. Default OFF; threshold default 4000
|
|
15
|
+
* chars (the TB2 never-acted signature was multi-thousand-char reasoning
|
|
16
|
+
* dumps — short direct answers must never trigger). */
|
|
17
|
+
export function resolveInactionConfig(env = process.env) {
|
|
18
|
+
const enabled = (env.CORTEX_INACTION_NUDGE ?? '').trim().toLowerCase() === 'true';
|
|
19
|
+
const raw = env.CORTEX_INACTION_MIN_CHARS?.trim();
|
|
20
|
+
const minChars = raw && /^\d+$/.test(raw) && Number(raw) > 0 ? Number(raw) : 4000;
|
|
21
|
+
return { enabled, minChars };
|
|
22
|
+
}
|
|
23
|
+
/** Should the inaction nudge fire? Pure — all state passed in. */
|
|
24
|
+
export function shouldNudgeInaction(input, env = process.env) {
|
|
25
|
+
const cfg = resolveInactionConfig(env);
|
|
26
|
+
if (!cfg.enabled)
|
|
27
|
+
return false;
|
|
28
|
+
if (input.alreadyNudged)
|
|
29
|
+
return false;
|
|
30
|
+
if (input.toolsOffered === 0)
|
|
31
|
+
return false; // pure-chat request
|
|
32
|
+
if (input.turnNumber !== 0)
|
|
33
|
+
return false; // conservative v1: first turn only
|
|
34
|
+
if (input.toolUseBlocksThisResponse > 0)
|
|
35
|
+
return false;
|
|
36
|
+
if (input.executedToolCallsThisTurn > 0)
|
|
37
|
+
return false; // it acted earlier this turn
|
|
38
|
+
return input.responseChars >= cfg.minChars;
|
|
39
|
+
}
|
|
40
|
+
/** The injected steering text (system-reminder-wrapped by the caller's
|
|
41
|
+
* standard synthetic-user-message shape). */
|
|
42
|
+
export function formatInactionNudge() {
|
|
43
|
+
return ('You produced a long analysis but ran no commands. Act first: run at least ' +
|
|
44
|
+
'one tool call to ground or execute your plan (inspect the actual files/state, ' +
|
|
45
|
+
'or make the first concrete change), then answer. Do not restate the plan.');
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=inactionGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inactionGuard.js","sourceRoot":"","sources":["../../src/orchestrator/inactionGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAmBH;;wDAEwD;AACxD,MAAM,UAAU,qBAAqB,CAAC,MAAyB,OAAO,CAAC,GAAG;IAIxE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;IAClF,MAAM,GAAG,GAAG,GAAG,CAAC,yBAAyB,EAAE,IAAI,EAAE,CAAC;IAClD,MAAM,QAAQ,GAAG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,mBAAmB,CACjC,KAAyB,EACzB,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,GAAG,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC/B,IAAI,KAAK,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,KAAK,CAAC,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,oBAAoB;IAChE,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,mCAAmC;IAC7E,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,6BAA6B;IACpF,OAAO,KAAK,CAAC,aAAa,IAAI,GAAG,CAAC,QAAQ,CAAC;AAC7C,CAAC;AAED;8CAC8C;AAC9C,MAAM,UAAU,mBAAmB;IACjC,OAAO,CACL,4EAA4E;QAC5E,gFAAgF;QAChF,2EAA2E,CAC5E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* requirementsVerification — EndTurn Stage 4 (docs/HARNESS_IMPROVEMENT_BACKLOG.md
|
|
3
|
+
* item 1). The as-shipped gate verifies CITATIONS (Stage 2 grounding, Stage 3
|
|
4
|
+
* coordinates) but not TASK REQUIREMENTS: a wrong-artifact finish passes with
|
|
5
|
+
* honest citations and a legitimate empty `verification` ("none asked") —
|
|
6
|
+
* TB2's 2nd-largest failure class (20 wrong-artifact fails, 11 in
|
|
7
|
+
* flash-persist alone). Stage 4 makes the model re-read the task statement
|
|
8
|
+
* and attest each stated requirement.
|
|
9
|
+
*
|
|
10
|
+
* Armed by CORTEX_ENDTURN_REQUIREMENTS=true (off by default; the
|
|
11
|
+
* persist+EndTurn bench cell and server profiles arm it). Pure — the
|
|
12
|
+
* orchestrator supplies all state.
|
|
13
|
+
*/
|
|
14
|
+
export interface RequirementRow {
|
|
15
|
+
requirement: string;
|
|
16
|
+
satisfied_by: string;
|
|
17
|
+
verified_how: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RequirementsVerdict {
|
|
20
|
+
ok: boolean;
|
|
21
|
+
/** Rejection text to surface on the EndTurn tool_result (Stage-2 style). */
|
|
22
|
+
nudge?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function resolveEndTurnRequirementsMode(env?: NodeJS.ProcessEnv): boolean;
|
|
25
|
+
/** Conservative imperative/task-shape heuristic: does the user text ask for
|
|
26
|
+
* work (vs. a question/discussion)? False negatives are acceptable (no
|
|
27
|
+
* nudge); false positives are the cost to avoid. */
|
|
28
|
+
export declare function isTaskShaped(userText: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Stage 4: verify the `requirements` attestation. Caller gates on
|
|
31
|
+
* resolveEndTurnRequirementsMode() — this function assumes armed mode.
|
|
32
|
+
*/
|
|
33
|
+
export declare function verifyRequirements(input: {
|
|
34
|
+
/** Raw `requirements` value from the EndTurn tool input. */
|
|
35
|
+
requirements: unknown;
|
|
36
|
+
/** Raw `verification` value from the EndTurn tool input. */
|
|
37
|
+
verification: unknown;
|
|
38
|
+
/** The turn's real user prompt text (empty string when unknown). */
|
|
39
|
+
userTaskText: string;
|
|
40
|
+
/** Did this turn run Edit/Write/Bash/NotebookEdit? */
|
|
41
|
+
turnUsedMutatingTool: boolean;
|
|
42
|
+
}): RequirementsVerdict;
|
|
43
|
+
//# sourceMappingURL=requirementsVerification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirementsVerification.d.ts","sourceRoot":"","sources":["../../src/orchestrator/requirementsVerification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAET;AAED;;qDAEqD;AACrD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKtD;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,oBAAoB,EAAE,OAAO,CAAC;CAC/B,GAAG,mBAAmB,CAoEtB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* requirementsVerification — EndTurn Stage 4 (docs/HARNESS_IMPROVEMENT_BACKLOG.md
|
|
3
|
+
* item 1). The as-shipped gate verifies CITATIONS (Stage 2 grounding, Stage 3
|
|
4
|
+
* coordinates) but not TASK REQUIREMENTS: a wrong-artifact finish passes with
|
|
5
|
+
* honest citations and a legitimate empty `verification` ("none asked") —
|
|
6
|
+
* TB2's 2nd-largest failure class (20 wrong-artifact fails, 11 in
|
|
7
|
+
* flash-persist alone). Stage 4 makes the model re-read the task statement
|
|
8
|
+
* and attest each stated requirement.
|
|
9
|
+
*
|
|
10
|
+
* Armed by CORTEX_ENDTURN_REQUIREMENTS=true (off by default; the
|
|
11
|
+
* persist+EndTurn bench cell and server profiles arm it). Pure — the
|
|
12
|
+
* orchestrator supplies all state.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveEndTurnRequirementsMode(env = process.env) {
|
|
15
|
+
return (env.CORTEX_ENDTURN_REQUIREMENTS ?? '').trim().toLowerCase() === 'true';
|
|
16
|
+
}
|
|
17
|
+
/** Conservative imperative/task-shape heuristic: does the user text ask for
|
|
18
|
+
* work (vs. a question/discussion)? False negatives are acceptable (no
|
|
19
|
+
* nudge); false positives are the cost to avoid. */
|
|
20
|
+
export function isTaskShaped(userText) {
|
|
21
|
+
if (!userText || userText.length < 8)
|
|
22
|
+
return false;
|
|
23
|
+
return /\b(fix|add|implement|create|write|build|make|update|refactor|convert|generate|install|configure|set up|setup|remove|delete|rename|migrate|optimi[sz]e|debug|repair|extract|compress|decompress|parse|train|deploy|run)\b/i.test(userText);
|
|
24
|
+
}
|
|
25
|
+
const UNVERIFIED_RE = /^\s*unverified\s*$/i;
|
|
26
|
+
/**
|
|
27
|
+
* Stage 4: verify the `requirements` attestation. Caller gates on
|
|
28
|
+
* resolveEndTurnRequirementsMode() — this function assumes armed mode.
|
|
29
|
+
*/
|
|
30
|
+
export function verifyRequirements(input) {
|
|
31
|
+
const reqs = Array.isArray(input.requirements) ? input.requirements : null;
|
|
32
|
+
const verification = Array.isArray(input.verification) ? input.verification : [];
|
|
33
|
+
// 4a — task-shaped turn with no requirements enumerated.
|
|
34
|
+
if ((!reqs || reqs.length === 0) && isTaskShaped(input.userTaskText)) {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
nudge: 'EndTurn REJECTED (requirements) — this turn has a stated task but you enumerated no requirements. ' +
|
|
38
|
+
'Re-read the task statement and list EACH stated requirement in `requirements` ' +
|
|
39
|
+
'[{requirement, satisfied_by, verified_how}]: `satisfied_by` = what in your artifact satisfies it; ' +
|
|
40
|
+
'`verified_how` = the command/observation that proves it, or the literal string "UNVERIFIED". ' +
|
|
41
|
+
'Then call EndTurn again.',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// 4b — malformed rows.
|
|
45
|
+
if (reqs) {
|
|
46
|
+
const bad = reqs.findIndex((r) => !r ||
|
|
47
|
+
typeof r !== 'object' ||
|
|
48
|
+
typeof r.requirement !== 'string' ||
|
|
49
|
+
typeof r.satisfied_by !== 'string' ||
|
|
50
|
+
typeof r.verified_how !== 'string');
|
|
51
|
+
if (bad !== -1) {
|
|
52
|
+
return {
|
|
53
|
+
ok: false,
|
|
54
|
+
nudge: `EndTurn REJECTED (requirements) — row ${bad + 1} is malformed. Each row must be ` +
|
|
55
|
+
'{requirement, satisfied_by, verified_how} (strings). Use "UNVERIFIED" as verified_how ' +
|
|
56
|
+
'when you did not verify a requirement — do not omit the field. Then call EndTurn again.',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// 4c — unverified rows must be nudged ONCE toward verification.
|
|
60
|
+
const unverified = reqs.filter((r) => UNVERIFIED_RE.test(r.verified_how));
|
|
61
|
+
if (unverified.length > 0) {
|
|
62
|
+
const names = unverified
|
|
63
|
+
.slice(0, 3)
|
|
64
|
+
.map((r) => `"${r.requirement.slice(0, 80)}"`)
|
|
65
|
+
.join(', ');
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
nudge: `EndTurn REJECTED (requirements) — ${unverified.length} requirement(s) are UNVERIFIED: ${names}. ` +
|
|
69
|
+
'For each: either RUN the check that proves it (then put the command + observed result in ' +
|
|
70
|
+
'`verified_how`), or move it to `open_items` with a one-line justification and delete the row. ' +
|
|
71
|
+
'Then call EndTurn again.',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// 4d — mutating turn that ran no checks at all.
|
|
76
|
+
if (input.turnUsedMutatingTool && verification.length === 0) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
nudge: 'EndTurn REJECTED (verification) — you modified files this turn but `verification` is empty: ' +
|
|
80
|
+
'no build/test/lint/behavior check was run. Run at least one check that exercises what you ' +
|
|
81
|
+
'changed and list it with the real result line, or state in `open_items` why no check is ' +
|
|
82
|
+
'possible. Then call EndTurn again.',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return { ok: true };
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=requirementsVerification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirementsVerification.js","sourceRoot":"","sources":["../../src/orchestrator/requirementsVerification.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,15 @@ export declare function resolveToolProfile(env?: NodeJS.ProcessEnv): ToolProfile
|
|
|
29
29
|
* — the dsh anchored-standard point). 'full' or unknown → no anchor.
|
|
30
30
|
*/
|
|
31
31
|
export declare function resolveToolAnchor(env?: NodeJS.ProcessEnv, cardAnchor?: string | null): ToolProfileName | null;
|
|
32
|
+
/**
|
|
33
|
+
* CORTEX_TOOL_ANCHOR_PERSIST — frame selection for an armed anchor (backlog
|
|
34
|
+
* item 5). 'lifted' (default): the anchor lifts at the first tool_result
|
|
35
|
+
* boundary and the session's full profile applies. 'persist': the anchored
|
|
36
|
+
* surface stays the ONLY surface for the whole session (the TB2 persist
|
|
37
|
+
* frame, previously an installed-copy patch). Precedence: env override >
|
|
38
|
+
* card frameProfile > 'lifted'. Irrelevant when no anchor is armed.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveFrameProfile(env?: NodeJS.ProcessEnv, cardFrame?: string | null): 'lifted' | 'persist';
|
|
32
41
|
/** Do MCP / management / context tools ride along? Narrow arms suppress them
|
|
33
42
|
* (surface leak otherwise); full and lean keep them. */
|
|
34
43
|
export declare function isNarrowProfile(profile?: ToolProfileName): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolProfile.d.ts","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ToolProfile.d.ts","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAwBxF,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,CAIxF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GACzB,eAAe,GAAG,IAAI,CASxB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,QAAQ,GAAG,SAAS,CAOtB;AAED;yDACyD;AACzD,wBAAgB,eAAe,CAAC,OAAO,GAAE,eAAsC,GAAG,OAAO,CAExF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,GAAE,eAAsC,GAC9C,CAAC,EAAE,CAML;AAED;8EAC8E;AAC9E,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAChD,OAAO,GAAE,eAAsC,GAC9C,OAAO,CAOT"}
|
|
@@ -28,11 +28,15 @@ const ALWAYS_KEEP = new Set(['EndTurn', 'AskUserQuestion']);
|
|
|
28
28
|
const BASH_ONLY = new Set(['Bash', ...ALWAYS_KEEP]);
|
|
29
29
|
/** bash-plus: the minimal-harness arm (BASH_PLUS_SPEC.md, R61) — the Pi/dsh
|
|
30
30
|
* surface class: shell + structural file ops, nothing else. The shell-native
|
|
31
|
-
* small-model graduation target and P1 anchoring-A/B arm.
|
|
32
|
-
|
|
31
|
+
* small-model graduation target and P1 anchoring-A/B arm.
|
|
32
|
+
* ReadImage rides the practical doors (item 7): the orchestrator's VISION
|
|
33
|
+
* GATE strips it for non-vision cards BEFORE profile filtering, so set
|
|
34
|
+
* membership changes nothing for existing text-only frames — a vision card
|
|
35
|
+
* under a narrow door gets door+ReadImage (the vision-arm shape). */
|
|
36
|
+
const BASH_PLUS = new Set(['Bash', 'Read', 'Edit', 'Write', 'ReadImage', ...ALWAYS_KEEP]);
|
|
33
37
|
/** bash-edit: the dsh-Minimal shape — shell + structural editor ONLY (their
|
|
34
38
|
* bash + str_replace_editor). The deepseek home-door candidate. */
|
|
35
|
-
const BASH_EDIT = new Set(['Bash', 'Edit', ...ALWAYS_KEEP]);
|
|
39
|
+
const BASH_EDIT = new Set(['Bash', 'Edit', 'ReadImage', ...ALWAYS_KEEP]);
|
|
36
40
|
export function resolveToolProfile(env = process.env) {
|
|
37
41
|
const raw = (env.CORTEX_TOOL_PROFILE ?? 'full').trim().toLowerCase();
|
|
38
42
|
if (raw === 'lean' || raw === 'bash-only' || raw === 'bash-plus' || raw === 'bash-edit')
|
|
@@ -58,6 +62,25 @@ export function resolveToolAnchor(env = process.env, cardAnchor) {
|
|
|
58
62
|
return card;
|
|
59
63
|
return null;
|
|
60
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* CORTEX_TOOL_ANCHOR_PERSIST — frame selection for an armed anchor (backlog
|
|
67
|
+
* item 5). 'lifted' (default): the anchor lifts at the first tool_result
|
|
68
|
+
* boundary and the session's full profile applies. 'persist': the anchored
|
|
69
|
+
* surface stays the ONLY surface for the whole session (the TB2 persist
|
|
70
|
+
* frame, previously an installed-copy patch). Precedence: env override >
|
|
71
|
+
* card frameProfile > 'lifted'. Irrelevant when no anchor is armed.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveFrameProfile(env = process.env, cardFrame) {
|
|
74
|
+
const raw = (env.CORTEX_TOOL_ANCHOR_PERSIST ?? '').trim().toLowerCase();
|
|
75
|
+
if (raw === 'true' || raw === '1' || raw === 'persist')
|
|
76
|
+
return 'persist';
|
|
77
|
+
if (raw === 'false' || raw === '0' || raw === 'off' || raw === 'lifted')
|
|
78
|
+
return 'lifted';
|
|
79
|
+
const card = (cardFrame ?? '').trim().toLowerCase();
|
|
80
|
+
if (card === 'persist')
|
|
81
|
+
return 'persist';
|
|
82
|
+
return 'lifted';
|
|
83
|
+
}
|
|
61
84
|
/** Do MCP / management / context tools ride along? Narrow arms suppress them
|
|
62
85
|
* (surface leak otherwise); full and lean keep them. */
|
|
63
86
|
export function isNarrowProfile(profile = resolveToolProfile()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolProfile.js","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH;;;6BAG6B;AAC7B,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAE5D,sEAAsE;AACtE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;AAEpD
|
|
1
|
+
{"version":3,"file":"ToolProfile.js","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseToolRegistry.d.ts","sourceRoot":"","sources":["../../../src/tools/registries/BaseToolRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"BaseToolRegistry.d.ts","sourceRoot":"","sources":["../../../src/tools/registries/BaseToolRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAypErG;;GAEG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;;IAS7D;;OAEG;IACH,WAAW,IAAI,uBAAuB,EAAE;IAIxC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS;IAI1D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI9B;;OAEG;IACH,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,uBAAuB,EAAE;IAIrE;;OAEG;IACH,YAAY,IAAI,MAAM;CAGvB;AAGD,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
|
|
@@ -20,7 +20,7 @@ const BASE_TOOLS = [
|
|
|
20
20
|
By default, it reads up to 2000 lines starting from the beginning of the file.
|
|
21
21
|
When you already know which part of the file you need, only read that part. This can be important for larger files.
|
|
22
22
|
Results are returned using cat -n format, with line numbers starting at 1.
|
|
23
|
-
This tool
|
|
23
|
+
This tool reads TEXT files. For images (PNG/JPG/GIF/WebP) use the ReadImage tool when available — Read on a binary file returns unusable bytes.
|
|
24
24
|
Do NOT re-read a file you just edited to verify — Edit would have errored if the change failed, and the harness tracks file state for you.`,
|
|
25
25
|
schema: {
|
|
26
26
|
type: 'object',
|
|
@@ -113,6 +113,33 @@ GUIDANCE:
|
|
|
113
113
|
version: '1.0.0'
|
|
114
114
|
}
|
|
115
115
|
},
|
|
116
|
+
{
|
|
117
|
+
name: 'ReadImage',
|
|
118
|
+
description: `Load an image file (PNG, JPEG, GIF, or WebP) so you can SEE it — the image is attached to the conversation as visual input on the next message. Use this to inspect screenshots, diagrams, charts, rendered output, or video frames (extract frames first, e.g. via ffmpeg).
|
|
119
|
+
|
|
120
|
+
GUIDANCE:
|
|
121
|
+
- Only available when the active model supports image input.
|
|
122
|
+
- Format is detected from file content (magic bytes), not the extension.
|
|
123
|
+
- Large images: the provider downscales (~800x800) — no need to resize first unless over the 32 MiB limit.
|
|
124
|
+
- Unsupported formats (BMP/TIFF/PDF): convert first (e.g. Bash + Python PIL), then ReadImage.`,
|
|
125
|
+
schema: {
|
|
126
|
+
type: 'object',
|
|
127
|
+
properties: {
|
|
128
|
+
file_path: {
|
|
129
|
+
type: 'string',
|
|
130
|
+
description: 'Path to the image file (absolute, or relative to the working directory).'
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
required: ['file_path']
|
|
134
|
+
},
|
|
135
|
+
category: 'base',
|
|
136
|
+
discoveryTier: 'essential', // vision-gated; must be on TURN 1 (deferred loading hid it behind SearchTools — live-probe finding 2026-08-25),
|
|
137
|
+
metadata: {
|
|
138
|
+
immutable: true,
|
|
139
|
+
executionEnvironment: 'client',
|
|
140
|
+
version: '1.0.0'
|
|
141
|
+
}
|
|
142
|
+
},
|
|
116
143
|
{
|
|
117
144
|
name: 'Edit',
|
|
118
145
|
description: `Performs exact string replacements in files.
|
|
@@ -950,6 +977,7 @@ Use plan mode for tasks with genuine ambiguity — multiple reasonable architect
|
|
|
950
977
|
|
|
951
978
|
- citations: list EACH specific reference in your draft with the exact verbatim source you copied it from this turn. If you cannot produce the verbatim source, the reference is unverified — delete it from your answer and do not list it (quote the code instead of asserting a coordinate). Inventing one is a failed answer, exactly like a non-matching edit old_string.
|
|
952
979
|
- verification: list each build/test/lint command you actually ran with the real result line you saw. Do not list a command you did not run.
|
|
980
|
+
- requirements: re-read the ORIGINAL task statement and list each requirement it states, with what in your artifact satisfies it and the command/observation that proves it (or the literal "UNVERIFIED"). Finishing without checking the artifact against the stated task is the most common failed answer.
|
|
953
981
|
- self_review: re-read your draft as a skeptical reviewer — what you did NOT check, what is assumed/possibly wrong, what one more tool call would verify. This pass exists to catch your own mistakes before they ship.
|
|
954
982
|
- summary / open_items: what you delivered and any gaps — do not hide them.
|
|
955
983
|
|
|
@@ -981,6 +1009,19 @@ After EndTurn returns, act on your own self_review, then produce your final plai
|
|
|
981
1009
|
required: ['command', 'observed_result']
|
|
982
1010
|
}
|
|
983
1011
|
},
|
|
1012
|
+
requirements: {
|
|
1013
|
+
type: 'array',
|
|
1014
|
+
description: 'Each requirement STATED in the original task, checked against your artifact. Empty array = the turn had no stated task. verified_how is the command/observation proving the requirement is met, or the literal string "UNVERIFIED".',
|
|
1015
|
+
items: {
|
|
1016
|
+
type: 'object',
|
|
1017
|
+
properties: {
|
|
1018
|
+
requirement: { type: 'string', description: 'A requirement as stated in the task.' },
|
|
1019
|
+
satisfied_by: { type: 'string', description: 'What in your artifact satisfies it.' },
|
|
1020
|
+
verified_how: { type: 'string', description: 'The command/observation that proves it — or "UNVERIFIED".' }
|
|
1021
|
+
},
|
|
1022
|
+
required: ['requirement', 'satisfied_by', 'verified_how']
|
|
1023
|
+
}
|
|
1024
|
+
},
|
|
984
1025
|
summary: {
|
|
985
1026
|
type: 'string',
|
|
986
1027
|
description: 'One sentence: what you delivered this turn.'
|