@corenel/harness 0.13.0 → 0.15.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/approvals/service.d.ts.map +1 -1
- package/dist/approvals/service.js +4 -1
- package/dist/approvals/service.js.map +1 -1
- package/dist/audit/log.d.ts.map +1 -1
- package/dist/audit/log.js +12 -1
- package/dist/audit/log.js.map +1 -1
- package/dist/audit/recorder.d.ts +12 -1
- package/dist/audit/recorder.d.ts.map +1 -1
- package/dist/audit/recorder.js +36 -5
- package/dist/audit/recorder.js.map +1 -1
- package/dist/audit/runAudit.d.ts +2 -1
- package/dist/audit/runAudit.d.ts.map +1 -1
- package/dist/audit/runAudit.js +4 -0
- package/dist/audit/runAudit.js.map +1 -1
- package/dist/conversation.d.ts +33 -0
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +44 -1
- package/dist/conversation.js.map +1 -1
- package/dist/core/compactHistory.d.ts +27 -18
- package/dist/core/compactHistory.d.ts.map +1 -1
- package/dist/core/compactHistory.js +106 -40
- package/dist/core/compactHistory.js.map +1 -1
- package/dist/core/dontsRecent.d.ts +5 -0
- package/dist/core/dontsRecent.d.ts.map +1 -0
- package/dist/core/dontsRecent.js +23 -0
- package/dist/core/dontsRecent.js.map +1 -0
- package/dist/core/foldBlocks.d.ts +43 -0
- package/dist/core/foldBlocks.d.ts.map +1 -0
- package/dist/core/foldBlocks.js +114 -0
- package/dist/core/foldBlocks.js.map +1 -0
- package/dist/core/foldTypes.d.ts +25 -0
- package/dist/core/foldTypes.d.ts.map +1 -0
- package/dist/core/foldTypes.js +2 -0
- package/dist/core/foldTypes.js.map +1 -0
- package/dist/core/loop.d.ts +26 -5
- package/dist/core/loop.d.ts.map +1 -1
- package/dist/core/loop.js +274 -74
- package/dist/core/loop.js.map +1 -1
- package/dist/core/recovery.d.ts +1 -0
- package/dist/core/recovery.d.ts.map +1 -1
- package/dist/core/recovery.js +12 -0
- package/dist/core/recovery.js.map +1 -1
- package/dist/core/spawn.d.ts +13 -1
- package/dist/core/spawn.d.ts.map +1 -1
- package/dist/core/spawn.js +10 -1
- package/dist/core/spawn.js.map +1 -1
- package/dist/core/summarize.d.ts +9 -3
- package/dist/core/summarize.d.ts.map +1 -1
- package/dist/core/summarize.js +97 -42
- package/dist/core/summarize.js.map +1 -1
- package/dist/dag/executeNode.d.ts +3 -1
- package/dist/dag/executeNode.d.ts.map +1 -1
- package/dist/dag/executeNode.js +1 -0
- package/dist/dag/executeNode.js.map +1 -1
- package/dist/guardrail/permission-service.d.ts.map +1 -1
- package/dist/guardrail/permission-service.js +31 -11
- package/dist/guardrail/permission-service.js.map +1 -1
- package/dist/guardrail/serialize.d.ts.map +1 -1
- package/dist/guardrail/serialize.js +5 -0
- package/dist/guardrail/serialize.js.map +1 -1
- package/dist/guardrail/validate.d.ts.map +1 -1
- package/dist/guardrail/validate.js +21 -6
- package/dist/guardrail/validate.js.map +1 -1
- package/dist/memory/store.d.ts +3 -0
- package/dist/memory/store.d.ts.map +1 -1
- package/dist/memory/store.js +16 -1
- package/dist/memory/store.js.map +1 -1
- package/dist/orchestrator/record.d.ts +7 -0
- package/dist/orchestrator/record.d.ts.map +1 -1
- package/dist/orchestrator/record.js +14 -2
- package/dist/orchestrator/record.js.map +1 -1
- package/dist/prompts/library/defaults.generated.d.ts +2 -0
- package/dist/prompts/library/defaults.generated.d.ts.map +1 -1
- package/dist/prompts/library/defaults.generated.js +6 -0
- package/dist/prompts/library/defaults.generated.js.map +1 -1
- package/dist/prompts/library/index.d.ts +3 -0
- package/dist/prompts/library/index.d.ts.map +1 -1
- package/dist/prompts/library/index.js +3 -0
- package/dist/prompts/library/index.js.map +1 -1
- package/dist/sessions/directivesStore.d.ts +9 -0
- package/dist/sessions/directivesStore.d.ts.map +1 -0
- package/dist/sessions/directivesStore.js +54 -0
- package/dist/sessions/directivesStore.js.map +1 -0
- package/dist/sessions/fileSessionStore.d.ts +3 -2
- package/dist/sessions/fileSessionStore.d.ts.map +1 -1
- package/dist/sessions/fileSessionStore.js +30 -9
- package/dist/sessions/fileSessionStore.js.map +1 -1
- package/dist/sessions/foldStorage.d.ts +15 -0
- package/dist/sessions/foldStorage.d.ts.map +1 -0
- package/dist/sessions/foldStorage.js +121 -0
- package/dist/sessions/foldStorage.js.map +1 -0
- package/dist/sessions/jsonl.d.ts +6 -0
- package/dist/sessions/jsonl.d.ts.map +1 -1
- package/dist/sessions/jsonl.js +15 -1
- package/dist/sessions/jsonl.js.map +1 -1
- package/dist/sidecar/accessTestRig.d.ts +32 -0
- package/dist/sidecar/accessTestRig.d.ts.map +1 -0
- package/dist/sidecar/accessTestRig.js +107 -0
- package/dist/sidecar/accessTestRig.js.map +1 -0
- package/dist/sidecar/askView.d.ts +20 -0
- package/dist/sidecar/askView.d.ts.map +1 -0
- package/dist/sidecar/askView.js +38 -0
- package/dist/sidecar/askView.js.map +1 -0
- package/dist/sidecar/host.d.ts +139 -11
- package/dist/sidecar/host.d.ts.map +1 -1
- package/dist/sidecar/host.js +394 -13
- package/dist/sidecar/host.js.map +1 -1
- package/dist/sidecar/hostCapability.d.ts +6 -0
- package/dist/sidecar/hostCapability.d.ts.map +1 -0
- package/dist/sidecar/hostCapability.js +7 -0
- package/dist/sidecar/hostCapability.js.map +1 -0
- package/dist/sidecar/identity.d.ts +5 -0
- package/dist/sidecar/identity.d.ts.map +1 -1
- package/dist/sidecar/memberGate.d.ts +5 -0
- package/dist/sidecar/memberGate.d.ts.map +1 -0
- package/dist/sidecar/memberGate.js +128 -0
- package/dist/sidecar/memberGate.js.map +1 -0
- package/dist/sidecar/server.d.ts +425 -11
- package/dist/sidecar/server.d.ts.map +1 -1
- package/dist/sidecar/server.js +1820 -53
- package/dist/sidecar/server.js.map +1 -1
- package/dist/skills.d.ts +7 -1
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +18 -5
- package/dist/skills.js.map +1 -1
- package/dist/tools/builtins.d.ts +17 -0
- package/dist/tools/builtins.d.ts.map +1 -1
- package/dist/tools/builtins.js +22 -2
- package/dist/tools/builtins.js.map +1 -1
- package/dist/tools/callAgent.d.ts +14 -1
- package/dist/tools/callAgent.d.ts.map +1 -1
- package/dist/tools/callAgent.js +18 -2
- package/dist/tools/callAgent.js.map +1 -1
- package/dist/tools/createCrewAgent.d.ts +39 -0
- package/dist/tools/createCrewAgent.d.ts.map +1 -0
- package/dist/tools/createCrewAgent.js +121 -0
- package/dist/tools/createCrewAgent.js.map +1 -0
- package/dist/tools/foldTools.d.ts +5 -0
- package/dist/tools/foldTools.d.ts.map +1 -0
- package/dist/tools/foldTools.js +123 -0
- package/dist/tools/foldTools.js.map +1 -0
- package/dist/tools/skillTool.d.ts.map +1 -1
- package/dist/tools/skillTool.js +7 -2
- package/dist/tools/skillTool.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,31 +1,38 @@
|
|
|
1
1
|
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
|
|
2
|
+
import { type FoldSummary } from './foldBlocks';
|
|
3
|
+
export { CHECKPOINT_MARKER, ANCHOR_MARKER } from './foldBlocks';
|
|
2
4
|
export interface CompactHistoryOptions {
|
|
3
5
|
/** Summarizes the collapsed stretch. Injected so the partitioning is testable
|
|
4
6
|
* without a model call. */
|
|
5
|
-
summarize: (collapsed: ChatCompletionMessageParam[]) => Promise<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
summarize: (collapsed: ChatCompletionMessageParam[]) => Promise<FoldSummary>;
|
|
8
|
+
contextWindow: number;
|
|
9
|
+
/** DIRECTIVES.md content when the host has one; wins over the in-context block. */
|
|
10
|
+
directivesOverride?: string[] | null;
|
|
11
|
+
/** Whether recall_history exists, so the fold notice may name it. */
|
|
12
|
+
recallAvailable?: boolean;
|
|
10
13
|
/** Byte size past which a user message's own content is offloaded rather than
|
|
11
14
|
* kept inline. Requires `offload`. */
|
|
12
15
|
offloadOverBytes?: number;
|
|
13
16
|
/** Records oversized user content and returns the pointer to leave in its
|
|
14
17
|
* place — the same treatment rung 1 gives an oversized tool result. */
|
|
15
18
|
offload?: (content: string) => Promise<string>;
|
|
19
|
+
now?: () => Date;
|
|
16
20
|
}
|
|
17
21
|
export interface CompactHistoryResult {
|
|
18
22
|
/** The rebuilt message array to send from here on. */
|
|
19
23
|
messages: ChatCompletionMessageParam[];
|
|
20
|
-
/**
|
|
21
|
-
|
|
24
|
+
/** This fold's own summary (one entry), for CHECKPOINT.md and the event. */
|
|
25
|
+
summary: string;
|
|
26
|
+
/** The full merged directive list now in context, for DIRECTIVES.md. */
|
|
27
|
+
directives: string[];
|
|
28
|
+
/** The raw messages handed to the summarizer (older users and every folded
|
|
29
|
+
* non-user message, never this module's own blocks), for ARCHIVE.jsonl. */
|
|
30
|
+
collapsed: ChatCompletionMessageParam[];
|
|
31
|
+
/** How many conversation messages the fold removed: the collapsed ones. Not
|
|
32
|
+
* input length minus output length, which goes negative whenever the blocks
|
|
33
|
+
* a fold writes back outnumber what it removed. */
|
|
34
|
+
collapsedCount: number;
|
|
22
35
|
}
|
|
23
|
-
/** The marker every checkpoint message starts with, so a later pass can
|
|
24
|
-
* recognize one it already wrote instead of collapsing it again. */
|
|
25
|
-
export declare const CHECKPOINT_MARKER = "[checkpoint] ";
|
|
26
|
-
/** The marker every anchor message starts with. An anchor is context ABOUT the
|
|
27
|
-
* user message that follows it, not something the assistant said. */
|
|
28
|
-
export declare const ANCHOR_MARKER = "[anchor] ";
|
|
29
36
|
/** Window fill ratio at which history compaction becomes worth its cost.
|
|
30
37
|
* High on purpose: see the one-shot reasoning at the top of this file. */
|
|
31
38
|
export declare const COMPACT_AT_FILL = 0.86;
|
|
@@ -33,7 +40,7 @@ export declare const COMPACT_AT_FILL = 0.86;
|
|
|
33
40
|
* window is genuinely close to full, AND there is bulk to remove. A compaction
|
|
34
41
|
* that reduces nothing still invalidates the whole prefix, so "nothing to
|
|
35
42
|
* collapse" is a refusal, not a no-op. */
|
|
36
|
-
export declare function shouldCompact(fill: number, messages: ChatCompletionMessageParam[]): boolean;
|
|
43
|
+
export declare function shouldCompact(fill: number, messages: ChatCompletionMessageParam[], contextWindow?: number): boolean;
|
|
37
44
|
/** Fill must fall back below this before compaction re-arms. */
|
|
38
45
|
export declare const REARM_BELOW_FILL = 0.6;
|
|
39
46
|
/** How much the window must refill, ABOVE where the last compaction left it,
|
|
@@ -66,19 +73,21 @@ export declare function afterCompaction(): CompactGate;
|
|
|
66
73
|
* here. That is the right direction to be wrong in, since the cost of reading
|
|
67
74
|
* high is a compaction nobody needed. */
|
|
68
75
|
export declare function estimateFill(messages: ChatCompletionMessageParam[], contextWindow: number | undefined): number;
|
|
69
|
-
|
|
76
|
+
/** The token estimate `estimateFill` divides by the window: what a caller
|
|
77
|
+
* measuring the same messages against several windows computes once. */
|
|
78
|
+
export declare function estimateTokens(messages: ChatCompletionMessageParam[]): number;
|
|
79
|
+
export declare function compactionDecision(fill: number, messages: ChatCompletionMessageParam[], gate: CompactGate, contextWindow?: number): {
|
|
70
80
|
compact: boolean;
|
|
71
81
|
next: CompactGate;
|
|
72
82
|
};
|
|
73
|
-
export declare function compactHistory(messages: ChatCompletionMessageParam[], opts: CompactHistoryOptions): Promise<CompactHistoryResult>;
|
|
83
|
+
export declare function compactHistory(messages: ChatCompletionMessageParam[], opts: CompactHistoryOptions): Promise<CompactHistoryResult | null>;
|
|
74
84
|
/** An anchor or checkpoint a compaction wrote — bookkeeping ABOUT the
|
|
75
85
|
* conversation rather than part of it. Exported because a caller that has to
|
|
76
86
|
* tell "what this run added" from "what a rewrite inserted" cannot do it by
|
|
77
87
|
* position: a rewrite puts fresh objects into the array at arbitrary places. */
|
|
78
88
|
export declare const isCompactionMarker: typeof isOwnMarker;
|
|
79
|
-
/** An anchor or
|
|
89
|
+
/** An anchor, checkpoint or directives block this module wrote on an earlier pass. Dropped and
|
|
80
90
|
* rewritten each time rather than accumulated: the newest checkpoint already
|
|
81
91
|
* subsumes what the older ones recorded. */
|
|
82
92
|
declare function isOwnMarker(m: ChatCompletionMessageParam): boolean;
|
|
83
|
-
export {};
|
|
84
93
|
//# sourceMappingURL=compactHistory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compactHistory.d.ts","sourceRoot":"","sources":["../../core/compactHistory.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"compactHistory.d.ts","sourceRoot":"","sources":["../../core/compactHistory.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAEpF,OAAO,EAGuC,KAAK,WAAW,EAC7D,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC;+BAC2B;IAC3B,SAAS,EAAE,CAAC,SAAS,EAAE,0BAA0B,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACrC,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;0CACsC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;2EACuE;IACvE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,sDAAsD;IACtD,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;+EAC2E;IAC3E,SAAS,EAAE,0BAA0B,EAAE,CAAC;IACxC;;uDAEmD;IACnD,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;0EAC0E;AAC1E,eAAO,MAAM,eAAe,OAAO,CAAC;AAqBpC;;;0CAG0C;AAC1C,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,0BAA0B,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAOnH;AAED,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;kDACkD;AAClD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;;;;wEAOwE;AACxE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;qEACqE;AACrE,wBAAgB,eAAe,IAAI,WAAW,CAE7C;AAyBD;;;;;;;;;;yCAUyC;AACzC,wBAAgB,YAAY,CAAC,QAAQ,EAAE,0BAA0B,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG9G;AAED;wEACwE;AACxE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,0BAA0B,EAAE,GAAG,MAAM,CAI7E;AA+BD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,0BAA0B,EAAE,EACtC,IAAI,EAAE,WAAW,EACjB,aAAa,CAAC,EAAE,MAAM,GACrB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAQzC;AAED,wBAAsB,cAAc,CAClC,QAAQ,EAAE,0BAA0B,EAAE,EACtC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA8EtC;AAeD;;;gFAGgF;AAChF,eAAO,MAAM,kBAAkB,oBAAc,CAAC;AAY9C;;4CAE4C;AAC5C,iBAAS,WAAW,CAAC,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAK3D"}
|
|
@@ -10,23 +10,44 @@
|
|
|
10
10
|
* trims a little each turn therefore pays full reprocessing every turn and saves
|
|
11
11
|
* almost nothing. One shot, high threshold, large payoff. */
|
|
12
12
|
import { isContextNote } from './contextPressure.js';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export const CHECKPOINT_MARKER = '[checkpoint] ';
|
|
16
|
-
/** The marker every anchor message starts with. An anchor is context ABOUT the
|
|
17
|
-
* user message that follows it, not something the assistant said. */
|
|
18
|
-
export const ANCHOR_MARKER = '[anchor] ';
|
|
13
|
+
import { CHECKPOINT_MARKER, ANCHOR_MARKER, DIRECTIVES_MARKER, DIRECTIVES_SHARE, SUMMARY_SHARE, USER_TAIL_SHARE, shareChars, mergeDirectives, renderDirectivesBlock, parseDirectivesBlock, renderSummaryBlock, parseSummaryBlock, trimEntries, anchorText, } from './foldBlocks.js';
|
|
14
|
+
export { CHECKPOINT_MARKER, ANCHOR_MARKER } from './foldBlocks.js';
|
|
19
15
|
/** Window fill ratio at which history compaction becomes worth its cost.
|
|
20
16
|
* High on purpose: see the one-shot reasoning at the top of this file. */
|
|
21
17
|
export const COMPACT_AT_FILL = 0.86;
|
|
18
|
+
/** Indices (into `convo`) of the user messages kept verbatim: newest first,
|
|
19
|
+
* while they fit the budget; the newest is always kept. */
|
|
20
|
+
function keptUserTail(convo, budgetChars) {
|
|
21
|
+
const kept = new Set();
|
|
22
|
+
let used = 0;
|
|
23
|
+
for (let i = convo.length - 1; i >= 0; i--) {
|
|
24
|
+
if (convo[i].role !== 'user')
|
|
25
|
+
continue;
|
|
26
|
+
const size = messageChars(convo[i]);
|
|
27
|
+
if (kept.size > 0 && used + size > budgetChars)
|
|
28
|
+
break;
|
|
29
|
+
kept.add(i);
|
|
30
|
+
used += size;
|
|
31
|
+
}
|
|
32
|
+
return kept;
|
|
33
|
+
}
|
|
34
|
+
function conversational(m) {
|
|
35
|
+
return m.role !== 'system' && !isOwnMarker(m) && !isContextNote(m);
|
|
36
|
+
}
|
|
22
37
|
/** Whether compacting now is worth rewriting the cached prefix. Two gates: the
|
|
23
38
|
* window is genuinely close to full, AND there is bulk to remove. A compaction
|
|
24
39
|
* that reduces nothing still invalidates the whole prefix, so "nothing to
|
|
25
40
|
* collapse" is a refusal, not a no-op. */
|
|
26
|
-
export function shouldCompact(fill, messages) {
|
|
41
|
+
export function shouldCompact(fill, messages, contextWindow) {
|
|
27
42
|
if (fill < COMPACT_AT_FILL)
|
|
28
43
|
return false;
|
|
29
|
-
|
|
44
|
+
const convo = messages.filter(conversational);
|
|
45
|
+
if (convo.some((m) => m.role !== 'user'))
|
|
46
|
+
return true;
|
|
47
|
+
if (!contextWindow)
|
|
48
|
+
return false;
|
|
49
|
+
const users = convo.filter((m) => m.role === 'user');
|
|
50
|
+
return keptUserTail(convo, shareChars(USER_TAIL_SHARE, contextWindow)).size < users.length;
|
|
30
51
|
}
|
|
31
52
|
/** Fill must fall back below this before compaction re-arms. */
|
|
32
53
|
export const REARM_BELOW_FILL = 0.6;
|
|
@@ -77,10 +98,15 @@ function messageChars(m) {
|
|
|
77
98
|
export function estimateFill(messages, contextWindow) {
|
|
78
99
|
if (!contextWindow || contextWindow <= 0)
|
|
79
100
|
return 0;
|
|
101
|
+
return Math.min(1, estimateTokens(messages) / contextWindow);
|
|
102
|
+
}
|
|
103
|
+
/** The token estimate `estimateFill` divides by the window: what a caller
|
|
104
|
+
* measuring the same messages against several windows computes once. */
|
|
105
|
+
export function estimateTokens(messages) {
|
|
80
106
|
let chars = 0;
|
|
81
107
|
for (const m of messages)
|
|
82
108
|
chars += messageChars(m);
|
|
83
|
-
return
|
|
109
|
+
return chars / 4;
|
|
84
110
|
}
|
|
85
111
|
/* The gate, with hysteresis.
|
|
86
112
|
*
|
|
@@ -95,9 +121,9 @@ export function estimateFill(messages, contextWindow) {
|
|
|
95
121
|
*
|
|
96
122
|
* RE-ARMING ON PROGRESS, NOT ON A MARK. The first version re-armed only below
|
|
97
123
|
* REARM_BELOW_FILL, which assumed a compaction always drains past that mark.
|
|
98
|
-
* Nothing guarantees it:
|
|
99
|
-
*
|
|
100
|
-
* conversation with large pastes that
|
|
124
|
+
* Nothing guarantees it: the kept user tail is size-budgeted, but a fold's floor
|
|
125
|
+
* is still system + that tail + directives + the summary, and in a long
|
|
126
|
+
* conversation with large pastes that can clear 0.6. Landing anywhere in
|
|
101
127
|
* [0.6, 0.86) left the latch stuck SHUT FOREVER -- fill only grows from there,
|
|
102
128
|
* so it could never fall back under the mark, and the run compacted exactly
|
|
103
129
|
* once before marching into the wall it was supposed to prevent. Silently: a
|
|
@@ -111,13 +137,13 @@ export function estimateFill(messages, contextWindow) {
|
|
|
111
137
|
* the gate still does nothing -- which remains the right answer, because a
|
|
112
138
|
* second compaction so soon has almost nothing left to remove and would charge
|
|
113
139
|
* a full prefix rewrite to discover that. */
|
|
114
|
-
export function compactionDecision(fill, messages, gate) {
|
|
140
|
+
export function compactionDecision(fill, messages, gate, contextWindow) {
|
|
115
141
|
if (!gate.armed) {
|
|
116
142
|
const drained = fill < REARM_BELOW_FILL;
|
|
117
143
|
const regrown = gate.floor !== null && fill >= gate.floor + REARM_ON_REGROWTH;
|
|
118
144
|
return { compact: false, next: { ...gate, armed: drained || regrown } };
|
|
119
145
|
}
|
|
120
|
-
if (!shouldCompact(fill, messages))
|
|
146
|
+
if (!shouldCompact(fill, messages, contextWindow))
|
|
121
147
|
return { compact: false, next: gate };
|
|
122
148
|
return { compact: true, next: afterCompaction() };
|
|
123
149
|
}
|
|
@@ -129,42 +155,80 @@ export async function compactHistory(messages, opts) {
|
|
|
129
155
|
const tail = messages.length ? messages[messages.length - 1] : undefined;
|
|
130
156
|
const pending = tail && isUnansweredToolCall(tail) ? tail : null;
|
|
131
157
|
const body = pending ? messages.slice(0, -1) : messages;
|
|
158
|
+
const w = opts.contextWindow;
|
|
132
159
|
const system = body.filter((m) => m.role === 'system');
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
* and letting it into the summarizer's input would write it into the
|
|
136
|
-
* checkpoint as though it were something that happened in the conversation.
|
|
137
|
-
* The agent gets a fresh one on the next crossing if it earns it. */
|
|
138
|
-
const collapsed = body.filter((m) => m.role !== 'system' && m.role !== 'user' && !isContextNote(m));
|
|
139
|
-
const kept = [];
|
|
140
|
-
let answered = null;
|
|
160
|
+
let prevDirectives = [];
|
|
161
|
+
let prevSummary = { folds: 0, entries: [] };
|
|
141
162
|
for (const m of body) {
|
|
142
|
-
|
|
143
|
-
* things to re-anchor. An anchor is an assistant message with string
|
|
144
|
-
* content, so a naive walk picks up the previous compaction's anchors and
|
|
145
|
-
* anchors those — a real run produced
|
|
146
|
-
* "[anchor] answering: [anchor] answering: [anchor] answering: ...".
|
|
147
|
-
* These are bookkeeping about the conversation, not part of it. */
|
|
148
|
-
if (isOwnMarker(m) || isContextNote(m))
|
|
163
|
+
if (m.role !== 'assistant' || typeof m.content !== 'string')
|
|
149
164
|
continue;
|
|
150
|
-
|
|
151
|
-
|
|
165
|
+
const d = parseDirectivesBlock(m.content);
|
|
166
|
+
if (d) {
|
|
167
|
+
prevDirectives = d;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (m.content.startsWith(CHECKPOINT_MARKER))
|
|
171
|
+
prevSummary = parseSummaryBlock(m.content) ?? prevSummary;
|
|
172
|
+
}
|
|
173
|
+
/* Our own blocks and stale pressure notices are not part of the conversation:
|
|
174
|
+
* the summary block is carried forward verbatim (never re-summarized), and a
|
|
175
|
+
* pressure notice is a fact about the window this fold is emptying. */
|
|
176
|
+
const convo = body.filter(conversational);
|
|
177
|
+
const kept = keptUserTail(convo, shareChars(USER_TAIL_SHARE, w));
|
|
178
|
+
const collapsed = convo.filter((m, i) => !(m.role === 'user' && kept.has(i)));
|
|
179
|
+
/* Nothing to collapse (e.g. one huge newest user message): a fold would only
|
|
180
|
+
* invent a summary and rewrite the cached prefix for no gain. */
|
|
181
|
+
if (!collapsed.length)
|
|
182
|
+
return null;
|
|
183
|
+
const folded = await opts.summarize(collapsed);
|
|
184
|
+
const base = opts.directivesOverride ?? prevDirectives;
|
|
185
|
+
const directives = mergeDirectives(base, folded.directives, shareChars(DIRECTIVES_SHARE, w));
|
|
186
|
+
const at = (opts.now ?? (() => new Date()))().toISOString();
|
|
187
|
+
const folds = prevSummary.folds + 1;
|
|
188
|
+
const recall = !!opts.recallAvailable;
|
|
189
|
+
/* The share bounds the whole rendered block, so the fixed head and notice come off the budget first. */
|
|
190
|
+
const overhead = renderSummaryBlock({ folds, entries: [] }, { recall }).length;
|
|
191
|
+
const entries = trimEntries([...prevSummary.entries, { at, body: folded.summary }], Math.max(0, shareChars(SUMMARY_SHARE, w) - overhead));
|
|
192
|
+
const summaryBlock = renderSummaryBlock({ folds, entries }, { recall });
|
|
193
|
+
const tailOut = [];
|
|
194
|
+
let answered = null;
|
|
195
|
+
for (let i = 0; i < convo.length; i++) {
|
|
196
|
+
const m = convo[i];
|
|
197
|
+
if (m.role === 'assistant' && typeof m.content === 'string' && m.content.trim()) {
|
|
198
|
+
answered = m.content;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
152
201
|
if (m.role !== 'user')
|
|
153
202
|
continue;
|
|
154
|
-
|
|
155
|
-
|
|
203
|
+
const replyTo = answered;
|
|
204
|
+
answered = null;
|
|
205
|
+
if (!kept.has(i))
|
|
206
|
+
continue;
|
|
207
|
+
const a = anchorText(replyTo);
|
|
208
|
+
if (a)
|
|
209
|
+
tailOut.push({ role: 'assistant', content: `${ANCHOR_MARKER}${a}` });
|
|
210
|
+
else if (replyTo === null) {
|
|
211
|
+
/* The answered turn may have been folded away by an earlier fold, which
|
|
212
|
+
* left its anchor directly in front of this user. Carry it as-is. */
|
|
213
|
+
const prev = body[body.indexOf(m) - 1];
|
|
214
|
+
if (prev && prev.role === 'assistant' && typeof prev.content === 'string' && prev.content.startsWith(ANCHOR_MARKER)) {
|
|
215
|
+
tailOut.push({ role: 'assistant', content: prev.content });
|
|
216
|
+
}
|
|
156
217
|
}
|
|
157
|
-
|
|
218
|
+
tailOut.push(await offloadIfOversized(m, opts));
|
|
158
219
|
}
|
|
159
|
-
const summary = await opts.summarize(collapsed);
|
|
160
220
|
return {
|
|
161
221
|
messages: [
|
|
162
222
|
...system,
|
|
163
|
-
{ role: 'assistant', content:
|
|
164
|
-
|
|
223
|
+
...(directives.length ? [{ role: 'assistant', content: renderDirectivesBlock(directives) }] : []),
|
|
224
|
+
{ role: 'assistant', content: summaryBlock },
|
|
225
|
+
...tailOut,
|
|
165
226
|
...(pending ? [pending] : []),
|
|
166
227
|
],
|
|
167
|
-
|
|
228
|
+
summary: folded.summary,
|
|
229
|
+
directives,
|
|
230
|
+
collapsed,
|
|
231
|
+
collapsedCount: collapsed.length,
|
|
168
232
|
};
|
|
169
233
|
}
|
|
170
234
|
/** A user turn's DECISION text is small and stays verbatim; a pasted log is
|
|
@@ -192,13 +256,15 @@ export const isCompactionMarker = isOwnMarker;
|
|
|
192
256
|
* conflating them silently truncates every `appended` count taken after a
|
|
193
257
|
* notice fired, and the host then persists a partial tail. One predicate, two
|
|
194
258
|
* very different jobs -- loop.contextPressure.test.ts pins the difference. */
|
|
195
|
-
/** An anchor or
|
|
259
|
+
/** An anchor, checkpoint or directives block this module wrote on an earlier pass. Dropped and
|
|
196
260
|
* rewritten each time rather than accumulated: the newest checkpoint already
|
|
197
261
|
* subsumes what the older ones recorded. */
|
|
198
262
|
function isOwnMarker(m) {
|
|
199
263
|
if (m.role !== 'assistant' || typeof m.content !== 'string')
|
|
200
264
|
return false;
|
|
201
|
-
return m.content.startsWith(ANCHOR_MARKER)
|
|
265
|
+
return m.content.startsWith(ANCHOR_MARKER)
|
|
266
|
+
|| m.content.startsWith(CHECKPOINT_MARKER)
|
|
267
|
+
|| m.content.startsWith(DIRECTIVES_MARKER);
|
|
202
268
|
}
|
|
203
269
|
function isUnansweredToolCall(m) {
|
|
204
270
|
return m.role === 'assistant' && Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compactHistory.js","sourceRoot":"","sources":["../../core/compactHistory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;6DAU6D;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"compactHistory.js","sourceRoot":"","sources":["../../core/compactHistory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
|
|
2
|
+
import type { DontsContextMessage } from '@corenel/protocol';
|
|
3
|
+
export declare const DONTS_RECENT_COUNT = 6;
|
|
4
|
+
export declare function recentForJudge(messages: readonly ChatCompletionMessageParam[], count?: number): DontsContextMessage[];
|
|
5
|
+
//# sourceMappingURL=dontsRecent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dontsRecent.d.ts","sourceRoot":"","sources":["../../core/dontsRecent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAcpC,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,0BAA0B,EAAE,EAAE,KAAK,SAAqB,GAAG,mBAAmB,EAAE,CAQjI"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const DONTS_RECENT_COUNT = 6;
|
|
2
|
+
function textOf(m) {
|
|
3
|
+
const c = m.content;
|
|
4
|
+
let text = typeof c === 'string'
|
|
5
|
+
? c
|
|
6
|
+
: Array.isArray(c) ? c.map((p) => ('text' in p && typeof p.text === 'string' ? p.text : '')).filter(Boolean).join('\n') : '';
|
|
7
|
+
if (m.role === 'assistant' && m.tool_calls && m.tool_calls.length) {
|
|
8
|
+
const names = `[called ${m.tool_calls.map((t) => t.function.name).join(', ')}]`;
|
|
9
|
+
text = text ? `${text}\n${names}` : names;
|
|
10
|
+
}
|
|
11
|
+
return text;
|
|
12
|
+
}
|
|
13
|
+
export function recentForJudge(messages, count = DONTS_RECENT_COUNT) {
|
|
14
|
+
const out = [];
|
|
15
|
+
for (let i = messages.length - 1; i >= 0 && out.length < count; i--) {
|
|
16
|
+
const m = messages[i];
|
|
17
|
+
if (m.role !== 'user' && m.role !== 'assistant' && m.role !== 'tool')
|
|
18
|
+
continue;
|
|
19
|
+
out.unshift({ role: m.role, text: textOf(m) });
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=dontsRecent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dontsRecent.js","sourceRoot":"","sources":["../../core/dontsRecent.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC,SAAS,MAAM,CAAC,CAA6B;IAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;IACpB,IAAI,IAAI,GAAG,OAAO,CAAC,KAAK,QAAQ;QAC9B,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/H,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QAClE,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAChF,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAA+C,EAAE,KAAK,GAAG,kBAAkB;IACxG,MAAM,GAAG,GAA0B,EAAE,CAAC;IACtC,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QACpE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAC/E,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** The marker every checkpoint (rolling summary) message starts with, so a
|
|
2
|
+
* later pass can recognize one it already wrote instead of collapsing it again. */
|
|
3
|
+
export declare const CHECKPOINT_MARKER = "[checkpoint] ";
|
|
4
|
+
/** The marker every anchor message starts with. An anchor is context ABOUT the
|
|
5
|
+
* user message that follows it, not something the assistant said. */
|
|
6
|
+
export declare const ANCHOR_MARKER = "[anchor] ";
|
|
7
|
+
export declare const USER_TAIL_SHARE = 0.15;
|
|
8
|
+
export declare const DIRECTIVES_SHARE = 0.02;
|
|
9
|
+
export declare const SUMMARY_SHARE = 0.1;
|
|
10
|
+
export declare const SUMMARIZER_INPUT_SHARE = 0.7;
|
|
11
|
+
export declare const ANCHOR_CHARS = 120;
|
|
12
|
+
/** The window assumed when a host gave none -- matches resolveContextWindow's fallback. */
|
|
13
|
+
export declare const FALLBACK_CONTEXT_WINDOW = 32000;
|
|
14
|
+
export declare const DIRECTIVES_MARKER = "[directives] ";
|
|
15
|
+
export interface FoldSummary {
|
|
16
|
+
summary: string;
|
|
17
|
+
directives: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface SummaryEntry {
|
|
20
|
+
at: string;
|
|
21
|
+
body: string;
|
|
22
|
+
}
|
|
23
|
+
export interface SummaryBlock {
|
|
24
|
+
folds: number;
|
|
25
|
+
entries: SummaryEntry[];
|
|
26
|
+
}
|
|
27
|
+
/** A share of a token window, in characters (4 per token, as estimateFill). */
|
|
28
|
+
export declare function shareChars(share: number, contextWindow: number): number;
|
|
29
|
+
export declare function normalizeDirective(s: string): string;
|
|
30
|
+
/** Previous then new, de-duplicated by normalized text (first wording wins),
|
|
31
|
+
* then the OLDEST dropped until the total fits `maxChars`. */
|
|
32
|
+
export declare function mergeDirectives(prev: string[], next: string[], maxChars: number): string[];
|
|
33
|
+
export declare function renderDirectivesBlock(directives: string[]): string;
|
|
34
|
+
export declare function parseDirectivesBlock(content: string): string[] | null;
|
|
35
|
+
export declare function renderSummaryBlock(block: SummaryBlock, opts: {
|
|
36
|
+
recall: boolean;
|
|
37
|
+
}): string;
|
|
38
|
+
export declare function parseSummaryBlock(content: string): SummaryBlock | null;
|
|
39
|
+
/** Drop the oldest entries until their RENDERED size fits; the newest always stays. */
|
|
40
|
+
export declare function trimEntries(entries: SummaryEntry[], maxChars: number): SummaryEntry[];
|
|
41
|
+
/** What a kept user message was replying to, without a model call. */
|
|
42
|
+
export declare function anchorText(answered: string | null): string | null;
|
|
43
|
+
//# sourceMappingURL=foldBlocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foldBlocks.d.ts","sourceRoot":"","sources":["../../core/foldBlocks.ts"],"names":[],"mappings":"AAOA;mFACmF;AACnF,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;qEACqE;AACrE,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,YAAY,MAAM,CAAC;AAChC,2FAA2F;AAC3F,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAC9C,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AACD,MAAM,WAAW,YAAY;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC1D,MAAM,WAAW,YAAY;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE;AAExE,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;8DAC8D;AAC9D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAc1F;AAID,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAElE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAGrE;AAMD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAQzF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAiBtE;AAOD,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAKrF;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAGjE"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* The blocks a fold leaves in the conversation, as pure text in and out.
|
|
2
|
+
*
|
|
3
|
+
* Both blocks are PARSED BACK FROM THE MESSAGE on the next fold, so a fold
|
|
4
|
+
* needs no store to remember what the last one kept: the conversation is its
|
|
5
|
+
* own record. The durable copies (CHECKPOINT.md, DIRECTIVES.md) are written by
|
|
6
|
+
* the host; these are only what the model carries. */
|
|
7
|
+
/** The marker every checkpoint (rolling summary) message starts with, so a
|
|
8
|
+
* later pass can recognize one it already wrote instead of collapsing it again. */
|
|
9
|
+
export const CHECKPOINT_MARKER = '[checkpoint] ';
|
|
10
|
+
/** The marker every anchor message starts with. An anchor is context ABOUT the
|
|
11
|
+
* user message that follows it, not something the assistant said. */
|
|
12
|
+
export const ANCHOR_MARKER = '[anchor] ';
|
|
13
|
+
export const USER_TAIL_SHARE = 0.15;
|
|
14
|
+
export const DIRECTIVES_SHARE = 0.02;
|
|
15
|
+
export const SUMMARY_SHARE = 0.1;
|
|
16
|
+
export const SUMMARIZER_INPUT_SHARE = 0.7;
|
|
17
|
+
export const ANCHOR_CHARS = 120;
|
|
18
|
+
/** The window assumed when a host gave none -- matches resolveContextWindow's fallback. */
|
|
19
|
+
export const FALLBACK_CONTEXT_WINDOW = 32000;
|
|
20
|
+
export const DIRECTIVES_MARKER = '[directives] ';
|
|
21
|
+
/** A share of a token window, in characters (4 per token, as estimateFill). */
|
|
22
|
+
export function shareChars(share, contextWindow) {
|
|
23
|
+
return Math.floor(share * contextWindow * 4);
|
|
24
|
+
}
|
|
25
|
+
export function normalizeDirective(s) {
|
|
26
|
+
return s.trim().replace(/\s+/g, ' ').toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
/** Previous then new, de-duplicated by normalized text (first wording wins),
|
|
29
|
+
* then the OLDEST dropped until the total fits `maxChars`. */
|
|
30
|
+
export function mergeDirectives(prev, next, maxChars) {
|
|
31
|
+
const seen = new Set();
|
|
32
|
+
const out = [];
|
|
33
|
+
for (const d of [...prev, ...next]) {
|
|
34
|
+
const t = d.trim().replace(/\s+/g, ' ');
|
|
35
|
+
if (!t)
|
|
36
|
+
continue;
|
|
37
|
+
const k = normalizeDirective(t);
|
|
38
|
+
if (seen.has(k))
|
|
39
|
+
continue;
|
|
40
|
+
seen.add(k);
|
|
41
|
+
out.push(t);
|
|
42
|
+
}
|
|
43
|
+
let total = out.reduce((n, d) => n + d.length, 0);
|
|
44
|
+
while (out.length > 1 && total > maxChars)
|
|
45
|
+
total -= out.shift().length;
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
const DIRECTIVES_HEAD = 'Standing instructions and decisions from the user. They hold until the user changes them:';
|
|
49
|
+
export function renderDirectivesBlock(directives) {
|
|
50
|
+
return `${DIRECTIVES_MARKER}${DIRECTIVES_HEAD}\n${directives.map((d) => `- ${d}`).join('\n')}`;
|
|
51
|
+
}
|
|
52
|
+
export function parseDirectivesBlock(content) {
|
|
53
|
+
if (!content.startsWith(DIRECTIVES_MARKER))
|
|
54
|
+
return null;
|
|
55
|
+
return content.split('\n').filter((l) => l.startsWith('- ')).map((l) => l.slice(2).trim()).filter(Boolean);
|
|
56
|
+
}
|
|
57
|
+
const SUMMARY_HEAD = /^Conversation so far \(folded (\d+) times?\)\.$/;
|
|
58
|
+
const ENTRY_LINE = /^--- fold (.*) ---$/;
|
|
59
|
+
const NOTICE_PREFIX = 'Earlier conversation was folded ';
|
|
60
|
+
export function renderSummaryBlock(block, opts) {
|
|
61
|
+
const n = block.folds;
|
|
62
|
+
const parts = [`Conversation so far (folded ${n} ${n === 1 ? 'time' : 'times'}).`];
|
|
63
|
+
for (const e of block.entries)
|
|
64
|
+
parts.push(`--- fold ${e.at} ---`, e.body);
|
|
65
|
+
const notice = `${NOTICE_PREFIX}${n} ${n === 1 ? 'time' : 'times'}.`
|
|
66
|
+
+ (opts.recall ? ' Older summaries and the full transcript can be searched with recall_history.' : '');
|
|
67
|
+
parts.push('', notice);
|
|
68
|
+
return `${CHECKPOINT_MARKER}${parts.join('\n')}`;
|
|
69
|
+
}
|
|
70
|
+
export function parseSummaryBlock(content) {
|
|
71
|
+
if (!content.startsWith(CHECKPOINT_MARKER))
|
|
72
|
+
return null;
|
|
73
|
+
const lines = content.slice(CHECKPOINT_MARKER.length).split('\n');
|
|
74
|
+
const head = SUMMARY_HEAD.exec(lines[0] ?? '');
|
|
75
|
+
/* A checkpoint written before this format existed is one plain summary.
|
|
76
|
+
* Treat it as one entry from one fold rather than dropping it. */
|
|
77
|
+
if (!head)
|
|
78
|
+
return { folds: 1, entries: [{ at: '', body: lines.join('\n').trim() }] };
|
|
79
|
+
const entries = [];
|
|
80
|
+
let cur = null;
|
|
81
|
+
for (const line of lines.slice(1)) {
|
|
82
|
+
if (line.startsWith(NOTICE_PREFIX))
|
|
83
|
+
break;
|
|
84
|
+
const m = ENTRY_LINE.exec(line);
|
|
85
|
+
if (m) {
|
|
86
|
+
cur = { at: m[1], body: '' };
|
|
87
|
+
entries.push(cur);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (cur)
|
|
91
|
+
cur.body = cur.body ? `${cur.body}\n${line}` : line;
|
|
92
|
+
}
|
|
93
|
+
for (const e of entries)
|
|
94
|
+
e.body = e.body.replace(/\n+$/, '');
|
|
95
|
+
return { folds: Number(head[1]), entries };
|
|
96
|
+
}
|
|
97
|
+
/** The size an entry adds to the rendered block: its fold line and its body, each with a newline. */
|
|
98
|
+
function entryChars(e) {
|
|
99
|
+
return `--- fold ${e.at} ---`.length + 1 + e.body.length + 1;
|
|
100
|
+
}
|
|
101
|
+
/** Drop the oldest entries until their RENDERED size fits; the newest always stays. */
|
|
102
|
+
export function trimEntries(entries, maxChars) {
|
|
103
|
+
const out = [...entries];
|
|
104
|
+
let total = out.reduce((n, e) => n + entryChars(e), 0);
|
|
105
|
+
while (out.length > 1 && total > maxChars)
|
|
106
|
+
total -= entryChars(out.shift());
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
/** What a kept user message was replying to, without a model call. */
|
|
110
|
+
export function anchorText(answered) {
|
|
111
|
+
const t = (answered ?? '').replace(/\s+/g, ' ').trim();
|
|
112
|
+
return t ? `re: ${t.slice(0, ANCHOR_CHARS)}` : null;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=foldBlocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foldBlocks.js","sourceRoot":"","sources":["../../core/foldBlocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
|
|
2
|
+
import type { FoldSummary } from './foldBlocks';
|
|
3
|
+
/** One fold as the host records it: what the summarizer kept, and the raw
|
|
4
|
+
* messages it was handed, so recall can still find what left the context. */
|
|
5
|
+
export interface FoldRecord extends FoldSummary {
|
|
6
|
+
collapsed: ChatCompletionMessageParam[];
|
|
7
|
+
}
|
|
8
|
+
export interface TranscriptReader {
|
|
9
|
+
/** This session's stored messages, either stored shape, including what
|
|
10
|
+
* folds removed. Throws when there is no readable history at all. */
|
|
11
|
+
messages(): Promise<unknown[]>;
|
|
12
|
+
/** CHECKPOINT.md text, or null when there is none. */
|
|
13
|
+
checkpoints(): Promise<string | null>;
|
|
14
|
+
}
|
|
15
|
+
export interface DirectivesFile {
|
|
16
|
+
/** Parsed DIRECTIVES.md, or null when absent/unreadable. */
|
|
17
|
+
read(): Promise<string[] | null>;
|
|
18
|
+
write(directives: string[]): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface FoldStorage {
|
|
21
|
+
onFold?(record: FoldRecord): Promise<void>;
|
|
22
|
+
directives?: DirectivesFile;
|
|
23
|
+
transcript?: TranscriptReader;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=foldTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foldTypes.d.ts","sourceRoot":"","sources":["../../core/foldTypes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;6EAC6E;AAC7E,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,SAAS,EAAE,0BAA0B,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B;yEACqE;IACrE,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/B,sDAAsD;IACtD,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IACjC,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foldTypes.js","sourceRoot":"","sources":["../../core/foldTypes.ts"],"names":[],"mappings":""}
|