pi-ui-extend 1.0.39 → 1.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/app/commands/command-registry.js +2 -2
- package/dist/app/commands/command-session-actions.d.ts +0 -1
- package/dist/app/commands/command-session-actions.js +22 -13
- package/dist/app/icons.d.ts +14 -0
- package/dist/app/icons.js +33 -0
- package/dist/app/rendering/conversation-tool-renderer.js +2 -2
- package/dist/app/rendering/dcp-stats.d.ts +6 -1
- package/dist/app/rendering/dcp-stats.js +214 -46
- package/dist/app/rendering/editor-panels.js +8 -5
- package/dist/app/session/lazy-session-manager.js +12 -1
- package/dist/app/session/tabs-controller.d.ts +2 -5
- package/dist/app/session/tabs-controller.js +12 -21
- package/dist/app/subagents/subagents-model.d.ts +14 -1
- package/dist/app/subagents/subagents-model.js +34 -15
- package/dist/app/types.d.ts +2 -0
- package/dist/bundled-extensions/session-title/config.js +1 -1
- package/dist/markdown-format.js +27 -9
- package/dist/schemas/pi-tools-suite-schema.d.ts +29 -16
- package/dist/schemas/pi-tools-suite-schema.js +46 -31
- package/external/pi-tools-suite/README.md +392 -52
- package/external/pi-tools-suite/docs/browser-qa-subagent.md +31 -21
- package/external/pi-tools-suite/docs/context-gateway-p00-adr.md +216 -0
- package/external/pi-tools-suite/docs/context-gateway-p01n-gate-review.md +122 -0
- package/external/pi-tools-suite/docs/context-gateway-p01n-measurement.md +133 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-ra-evidence.md +111 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rb-evidence.md +100 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rc-evidence.md +69 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rd-evidence.md +100 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-re-evidence.md +74 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rf-evidence.md +153 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rg-evidence.md +235 -0
- package/external/pi-tools-suite/docs/evals.md +684 -0
- package/external/pi-tools-suite/docs/subagent-model-pools.md +109 -0
- package/external/pi-tools-suite/package.json +10 -3
- package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/scripts/browser-qa-runner.mjs +82 -1
- package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/SKILL.md → agents/browser-qa.md} +261 -12
- package/external/pi-tools-suite/src/async-subagents/agents/implement.md +20 -0
- package/external/pi-tools-suite/src/async-subagents/agents/oracle.md +16 -0
- package/external/pi-tools-suite/src/async-subagents/agents/research.md +18 -0
- package/external/pi-tools-suite/src/async-subagents/agents/verify.md +18 -0
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +27 -243
- package/external/pi-tools-suite/src/async-subagents/commands.ts +6 -2
- package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +41 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +13 -93
- package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +494 -0
- package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +9 -0
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +200 -143
- package/external/pi-tools-suite/src/async-subagents/core/model-fallback.ts +1 -1
- package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +54 -0
- package/external/pi-tools-suite/src/async-subagents/core/prompt.ts +7 -6
- package/external/pi-tools-suite/src/async-subagents/core/routing.ts +52 -45
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +12 -4
- package/external/pi-tools-suite/src/async-subagents/index.ts +11 -1
- package/external/pi-tools-suite/src/async-subagents/lib.ts +6 -2
- package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +46 -18
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +3 -2
- package/external/pi-tools-suite/src/async-subagents/types.ts +2 -0
- package/external/pi-tools-suite/src/coding-discipline/index.ts +41 -142
- package/external/pi-tools-suite/src/config.ts +1 -22
- package/external/pi-tools-suite/src/context-gateway/accounting.ts +151 -0
- package/external/pi-tools-suite/src/context-gateway/config.ts +111 -0
- package/external/pi-tools-suite/src/context-gateway/index.ts +160 -0
- package/external/pi-tools-suite/src/context-gateway/metadata-normalization.ts +88 -0
- package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +89 -0
- package/external/pi-tools-suite/src/context-gateway/telemetry.ts +429 -0
- package/external/pi-tools-suite/src/context-gateway/test-output-parser.ts +326 -0
- package/external/pi-tools-suite/src/context-gateway/types.ts +152 -0
- package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +106 -0
- package/external/pi-tools-suite/src/dcp/auto-compress.ts +810 -106
- package/external/pi-tools-suite/src/dcp/commands.ts +64 -139
- package/external/pi-tools-suite/src/dcp/compress-tool.ts +369 -35
- package/external/pi-tools-suite/src/dcp/compression-blocks.ts +510 -64
- package/external/pi-tools-suite/src/dcp/compression-preview.ts +113 -0
- package/external/pi-tools-suite/src/dcp/compression-progress.ts +70 -0
- package/external/pi-tools-suite/src/dcp/config.ts +36 -61
- package/external/pi-tools-suite/src/dcp/conversation-index.ts +421 -0
- package/external/pi-tools-suite/src/dcp/debug-log.ts +7 -5
- package/external/pi-tools-suite/src/dcp/index.ts +617 -203
- package/external/pi-tools-suite/src/dcp/journal.ts +566 -0
- package/external/pi-tools-suite/src/dcp/progress-controller.ts +244 -0
- package/external/pi-tools-suite/src/dcp/prompts.ts +10 -7
- package/external/pi-tools-suite/src/dcp/provider-tool-results.ts +189 -0
- package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +298 -78
- package/external/pi-tools-suite/src/dcp/pruner-compression-blocks.ts +173 -281
- package/external/pi-tools-suite/src/dcp/pruner-emergency.ts +2 -4
- package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +17 -5
- package/external/pi-tools-suite/src/dcp/pruner-metadata.ts +11 -1
- package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +30 -82
- package/external/pi-tools-suite/src/dcp/pruner-tools.ts +22 -133
- package/external/pi-tools-suite/src/dcp/pruner.ts +18 -33
- package/external/pi-tools-suite/src/dcp/recovery.ts +129 -0
- package/external/pi-tools-suite/src/dcp/shadow-plan.ts +127 -0
- package/external/pi-tools-suite/src/dcp/state-transaction.ts +102 -0
- package/external/pi-tools-suite/src/dcp/state.ts +158 -580
- package/external/pi-tools-suite/src/dcp/ui.ts +1 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +55 -220
- package/external/pi-tools-suite/src/index.ts +9 -0
- package/external/pi-tools-suite/src/model-tools/index.ts +76 -42
- package/external/pi-tools-suite/src/repo-discovery/index.ts +84 -18
- package/external/pi-tools-suite/src/repo-discovery/native-compact.ts +458 -0
- package/external/pi-tools-suite/src/session-recovery/index.ts +189 -43
- package/external/pi-tools-suite/src/tool-descriptions.ts +43 -38
- package/external/pi-tools-suite/src/truncation-metadata-normalizer/index.ts +17 -0
- package/package.json +6 -6
- package/schemas/pi-tools-suite.json +159 -78
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/auth-scaffold-spec.md +0 -78
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/qa-design.md +0 -223
- package/external/pi-tools-suite/src/dcp/state-persistence.ts +0 -195
- /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-auth.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-flow.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.LICENSE +0 -0
- /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.mjs +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { DcpConfig } from "./config.js"
|
|
2
|
+
import { canonicalMessageHash, copyRawMutationHash } from "./conversation-index.js"
|
|
3
|
+
import { cloneDcpTransactionState } from "./state-transaction.js"
|
|
4
|
+
import type { CompressionBlock, ConversationIndexEntry, DcpState } from "./state.js"
|
|
5
|
+
import { stripStaleDcpMetadataFromMessage, estimateMessageTokens } from "./pruner-metadata.js"
|
|
6
|
+
import { injectMessageIds, stableMessageKeys } from "./pruner-message-ids.js"
|
|
7
|
+
import { applyCompressionBlocks } from "./pruner-compression-blocks.js"
|
|
8
|
+
|
|
9
|
+
/** The latest provider projection is runtime-only and intentionally never persisted. */
|
|
10
|
+
const projectionSnapshots = new WeakMap<ConversationIndexEntry[], any[]>()
|
|
11
|
+
|
|
12
|
+
const DCP_PROVENANCE_KEYS = ["_dcpOrigin", "_dcpStableId", "_dcpBlockId"] as const
|
|
13
|
+
|
|
14
|
+
function copyDcpProvenance(source: any, target: any): any {
|
|
15
|
+
if (!source || !target || typeof source !== "object" || typeof target !== "object") return target
|
|
16
|
+
for (const key of DCP_PROVENANCE_KEYS) {
|
|
17
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key)
|
|
18
|
+
if (descriptor) Object.defineProperty(target, key, descriptor)
|
|
19
|
+
}
|
|
20
|
+
copyRawMutationHash(source, target)
|
|
21
|
+
return target
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Clone message objects while retaining the non-enumerable DCP provenance used by exact spans. */
|
|
25
|
+
export function cloneProjectionMessages(messages: readonly any[]): any[] {
|
|
26
|
+
return messages.map((message) => {
|
|
27
|
+
const clone = message && typeof message === "object" ? { ...message } : message
|
|
28
|
+
if (!clone || typeof clone !== "object") return clone
|
|
29
|
+
if (message.content && typeof message.content === "object") clone.content = structuredClone(message.content)
|
|
30
|
+
return copyDcpProvenance(message, clone)
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Store a detached copy of the exact provider projection that produced this index. */
|
|
35
|
+
export function recordCompressionProjection(
|
|
36
|
+
entries: ConversationIndexEntry[],
|
|
37
|
+
messages: readonly any[],
|
|
38
|
+
): void {
|
|
39
|
+
projectionSnapshots.set(entries, cloneProjectionMessages(messages))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function verifiedSnapshot(state: DcpState): any[] {
|
|
43
|
+
const snapshot = projectionSnapshots.get(state.conversationIndexSnapshot)
|
|
44
|
+
if (!snapshot || snapshot.length !== state.conversationIndexSnapshot.length) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"Manual compression requires a current verifiable provider projection; refresh the DCP context and retry.",
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
const stableKeys = stableMessageKeys(snapshot)
|
|
50
|
+
for (let index = 0; index < snapshot.length; index++) {
|
|
51
|
+
const entry = state.conversationIndexSnapshot[index]
|
|
52
|
+
if (!entry || entry.stableId !== stableKeys[index] || entry.contentHash !== canonicalMessageHash(snapshot[index])) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
"Manual compression provider projection no longer matches the current DCP snapshot; refresh the context and retry.",
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return snapshot
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function stripProjectionMetadata(message: any): any {
|
|
62
|
+
const stripped = stripStaleDcpMetadataFromMessage(message)
|
|
63
|
+
return copyDcpProvenance(message, stripped)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ManualCompressionProjection {
|
|
67
|
+
projectedBeforeTokens: number
|
|
68
|
+
projectedAfterTokens: number
|
|
69
|
+
netGain: number
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Materialize only an operation's new blocks against the exact current
|
|
74
|
+
* provider projection. Existing blocks are already represented there as
|
|
75
|
+
* synthetic entries, so replaying them would double-count and hide a bad
|
|
76
|
+
* manual summary behind unrelated automatic pruning.
|
|
77
|
+
*/
|
|
78
|
+
export function previewManualCompressionProjection(
|
|
79
|
+
state: DcpState,
|
|
80
|
+
config: DcpConfig,
|
|
81
|
+
newBlocks: CompressionBlock[],
|
|
82
|
+
): ManualCompressionProjection {
|
|
83
|
+
const source = verifiedSnapshot(state)
|
|
84
|
+
const before = cloneProjectionMessages(source)
|
|
85
|
+
const after = cloneProjectionMessages(source).map(stripProjectionMetadata)
|
|
86
|
+
const previewState = cloneDcpTransactionState(state)
|
|
87
|
+
previewState.compressionBlocks = newBlocks.map((block) => structuredClone(block))
|
|
88
|
+
previewState.accountedCompressionBlockIds = new Set()
|
|
89
|
+
previewState.compressionTokenSavings = new Map()
|
|
90
|
+
|
|
91
|
+
applyCompressionBlocks(after, previewState)
|
|
92
|
+
const appliedBlockIds = new Set(
|
|
93
|
+
after.flatMap((message) => Number.isInteger(message?._dcpBlockId) ? [message._dcpBlockId as number] : []),
|
|
94
|
+
)
|
|
95
|
+
const missing = newBlocks.filter((block) => !appliedBlockIds.has(block.id))
|
|
96
|
+
if (missing.length > 0) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Manual compression could not materialize ${missing.map((block) => `b${block.id}`).join(", ")} in the current provider projection; no state was published.`,
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Recreate carrier overhead on a detached state. This deliberately happens
|
|
103
|
+
// after applying the wrapper so the comparison includes the full delivered
|
|
104
|
+
// provider projection rather than just summary text.
|
|
105
|
+
injectMessageIds(after, previewState, { config })
|
|
106
|
+
const projectedBeforeTokens = before.reduce((sum, message) => sum + estimateMessageTokens(message), 0)
|
|
107
|
+
const projectedAfterTokens = after.reduce((sum, message) => sum + estimateMessageTokens(message), 0)
|
|
108
|
+
return {
|
|
109
|
+
projectedBeforeTokens,
|
|
110
|
+
projectedAfterTokens,
|
|
111
|
+
netGain: projectedBeforeTokens - projectedAfterTokens,
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { DcpState } from "./state.js"
|
|
2
|
+
|
|
3
|
+
/** Routine recovery aims for up to five percentage points, never below min. */
|
|
4
|
+
export function routineRecoveryTokens(tokens: number, window: number, minPercent: number): number {
|
|
5
|
+
return Math.max(1, Math.ceil(Math.min(window * 0.05, Math.max(0, tokens - window * minPercent))))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface CompressionProgressInput {
|
|
9
|
+
projectedTokens: number
|
|
10
|
+
contextWindow: number
|
|
11
|
+
requiredTokens: number
|
|
12
|
+
kind: "routine" | "emergency"
|
|
13
|
+
observedTokens?: number
|
|
14
|
+
targetHeadroomTokens?: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Remaining debt follows new content/usage, not a stale pre-compression sample. */
|
|
18
|
+
export function outstandingCompressionTokens(state: DcpState, input: CompressionProgressInput): number | undefined {
|
|
19
|
+
const previous = state.compressionProgress
|
|
20
|
+
if (!previous || previous.contextWindow !== input.contextWindow) return undefined
|
|
21
|
+
const projectionChange = input.projectedTokens - previous.projectedTokens
|
|
22
|
+
const observedGrowth = input.observedTokens !== undefined && previous.observedTokens !== undefined
|
|
23
|
+
? Math.max(0, input.observedTokens - previous.observedTokens) : 0
|
|
24
|
+
const growth = observedGrowth > 0 ? Math.max(projectionChange, observedGrowth) : projectionChange
|
|
25
|
+
const stricterTarget = previous.kind === input.kind && previous.targetHeadroomTokens !== undefined && input.targetHeadroomTokens !== undefined
|
|
26
|
+
? Math.max(0, previous.targetHeadroomTokens - input.targetHeadroomTokens) : 0
|
|
27
|
+
return Math.max(0, previous.remainingTokens + growth + stricterTarget)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Follow actual projection growth, not context callback/retry count. */
|
|
31
|
+
export function trackCompressionProgress(
|
|
32
|
+
state: DcpState,
|
|
33
|
+
input: CompressionProgressInput,
|
|
34
|
+
): void {
|
|
35
|
+
const previous = state.compressionProgress
|
|
36
|
+
const remaining = outstandingCompressionTokens(state, input)
|
|
37
|
+
state.compressionProgress = {
|
|
38
|
+
projectedTokens: input.projectedTokens,
|
|
39
|
+
contextWindow: input.contextWindow,
|
|
40
|
+
// The unchanged native sample still describes the input before a manual
|
|
41
|
+
// commit. Do not charge the same already-recovered tokens on every callback.
|
|
42
|
+
remainingTokens: previous && previous.kind === input.kind && remaining !== undefined && remaining > 0
|
|
43
|
+
? remaining : Math.max(1, input.requiredTokens, remaining ?? 0),
|
|
44
|
+
kind: input.kind,
|
|
45
|
+
observedTokens: input.observedTokens,
|
|
46
|
+
targetHeadroomTokens: previous?.kind === input.kind && previous.targetHeadroomTokens !== undefined && input.targetHeadroomTokens !== undefined
|
|
47
|
+
? Math.min(previous.targetHeadroomTokens, input.targetHeadroomTokens) : input.targetHeadroomTokens,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function resetCompressionProgress(state: DcpState): void {
|
|
52
|
+
state.consecutiveIgnoredStrongNudges = 0
|
|
53
|
+
state.consecutiveIgnoredNudges = 0
|
|
54
|
+
state.compressionProgress = undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Called on a detached state only after positive full-projection gain is proved. */
|
|
58
|
+
export function settleCompressionProgress(state: DcpState, gain: number, projectedAfterTokens: number): boolean {
|
|
59
|
+
const goal = state.compressionProgress
|
|
60
|
+
if (!goal || gain >= goal.remainingTokens) {
|
|
61
|
+
resetCompressionProgress(state)
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
state.compressionProgress = {
|
|
65
|
+
...goal,
|
|
66
|
+
remainingTokens: goal.remainingTokens - gain,
|
|
67
|
+
projectedTokens: projectedAfterTokens,
|
|
68
|
+
}
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
@@ -16,7 +16,6 @@ export interface DcpConfig {
|
|
|
16
16
|
}
|
|
17
17
|
manualMode: {
|
|
18
18
|
enabled: boolean
|
|
19
|
-
automaticStrategies: boolean // run dedup/purge even in manual mode
|
|
20
19
|
}
|
|
21
20
|
compress: {
|
|
22
21
|
maxContextPercent: number | string // accepts a 0-1 fraction, absolute tokens, or a percent string like "80%"
|
|
@@ -50,15 +49,16 @@ export interface DcpConfig {
|
|
|
50
49
|
maxSuggestions: number
|
|
51
50
|
}
|
|
52
51
|
/**
|
|
53
|
-
* Auto-compress fallback:
|
|
54
|
-
*
|
|
55
|
-
*
|
|
52
|
+
* Auto-compress fallback: after completed actionable provider opportunities
|
|
53
|
+
* fail to meet the recovery goal, DCP can create a safe compression block,
|
|
54
|
+
* including after routine-reminder escalation. Lossy within a
|
|
56
55
|
* session — disabled by default; opt in via config.
|
|
57
56
|
*/
|
|
58
57
|
autoCompress: {
|
|
59
58
|
enabled: boolean
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
59
|
+
/** Auto fallback is eligible after more than this many completed,
|
|
60
|
+
* correlated opportunities with a delivered actionable reminder.
|
|
61
|
+
* Failed calls and insufficient commits do not reset patience. */
|
|
62
62
|
patience: number
|
|
63
63
|
/** Models to try, in order, when producing a model-generated summary.
|
|
64
64
|
* Empty array → deterministic programmatic digest (no model call). */
|
|
@@ -68,23 +68,6 @@ export interface DcpConfig {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
strategies: {
|
|
71
|
-
deduplication: {
|
|
72
|
-
enabled: boolean
|
|
73
|
-
protectedTools: string[]
|
|
74
|
-
}
|
|
75
|
-
purgeErrors: {
|
|
76
|
-
enabled: boolean
|
|
77
|
-
turns: number // prune error inputs after N user turns (default: 4)
|
|
78
|
-
protectedTools: string[]
|
|
79
|
-
}
|
|
80
|
-
autoToolPruning: {
|
|
81
|
-
enabled: boolean
|
|
82
|
-
maxOutputTokens: number
|
|
83
|
-
keepRecentTurns: number
|
|
84
|
-
readLikeTools: string[]
|
|
85
|
-
readLikeTurns: number
|
|
86
|
-
protectedTools: string[]
|
|
87
|
-
}
|
|
88
71
|
emergencyCurrentTurnPruning: {
|
|
89
72
|
/** Enable same-turn candidates and lossy fallback pruning; emergency reminders remain active. */
|
|
90
73
|
enabled: boolean
|
|
@@ -104,7 +87,6 @@ export interface DcpConfig {
|
|
|
104
87
|
}
|
|
105
88
|
}
|
|
106
89
|
protectedFilePatterns: string[]
|
|
107
|
-
pruneNotification: "off" | "minimal" | "detailed"
|
|
108
90
|
modelOverrides: Record<string, DcpConfigOverride>
|
|
109
91
|
}
|
|
110
92
|
|
|
@@ -125,7 +107,6 @@ const DEFAULT_CONFIG: DcpConfig = {
|
|
|
125
107
|
debug: false,
|
|
126
108
|
manualMode: {
|
|
127
109
|
enabled: false,
|
|
128
|
-
automaticStrategies: true,
|
|
129
110
|
},
|
|
130
111
|
compress: {
|
|
131
112
|
maxContextPercent: 0.65,
|
|
@@ -162,39 +143,6 @@ const DEFAULT_CONFIG: DcpConfig = {
|
|
|
162
143
|
},
|
|
163
144
|
},
|
|
164
145
|
strategies: {
|
|
165
|
-
deduplication: {
|
|
166
|
-
enabled: true,
|
|
167
|
-
protectedTools: [],
|
|
168
|
-
},
|
|
169
|
-
purgeErrors: {
|
|
170
|
-
enabled: true,
|
|
171
|
-
turns: 4,
|
|
172
|
-
protectedTools: [],
|
|
173
|
-
},
|
|
174
|
-
autoToolPruning: {
|
|
175
|
-
enabled: true,
|
|
176
|
-
maxOutputTokens: 1200,
|
|
177
|
-
keepRecentTurns: 1,
|
|
178
|
-
readLikeTools: [
|
|
179
|
-
"read",
|
|
180
|
-
"shell",
|
|
181
|
-
"bash",
|
|
182
|
-
"grep",
|
|
183
|
-
"find",
|
|
184
|
-
"ls",
|
|
185
|
-
"web_search",
|
|
186
|
-
"web_fetch",
|
|
187
|
-
"repo_architecture",
|
|
188
|
-
"repo_structure",
|
|
189
|
-
"repo_ast",
|
|
190
|
-
"repo_search",
|
|
191
|
-
"repo_explain",
|
|
192
|
-
"repo_deps",
|
|
193
|
-
"ast_grep",
|
|
194
|
-
],
|
|
195
|
-
readLikeTurns: 3,
|
|
196
|
-
protectedTools: [],
|
|
197
|
-
},
|
|
198
146
|
emergencyCurrentTurnPruning: {
|
|
199
147
|
enabled: true,
|
|
200
148
|
hardContextPercent: 0.82,
|
|
@@ -207,7 +155,6 @@ const DEFAULT_CONFIG: DcpConfig = {
|
|
|
207
155
|
},
|
|
208
156
|
},
|
|
209
157
|
protectedFilePatterns: [],
|
|
210
|
-
pruneNotification: "detailed",
|
|
211
158
|
modelOverrides: {},
|
|
212
159
|
}
|
|
213
160
|
|
|
@@ -285,7 +232,35 @@ function readDcpFromSuiteConfig(filePath: string): Record<string, unknown> {
|
|
|
285
232
|
const raw = readJsoncFile(filePath)
|
|
286
233
|
const dcp = raw["dcp"]
|
|
287
234
|
if (dcp === null || typeof dcp !== "object" || Array.isArray(dcp)) return {}
|
|
288
|
-
return dcp as Record<string, unknown>
|
|
235
|
+
return stripRemovedDcpKeys(dcp as Record<string, unknown>)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function stripRemovedDcpKeys(raw: Record<string, unknown>): Record<string, unknown> {
|
|
239
|
+
const cleaned = structuredClone(raw)
|
|
240
|
+
delete cleaned.pruneNotification
|
|
241
|
+
|
|
242
|
+
const manualMode = cleaned.manualMode
|
|
243
|
+
if (manualMode && typeof manualMode === "object" && !Array.isArray(manualMode)) {
|
|
244
|
+
delete (manualMode as Record<string, unknown>).automaticStrategies
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const strategies = cleaned.strategies
|
|
248
|
+
if (strategies && typeof strategies === "object" && !Array.isArray(strategies)) {
|
|
249
|
+
const record = strategies as Record<string, unknown>
|
|
250
|
+
delete record.deduplication
|
|
251
|
+
delete record.purgeErrors
|
|
252
|
+
delete record.autoToolPruning
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const modelOverrides = cleaned.modelOverrides
|
|
256
|
+
if (modelOverrides && typeof modelOverrides === "object" && !Array.isArray(modelOverrides)) {
|
|
257
|
+
for (const [key, override] of Object.entries(modelOverrides as Record<string, unknown>)) {
|
|
258
|
+
if (!override || typeof override !== "object" || Array.isArray(override)) continue
|
|
259
|
+
;(modelOverrides as Record<string, unknown>)[key] = stripRemovedDcpKeys(override as Record<string, unknown>)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return cleaned
|
|
289
264
|
}
|
|
290
265
|
|
|
291
266
|
function mergeSuiteDcpConfig(config: DcpConfig, filePath: string): DcpConfig {
|
|
@@ -431,7 +406,7 @@ export interface LoadConfigOptions {
|
|
|
431
406
|
*/
|
|
432
407
|
export function loadConfig(options: LoadConfigOptions = {}): DcpConfig {
|
|
433
408
|
// Layer 1: defaults (deep clone so we never mutate the constant)
|
|
434
|
-
let config: DcpConfig =
|
|
409
|
+
let config: DcpConfig = structuredClone(DEFAULT_CONFIG)
|
|
435
410
|
|
|
436
411
|
const homeDir = options.homeDir ?? os.homedir()
|
|
437
412
|
config = mergeSuiteDcpConfig(config, path.join(homeDir, ".config", "pi", "pi-tools-suite.jsonc"))
|