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,127 @@
|
|
|
1
|
+
import type { DcpConfig } from "./config.js"
|
|
2
|
+
import { applyPruning, detectCompressionCandidate, detectEmergencyCompressionCandidate, detectMessageCompressionCandidates, getActiveSummaryTokenEstimate, resolveContextThresholds } from "./pruner.js"
|
|
3
|
+
import { estimateMessageTokens } from "./pruner-metadata.js"
|
|
4
|
+
import type { CompressionCandidate, MessageCompressionCandidate } from "./pruner-types.js"
|
|
5
|
+
import { planDcpBudget, type DcpBudgetPlan } from "./progress-controller.js"
|
|
6
|
+
import type { DcpState } from "./state.js"
|
|
7
|
+
|
|
8
|
+
export interface DcpShadowPlanInput {
|
|
9
|
+
messages: any[]
|
|
10
|
+
state: DcpState
|
|
11
|
+
config: DcpConfig
|
|
12
|
+
contextWindow: number
|
|
13
|
+
providerUsageTokens?: number | null
|
|
14
|
+
reservedOutputTokens?: number
|
|
15
|
+
reservedToolTokens?: number
|
|
16
|
+
modelKeys?: string[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DcpShadowPlanResult {
|
|
20
|
+
projectedTokens: number
|
|
21
|
+
contextPercent: number
|
|
22
|
+
budget: DcpBudgetPlan
|
|
23
|
+
routineCandidate: CompressionCandidate | null
|
|
24
|
+
emergencyCandidate: CompressionCandidate | null
|
|
25
|
+
messageCandidates: MessageCompressionCandidate[]
|
|
26
|
+
projectedMessageCount: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function cloneDcpState(state: DcpState): DcpState {
|
|
30
|
+
return {
|
|
31
|
+
...state,
|
|
32
|
+
toolCalls: new Map([...state.toolCalls].map(([id, record]) => [id, {
|
|
33
|
+
...record,
|
|
34
|
+
inputArgs: { ...(record.inputArgs ?? {}) },
|
|
35
|
+
}])),
|
|
36
|
+
prunedToolIds: new Set(state.prunedToolIds),
|
|
37
|
+
prunedToolReasons: new Map(state.prunedToolReasons),
|
|
38
|
+
providerSeenToolIds: new Set(state.providerSeenToolIds),
|
|
39
|
+
compressionBlocks: state.compressionBlocks.map((block) => ({
|
|
40
|
+
...block,
|
|
41
|
+
coveredBlockIds: block.coveredBlockIds ? [...block.coveredBlockIds] : undefined,
|
|
42
|
+
protectedFragments: block.protectedFragments?.map((fragment) => ({ ...fragment })),
|
|
43
|
+
sourceCoverage: block.sourceCoverage ? { ...block.sourceCoverage } : undefined,
|
|
44
|
+
})),
|
|
45
|
+
messageIdSnapshot: new Map(state.messageIdSnapshot),
|
|
46
|
+
messageMetaSnapshot: new Map([...state.messageMetaSnapshot].map(([id, meta]) => [id, {
|
|
47
|
+
...meta,
|
|
48
|
+
toolCallIds: meta.toolCallIds ? [...meta.toolCallIds] : undefined,
|
|
49
|
+
}])),
|
|
50
|
+
conversationIndexSnapshot: state.conversationIndexSnapshot.map((entry) => ({
|
|
51
|
+
...entry,
|
|
52
|
+
toolCallIds: entry.toolCallIds ? [...entry.toolCallIds] : undefined,
|
|
53
|
+
})),
|
|
54
|
+
messageIdsByStableId: new Map(state.messageIdsByStableId),
|
|
55
|
+
accountedCompressionBlockIds: new Set(state.accountedCompressionBlockIds),
|
|
56
|
+
compressionTokenSavings: new Map(state.compressionTokenSavings),
|
|
57
|
+
accountedPrunedToolIds: new Set(state.accountedPrunedToolIds),
|
|
58
|
+
nudgeAnchors: state.nudgeAnchors.map((anchor) => ({ ...anchor })),
|
|
59
|
+
lastNudge: state.lastNudge ? { ...state.lastNudge } : undefined,
|
|
60
|
+
progressRecovery: state.progressRecovery ? { ...state.progressRecovery } : undefined,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* E10 dry-run planner. All DCP transforms and candidate discovery run against a
|
|
66
|
+
* detached state clone; the supplied live state is never published, persisted,
|
|
67
|
+
* or passed to a model. This is intended for rollout diagnostics/shadow checks.
|
|
68
|
+
*/
|
|
69
|
+
export function planDcpShadow(input: DcpShadowPlanInput): DcpShadowPlanResult {
|
|
70
|
+
const shadowState = cloneDcpState(input.state)
|
|
71
|
+
const projected = applyPruning(input.messages, shadowState, input.config)
|
|
72
|
+
const projectedTokens = projected.reduce((sum, message) => sum + estimateMessageTokens(message), 0)
|
|
73
|
+
const contextWindow = Math.max(1, Math.floor(input.contextWindow))
|
|
74
|
+
const emergency = input.config.strategies.emergencyCurrentTurnPruning
|
|
75
|
+
const thresholds = resolveContextThresholds(input.config, input.modelKeys ?? [], contextWindow)
|
|
76
|
+
const budget = planDcpBudget({
|
|
77
|
+
providerUsageTokens: input.providerUsageTokens,
|
|
78
|
+
repoProjectedTokens: projectedTokens,
|
|
79
|
+
contextWindow,
|
|
80
|
+
reservedOutputTokens: input.reservedOutputTokens ?? 0,
|
|
81
|
+
reservedToolTokens: input.reservedToolTokens ?? 0,
|
|
82
|
+
maxContextPercent: thresholds.maxContextPercent,
|
|
83
|
+
hardContextPercent: emergency.hardContextPercent,
|
|
84
|
+
targetContextPercent: Math.min(
|
|
85
|
+
emergency.targetContextPercent,
|
|
86
|
+
Math.max(0, thresholds.maxContextPercent * 0.9),
|
|
87
|
+
),
|
|
88
|
+
summaryBufferEnabled: input.config.compress.summaryBuffer,
|
|
89
|
+
activeSummaryTokens: getActiveSummaryTokenEstimate(shadowState),
|
|
90
|
+
estimatorMarginTokens: Math.max(256, Math.ceil(contextWindow * 0.0025)),
|
|
91
|
+
})
|
|
92
|
+
const contextPercent = budget.projectedBeforeTokens / contextWindow
|
|
93
|
+
const recovery = budget.pressured ? { requiredSavingsTokens: budget.requiredSavingsTokens } : undefined
|
|
94
|
+
const routineCandidate = detectCompressionCandidate(
|
|
95
|
+
projected,
|
|
96
|
+
shadowState,
|
|
97
|
+
input.config,
|
|
98
|
+
contextPercent,
|
|
99
|
+
recovery,
|
|
100
|
+
)
|
|
101
|
+
const emergencyCandidate = routineCandidate === null && budget.pressured
|
|
102
|
+
? detectEmergencyCompressionCandidate(
|
|
103
|
+
projected,
|
|
104
|
+
shadowState,
|
|
105
|
+
input.config,
|
|
106
|
+
contextPercent,
|
|
107
|
+
budget.softHeadroomTokens / contextWindow,
|
|
108
|
+
recovery,
|
|
109
|
+
)
|
|
110
|
+
: null
|
|
111
|
+
const messageCandidates = detectMessageCompressionCandidates(
|
|
112
|
+
projected,
|
|
113
|
+
shadowState,
|
|
114
|
+
input.config,
|
|
115
|
+
contextPercent,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
projectedTokens,
|
|
120
|
+
contextPercent,
|
|
121
|
+
budget,
|
|
122
|
+
routineCandidate,
|
|
123
|
+
emergencyCandidate,
|
|
124
|
+
messageCandidates,
|
|
125
|
+
projectedMessageCount: projected.length,
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { DcpState } from "./state.js"
|
|
2
|
+
import { createHash } from "node:crypto"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Serialize all stateful DCP publications which share one live state object.
|
|
6
|
+
*
|
|
7
|
+
* Persistence has its own per-path queue, but that queue cannot protect the
|
|
8
|
+
* read/plan/publish interval: two callers can otherwise both clone `nextBlockId
|
|
9
|
+
* === 1`, persist independent snapshots, and both report success for b1. This
|
|
10
|
+
* queue deliberately spans preparation, durable publication, and the final
|
|
11
|
+
* in-memory commit.
|
|
12
|
+
*/
|
|
13
|
+
const transactionTails = new WeakMap<DcpState, Promise<void>>()
|
|
14
|
+
|
|
15
|
+
export async function runDcpStateTransaction<T>(
|
|
16
|
+
state: DcpState,
|
|
17
|
+
operation: () => Promise<T> | T,
|
|
18
|
+
): Promise<T> {
|
|
19
|
+
const previous = transactionTails.get(state) ?? Promise.resolve()
|
|
20
|
+
let release!: () => void
|
|
21
|
+
const current = new Promise<void>((resolve) => {
|
|
22
|
+
release = resolve
|
|
23
|
+
})
|
|
24
|
+
const tail = previous.catch(() => undefined).then(() => current)
|
|
25
|
+
transactionTails.set(state, tail)
|
|
26
|
+
|
|
27
|
+
await previous.catch(() => undefined)
|
|
28
|
+
try {
|
|
29
|
+
return await operation()
|
|
30
|
+
} finally {
|
|
31
|
+
release()
|
|
32
|
+
if (transactionTails.get(state) === tail) transactionTails.delete(state)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Runtime ownership changes invalidate any detached compression plan. */
|
|
37
|
+
export function invalidateDcpStateOwner(state: DcpState): number {
|
|
38
|
+
state.sessionEpoch = Math.max(1, Math.floor(state.sessionEpoch || 0) + 1)
|
|
39
|
+
return state.sessionEpoch
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function cloneDcpTransactionState(state: DcpState): DcpState {
|
|
43
|
+
return structuredClone(state)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function canonicalRuntimeValue(value: unknown, seen = new WeakSet<object>()): unknown {
|
|
47
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value
|
|
48
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : String(value)
|
|
49
|
+
if (typeof value === "bigint") return `${value}n`
|
|
50
|
+
if (typeof value === "undefined") return "[undefined]"
|
|
51
|
+
if (Array.isArray(value)) return value.map((item) => canonicalRuntimeValue(item, seen))
|
|
52
|
+
if (value instanceof Map) {
|
|
53
|
+
return [...value.entries()]
|
|
54
|
+
.map(([key, item]) => [canonicalRuntimeValue(key, seen), canonicalRuntimeValue(item, seen)] as const)
|
|
55
|
+
.sort(([a], [b]) => JSON.stringify(a).localeCompare(JSON.stringify(b)))
|
|
56
|
+
}
|
|
57
|
+
if (value instanceof Set) {
|
|
58
|
+
return [...value.values()]
|
|
59
|
+
.map((item) => canonicalRuntimeValue(item, seen))
|
|
60
|
+
.sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)))
|
|
61
|
+
}
|
|
62
|
+
if (typeof value === "object") {
|
|
63
|
+
if (seen.has(value as object)) return "[cycle]"
|
|
64
|
+
seen.add(value as object)
|
|
65
|
+
const record = value as Record<string, unknown>
|
|
66
|
+
const result: Record<string, unknown> = {}
|
|
67
|
+
for (const key of Object.keys(record).sort()) result[key] = canonicalRuntimeValue(record[key], seen)
|
|
68
|
+
seen.delete(value as object)
|
|
69
|
+
return result
|
|
70
|
+
}
|
|
71
|
+
return String(value)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function transactionRevision(state: DcpState): string {
|
|
75
|
+
return createHash("sha256").update(JSON.stringify(canonicalRuntimeValue(state))).digest("hex")
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Capture ownership before queuing, never after a long await. */
|
|
79
|
+
export function captureDcpTransactionGuard(
|
|
80
|
+
state: DcpState,
|
|
81
|
+
config: unknown,
|
|
82
|
+
signal?: AbortSignal,
|
|
83
|
+
context?: any,
|
|
84
|
+
): () => void {
|
|
85
|
+
const epoch = state.sessionEpoch
|
|
86
|
+
const revision = transactionRevision(state)
|
|
87
|
+
const configRevision = JSON.stringify(config)
|
|
88
|
+
const contextRevision = () => JSON.stringify({
|
|
89
|
+
session: context?.sessionManager?.getSessionId?.(),
|
|
90
|
+
branch: context?.sessionManager?.getBranch?.(),
|
|
91
|
+
model: context?.model,
|
|
92
|
+
cwd: context?.cwd,
|
|
93
|
+
})
|
|
94
|
+
const owner = contextRevision()
|
|
95
|
+
return () => {
|
|
96
|
+
signal?.throwIfAborted()
|
|
97
|
+
if (state.sessionEpoch !== epoch || transactionRevision(state) !== revision ||
|
|
98
|
+
JSON.stringify(config) !== configRevision || contextRevision() !== owner) {
|
|
99
|
+
throw new Error("stale_plan: DCP session, branch, model, configuration or source revision changed before publication")
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|