@cydm/pie 2.6.12 → 2.7.1
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 +85 -3
- package/dist/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/plan-mode/index.js +130 -21
- package/dist/builtin/extensions/subagent/index.js +15 -6
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/computer-use-axi/SKILL.md +172 -0
- package/dist/builtin/{extensions/computer-use/index.js → skills/computer-use-axi/computer-use-axi-broker.js} +2122 -708
- package/dist/builtin/skills/computer-use-axi/computer-use-axi-cli.js +37 -0
- package/dist/builtin/skills/computer-use-axi/computer-use-axi-runtime.js +728 -0
- package/dist/builtin/skills/computer-use-axi/package.json +11 -0
- package/dist/chunks/{chunk-PPEWRUMQ.js → chunk-M44CWVDZ.js} +1249 -752
- package/dist/chunks/{chunk-HHNOENEH.js → chunk-NJFPBU36.js} +14 -1
- package/dist/chunks/{chunk-AAEBH6KX.js → chunk-W74NRSRV.js} +239 -231
- package/dist/chunks/{chunk-7B4IIBVS.js → chunk-XUROMYTT.js} +1747 -14
- package/dist/chunks/{src-OWQI5M6W.js → src-C4KA4G75.js} +2 -2
- package/dist/chunks/{test-stream-Y7WXELAJ.js → test-stream-A5ZELKNG.js} +1 -1
- package/dist/cli.js +863 -305
- package/models.schema.json +57 -0
- package/package.json +3 -3
- package/dist/builtin/extensions/computer-use/package.json +0 -14
- package/dist/builtin/extensions/computer-use/scripts/build-native.mjs +0 -278
- package/dist/builtin/extensions/computer-use/scripts/test-native-retention.mjs +0 -204
- package/dist/chunks/chunk-5353DEEC.js +0 -130
- package/dist/chunks/webapi-MBCKO7ZV.js +0 -2481
- package/dist/code-intel-worker.cjs +0 -211227
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/linux/arm64/linux-bridge +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/linux/x64/linux-bridge +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/arm64/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/Info.plist +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/_CodeSignature/CodeResources +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/x64/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/windows/windows-bridge.exe +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/scripts/helper-path.mjs +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/scripts/setup-helper.mjs +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
+
VERSION,
|
|
4
5
|
cleanupBashOutputArtifacts,
|
|
5
6
|
createBashTool,
|
|
6
7
|
createCliHostCapabilities,
|
|
7
8
|
createCliWebResearchHealthStore,
|
|
9
|
+
createTraceTransportSink,
|
|
10
|
+
createTransportDiagnosticsStreamFn,
|
|
8
11
|
formatSize,
|
|
12
|
+
getAgentDir,
|
|
13
|
+
getBuiltinDir,
|
|
14
|
+
getConfigDir,
|
|
15
|
+
getCustomThemesDir,
|
|
16
|
+
getLogsDir,
|
|
17
|
+
getPackageDir,
|
|
18
|
+
getProjectSettingsPath,
|
|
19
|
+
getRuntimeLogPath,
|
|
20
|
+
getSessionsDir,
|
|
21
|
+
getSettingsPath,
|
|
22
|
+
getThemesDir,
|
|
23
|
+
logTransportLifecycle,
|
|
24
|
+
migrateConfigFromAgentDir,
|
|
9
25
|
truncateHeadTail
|
|
10
|
-
} from "./chunks/chunk-
|
|
26
|
+
} from "./chunks/chunk-W74NRSRV.js";
|
|
27
|
+
import {
|
|
28
|
+
resolveCliProjectRoot
|
|
29
|
+
} from "./chunks/chunk-WLFOBECN.js";
|
|
11
30
|
import {
|
|
12
31
|
AGENTS_CONTEXT_FILE_NAME,
|
|
13
32
|
AgentSessionController,
|
|
14
33
|
AttentionCoordinator,
|
|
15
34
|
BUILTIN_TOOL_CAPABILITY_METADATA,
|
|
35
|
+
DEFAULT_COMPACTION_CONFIG,
|
|
16
36
|
ExtensionResourceScope,
|
|
17
37
|
FileSessionStore,
|
|
18
38
|
SessionTraceSnapshotWriter,
|
|
@@ -30,6 +50,7 @@ import {
|
|
|
30
50
|
createFileObservationState,
|
|
31
51
|
createPolicyEnforcedTools,
|
|
32
52
|
createReadFileUnderstandingHandler,
|
|
53
|
+
createSearchContextTool,
|
|
33
54
|
createSessionManager,
|
|
34
55
|
createSharedFileSystemTools,
|
|
35
56
|
createSharedWebSearchTool,
|
|
@@ -51,20 +72,22 @@ import {
|
|
|
51
72
|
interactionAttentionResolution,
|
|
52
73
|
isCompactSummaryMessage,
|
|
53
74
|
isExtensionEnabled,
|
|
75
|
+
isToolAllowedInPlanMode,
|
|
54
76
|
maybeAdvanceTodoExecutionState,
|
|
55
77
|
modalityForReadFileUnderstandingKind,
|
|
56
78
|
pauseExecutionState,
|
|
79
|
+
prepareSessionCompaction,
|
|
57
80
|
registerInteractionHandler,
|
|
58
81
|
requestInteraction,
|
|
59
82
|
resolveExtensionIdentity,
|
|
60
83
|
restoreExecutionState,
|
|
61
|
-
selectToolsForRuntimePolicy,
|
|
62
84
|
setEnablementInMap,
|
|
63
85
|
setExtensionEnabledInSettings,
|
|
64
86
|
shouldPreserveExecutionStateForUserText,
|
|
65
|
-
supersedeExecutionState
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
supersedeExecutionState,
|
|
88
|
+
verifyPreparedCompactionCommit
|
|
89
|
+
} from "./chunks/chunk-M44CWVDZ.js";
|
|
90
|
+
import "./chunks/chunk-NJFPBU36.js";
|
|
68
91
|
import {
|
|
69
92
|
Deref,
|
|
70
93
|
EMPTY_ASSISTANT_CONTENT_ERROR,
|
|
@@ -87,26 +110,9 @@ import {
|
|
|
87
110
|
requiredCapabilityForToolPurpose,
|
|
88
111
|
setLogger,
|
|
89
112
|
sortToolModelCandidatesByCapability,
|
|
113
|
+
streamSimple,
|
|
90
114
|
type_exports
|
|
91
|
-
} from "./chunks/chunk-
|
|
92
|
-
import {
|
|
93
|
-
VERSION,
|
|
94
|
-
getAgentDir,
|
|
95
|
-
getBuiltinDir,
|
|
96
|
-
getConfigDir,
|
|
97
|
-
getCustomThemesDir,
|
|
98
|
-
getLogsDir,
|
|
99
|
-
getPackageDir,
|
|
100
|
-
getProjectSettingsPath,
|
|
101
|
-
getRuntimeLogPath,
|
|
102
|
-
getSessionsDir,
|
|
103
|
-
getSettingsPath,
|
|
104
|
-
getThemesDir,
|
|
105
|
-
migrateConfigFromAgentDir
|
|
106
|
-
} from "./chunks/chunk-5353DEEC.js";
|
|
107
|
-
import {
|
|
108
|
-
resolveCliProjectRoot
|
|
109
|
-
} from "./chunks/chunk-WLFOBECN.js";
|
|
115
|
+
} from "./chunks/chunk-XUROMYTT.js";
|
|
110
116
|
import {
|
|
111
117
|
IsArray,
|
|
112
118
|
IsBigInt,
|
|
@@ -51971,6 +51977,7 @@ var MODEL_OVERRIDE_KEYS = [
|
|
|
51971
51977
|
"cost",
|
|
51972
51978
|
"contextWindow",
|
|
51973
51979
|
"maxTokens",
|
|
51980
|
+
"transport",
|
|
51974
51981
|
"headers",
|
|
51975
51982
|
"compat",
|
|
51976
51983
|
"cacheCapability",
|
|
@@ -51988,9 +51995,11 @@ function validateExtensionProviderConfig(provider, config) {
|
|
|
51988
51995
|
throw new Error(`registerProvider("${provider}"): baseUrl must be an absolute URL`);
|
|
51989
51996
|
}
|
|
51990
51997
|
assertHeadersShape(config.headers, `registerProvider("${provider}")`);
|
|
51998
|
+
validateTransport(config.transport, `registerProvider("${provider}")`);
|
|
51991
51999
|
for (const model of config.models ?? []) {
|
|
51992
52000
|
if (!model || typeof model.id !== "string" || !model.id.trim() || /\s/.test(model.id)) throw new Error(`registerProvider("${provider}"): invalid model id`);
|
|
51993
52001
|
assertHeadersShape(model.headers, `registerProvider("${provider}") model "${model.id}"`);
|
|
52002
|
+
validateTransport(model.transport, `Model "${model.id}"`);
|
|
51994
52003
|
validateCompat(model.compat, `registerProvider("${provider}") model "${model.id}" compat`);
|
|
51995
52004
|
validateCacheCapability(model.cacheCapability, `registerProvider("${provider}") model "${model.id}" cacheCapability`);
|
|
51996
52005
|
validateWebSearchCapability(model.webSearch, `registerProvider("${provider}") model "${model.id}" webSearch`);
|
|
@@ -51998,7 +52007,7 @@ function validateExtensionProviderConfig(provider, config) {
|
|
|
51998
52007
|
}
|
|
51999
52008
|
}
|
|
52000
52009
|
var REMOTE_CATALOG_CACHE_VERSION = 4;
|
|
52001
|
-
var SUPPORTED_REMOTE_APIS = /* @__PURE__ */ new Set(["openai-completions", "anthropic-messages"]);
|
|
52010
|
+
var SUPPORTED_REMOTE_APIS = /* @__PURE__ */ new Set(["openai-completions", "anthropic-messages", "openai-responses"]);
|
|
52002
52011
|
var MAX_REMOTE_CATALOG_BYTES = 2 * 1024 * 1024;
|
|
52003
52012
|
var OAUTH_RESTORE_LEEWAY_MS = 6e4;
|
|
52004
52013
|
var OAUTH_REFRESH_TIMEOUT_MS = 3e4;
|
|
@@ -52495,11 +52504,17 @@ function validateFileCapabilities(value, label) {
|
|
|
52495
52504
|
}
|
|
52496
52505
|
}
|
|
52497
52506
|
}
|
|
52507
|
+
function validateTransport(value, label) {
|
|
52508
|
+
if (value !== void 0 && value !== "sse" && value !== "websocket" && value !== "auto") throw new Error(`${label}.transport is invalid`);
|
|
52509
|
+
}
|
|
52498
52510
|
function validateCompat(value, label) {
|
|
52499
52511
|
if (value === void 0) return;
|
|
52500
52512
|
if (!isPlainRecord(value)) throw new Error(`${label} is invalid`);
|
|
52501
52513
|
assertOnlyKeys(value, [
|
|
52502
52514
|
"forcedReasoningEffort",
|
|
52515
|
+
"store",
|
|
52516
|
+
"supportsEncryptedReasoning",
|
|
52517
|
+
"responsesContinuation",
|
|
52503
52518
|
"supportsStore",
|
|
52504
52519
|
"supportsDeveloperRole",
|
|
52505
52520
|
"supportsReasoningEffort",
|
|
@@ -52517,6 +52532,9 @@ function validateCompat(value, label) {
|
|
|
52517
52532
|
throw new Error(`${label}.forcedReasoningEffort must be "none"`);
|
|
52518
52533
|
}
|
|
52519
52534
|
for (const field of [
|
|
52535
|
+
"store",
|
|
52536
|
+
"supportsEncryptedReasoning",
|
|
52537
|
+
"responsesContinuation",
|
|
52520
52538
|
"supportsStore",
|
|
52521
52539
|
"supportsDeveloperRole",
|
|
52522
52540
|
"supportsReasoningEffort",
|
|
@@ -52537,12 +52555,14 @@ function validateRemoteModel(profileId, model) {
|
|
|
52537
52555
|
if (!isPlainRecord(model) || typeof model.id !== "string" || !model.id.trim() || model.id !== model.id.trim() || /\s/.test(model.id)) throw new Error(`Remote profile "${profileId}" contains an invalid model id`);
|
|
52538
52556
|
assertOnlyKeys(model, [
|
|
52539
52557
|
"id",
|
|
52558
|
+
"api",
|
|
52540
52559
|
"name",
|
|
52541
52560
|
"reasoning",
|
|
52542
52561
|
"input",
|
|
52543
52562
|
"cost",
|
|
52544
52563
|
"contextWindow",
|
|
52545
52564
|
"maxTokens",
|
|
52565
|
+
"transport",
|
|
52546
52566
|
"compat",
|
|
52547
52567
|
"cacheCapability",
|
|
52548
52568
|
"webSearch",
|
|
@@ -52556,19 +52576,21 @@ function validateRemoteModel(profileId, model) {
|
|
|
52556
52576
|
for (const field of ["name", "displayName", "filePlatform", "attachmentPlatform", "apiKeyEnv"]) {
|
|
52557
52577
|
assertOptionalString(model[field], `Remote profile "${profileId}" model "${model.id}" ${field}`);
|
|
52558
52578
|
}
|
|
52579
|
+
if (model.api !== void 0 && !SUPPORTED_REMOTE_APIS.has(model.api)) throw new Error(`Model "${model.id}" has unsupported api ${model.api}`);
|
|
52559
52580
|
assertOptionalBoolean(model.reasoning, `Remote profile "${profileId}" model "${model.id}" reasoning`);
|
|
52560
52581
|
if (!Array.isArray(model.input) || model.input.length === 0 || model.input.some((item) => !["text", "image", "audio", "video"].includes(item))) {
|
|
52561
52582
|
throw new Error(`Remote profile "${profileId}" model "${model.id}" has invalid input capabilities`);
|
|
52562
52583
|
}
|
|
52563
52584
|
if (!isPlainRecord(model.cost)) throw new Error(`Remote profile "${profileId}" model "${model.id}" has invalid cost values`);
|
|
52564
|
-
assertOnlyKeys(model.cost, ["input", "output", "cacheRead", "cacheWrite"], `Remote profile "${profileId}" model "${model.id}" cost`);
|
|
52565
|
-
if ([model.cost.input, model.cost.output, model.cost.cacheRead, model.cost.cacheWrite].some((value) => typeof value !== "number" || !Number.isFinite(value) || value < 0)) {
|
|
52585
|
+
assertOnlyKeys(model.cost, ["input", "output", "cacheRead", "cacheWrite", "cacheWriteLong"], `Remote profile "${profileId}" model "${model.id}" cost`);
|
|
52586
|
+
if ([model.cost.input, model.cost.output, model.cost.cacheRead, model.cost.cacheWrite, model.cost.cacheWriteLong].some((value) => value !== void 0 && (typeof value !== "number" || !Number.isFinite(value) || value < 0))) {
|
|
52566
52587
|
throw new Error(`Remote profile "${profileId}" model "${model.id}" has invalid cost values`);
|
|
52567
52588
|
}
|
|
52568
52589
|
if (!Number.isSafeInteger(model.contextWindow) || Number(model.contextWindow) <= 0 || !Number.isSafeInteger(model.maxTokens) || Number(model.maxTokens) <= 0 || Number(model.maxTokens) > Number(model.contextWindow)) {
|
|
52569
52590
|
throw new Error(`Remote profile "${profileId}" model "${model.id}" has invalid token limits`);
|
|
52570
52591
|
}
|
|
52571
52592
|
if (new Set(model.input).size !== model.input.length) throw new Error(`Remote profile "${profileId}" model "${model.id}" has duplicate input capabilities`);
|
|
52593
|
+
validateTransport(model.transport, `Model "${model.id}"`);
|
|
52572
52594
|
validateCompat(model.compat, `Remote profile "${profileId}" model "${model.id}" compat`);
|
|
52573
52595
|
validateCacheCapability(model.cacheCapability, `Remote profile "${profileId}" model "${model.id}" cacheCapability`);
|
|
52574
52596
|
validateWebSearchCapability(model.webSearch, `Remote profile "${profileId}" model "${model.id}" webSearch`);
|
|
@@ -52604,6 +52626,7 @@ function sanitizeRemotePayload(decoded, remote, catalogUrl, allowLocallyInjected
|
|
|
52604
52626
|
if (!provider || provider !== provider.trim() || /\s/.test(provider) || !isPlainRecord(source)) throw new Error("catalog contains an invalid profile");
|
|
52605
52627
|
assertOnlyKeys(source, [
|
|
52606
52628
|
"baseUrl",
|
|
52629
|
+
"endpoints",
|
|
52607
52630
|
"api",
|
|
52608
52631
|
"apiKey",
|
|
52609
52632
|
"apiKeyEnv",
|
|
@@ -52611,6 +52634,7 @@ function sanitizeRemotePayload(decoded, remote, catalogUrl, allowLocallyInjected
|
|
|
52611
52634
|
"displayName",
|
|
52612
52635
|
"filePlatform",
|
|
52613
52636
|
"attachmentPlatform",
|
|
52637
|
+
"transport",
|
|
52614
52638
|
"compat",
|
|
52615
52639
|
"cacheCapability",
|
|
52616
52640
|
"webSearch",
|
|
@@ -52626,8 +52650,13 @@ function sanitizeRemotePayload(decoded, remote, catalogUrl, allowLocallyInjected
|
|
|
52626
52650
|
assertOptionalString(source[field], `Remote profile "${provider}" ${field}`);
|
|
52627
52651
|
}
|
|
52628
52652
|
validateRemoteEndpoint(source.baseUrl, catalogUrl, `Remote profile "${provider}"`);
|
|
52653
|
+
validateProfileEndpoints(source, `Remote profile "${provider}"`);
|
|
52654
|
+
for (const [api, endpoint] of Object.entries(source.endpoints ?? {})) {
|
|
52655
|
+
validateRemoteEndpoint(endpoint, catalogUrl, `Remote profile "${provider}" endpoints.${api}`);
|
|
52656
|
+
}
|
|
52629
52657
|
if (!Array.isArray(source.models) || source.models.length === 0) throw new Error(`Remote profile "${provider}" has no models`);
|
|
52630
52658
|
assertRemoteHeadersSafe(source.headers, `Remote profile "${provider}"`);
|
|
52659
|
+
validateTransport(source.transport, `Remote profile "${provider}"`);
|
|
52631
52660
|
validateCompat(source.compat, `Remote profile "${provider}" compat`);
|
|
52632
52661
|
validateCacheCapability(source.cacheCapability, `Remote profile "${provider}" cacheCapability`);
|
|
52633
52662
|
validateWebSearchCapability(source.webSearch, `Remote profile "${provider}" webSearch`);
|
|
@@ -52644,7 +52673,9 @@ function sanitizeRemotePayload(decoded, remote, catalogUrl, allowLocallyInjected
|
|
|
52644
52673
|
}
|
|
52645
52674
|
const sanitized = {
|
|
52646
52675
|
baseUrl: source.baseUrl,
|
|
52676
|
+
...source.endpoints === void 0 ? {} : { endpoints: { ...source.endpoints } },
|
|
52647
52677
|
api: source.api,
|
|
52678
|
+
transport: source.transport,
|
|
52648
52679
|
apiKeyEnv: remote.apiKeyEnv,
|
|
52649
52680
|
...source.headers === void 0 ? {} : { headers: { ...source.headers } },
|
|
52650
52681
|
...source.displayName === void 0 ? {} : { displayName: source.displayName },
|
|
@@ -52656,6 +52687,7 @@ function sanitizeRemotePayload(decoded, remote, catalogUrl, allowLocallyInjected
|
|
|
52656
52687
|
...source.fileCapabilities === void 0 ? {} : { fileCapabilities: { ...source.fileCapabilities } },
|
|
52657
52688
|
models: source.models.map((model) => ({
|
|
52658
52689
|
id: model.id,
|
|
52690
|
+
...model.api === void 0 ? {} : { api: model.api },
|
|
52659
52691
|
...model.name === void 0 ? {} : { name: model.name },
|
|
52660
52692
|
...model.reasoning === void 0 ? {} : { reasoning: model.reasoning },
|
|
52661
52693
|
input: [...model.input],
|
|
@@ -52663,10 +52695,12 @@ function sanitizeRemotePayload(decoded, remote, catalogUrl, allowLocallyInjected
|
|
|
52663
52695
|
input: model.cost.input,
|
|
52664
52696
|
output: model.cost.output,
|
|
52665
52697
|
cacheRead: model.cost.cacheRead,
|
|
52666
|
-
cacheWrite: model.cost.cacheWrite
|
|
52698
|
+
cacheWrite: model.cost.cacheWrite,
|
|
52699
|
+
...model.cost.cacheWriteLong === void 0 ? {} : { cacheWriteLong: model.cost.cacheWriteLong }
|
|
52667
52700
|
},
|
|
52668
52701
|
contextWindow: model.contextWindow,
|
|
52669
52702
|
maxTokens: model.maxTokens,
|
|
52703
|
+
...model.transport === void 0 ? {} : { transport: model.transport },
|
|
52670
52704
|
...model.compat === void 0 ? {} : { compat: { ...model.compat } },
|
|
52671
52705
|
...model.cacheCapability === void 0 ? {} : { cacheCapability: { ...model.cacheCapability } },
|
|
52672
52706
|
...model.webSearch === void 0 ? {} : { webSearch: { ...model.webSearch } },
|
|
@@ -52729,8 +52763,8 @@ function validateModelOverrides(value) {
|
|
|
52729
52763
|
if (override.maxTokens !== void 0 && (!Number.isInteger(override.maxTokens) || Number(override.maxTokens) < 1)) throw new Error(`models.json modelOverrides["${key}"].maxTokens is invalid`);
|
|
52730
52764
|
if (override.cost !== void 0) {
|
|
52731
52765
|
if (!isPlainRecord(override.cost)) throw new Error(`models.json modelOverrides["${key}"].cost must be an object`);
|
|
52732
|
-
for (const field of ["input", "output", "cacheRead", "cacheWrite"]) {
|
|
52733
|
-
if (override.cost[field] !== void 0 && (typeof override.cost[field] !== "number" || Number.
|
|
52766
|
+
for (const field of ["input", "output", "cacheRead", "cacheWrite", "cacheWriteLong"]) {
|
|
52767
|
+
if (override.cost[field] !== void 0 && (typeof override.cost[field] !== "number" || !Number.isFinite(override.cost[field]) || override.cost[field] < 0)) throw new Error(`models.json modelOverrides["${key}"].cost.${field} must be a non-negative finite number`);
|
|
52734
52768
|
}
|
|
52735
52769
|
}
|
|
52736
52770
|
if (override.headers !== void 0) {
|
|
@@ -52739,16 +52773,41 @@ function validateModelOverrides(value) {
|
|
|
52739
52773
|
if (typeof headerValue !== "string") throw new Error(`models.json modelOverrides["${key}"].headers.${headerName} must be a string`);
|
|
52740
52774
|
}
|
|
52741
52775
|
}
|
|
52776
|
+
validateTransport(override.transport, `Model override "${key}"`);
|
|
52742
52777
|
validateCompat(override.compat, `models.json modelOverrides["${key}"].compat`);
|
|
52743
52778
|
validateCacheCapability(override.cacheCapability, `models.json modelOverrides["${key}"].cacheCapability`);
|
|
52744
52779
|
validateWebSearchCapability(override.webSearch, `models.json modelOverrides["${key}"].webSearch`);
|
|
52745
52780
|
validateFileCapabilities(override.fileCapabilities, `models.json modelOverrides["${key}"].fileCapabilities`);
|
|
52746
52781
|
}
|
|
52747
52782
|
}
|
|
52783
|
+
function validateProfileEndpoints(profile, label) {
|
|
52784
|
+
if (profile.endpoints === void 0) return;
|
|
52785
|
+
if (!isPlainRecord(profile.endpoints)) throw new Error(`${label} endpoints must be an object`);
|
|
52786
|
+
for (const [api, value] of Object.entries(profile.endpoints)) {
|
|
52787
|
+
if (!SUPPORTED_REMOTE_APIS.has(api)) throw new Error(`${label} endpoints has unsupported api ${api}`);
|
|
52788
|
+
try {
|
|
52789
|
+
if (typeof value !== "string") throw new Error("invalid URL");
|
|
52790
|
+
const endpoint = new URL(value);
|
|
52791
|
+
if (endpoint.protocol !== "http:" && endpoint.protocol !== "https:") throw new Error("unsupported protocol");
|
|
52792
|
+
} catch {
|
|
52793
|
+
throw new Error(`${label} endpoints.${api} must be an absolute HTTP(S) URL`);
|
|
52794
|
+
}
|
|
52795
|
+
}
|
|
52796
|
+
}
|
|
52797
|
+
function resolveProfileRoute(profile, model) {
|
|
52798
|
+
const api = model.api ?? profile.api;
|
|
52799
|
+
if (!SUPPORTED_REMOTE_APIS.has(api)) throw new Error(`Model "${model.id}" has unsupported api ${api}`);
|
|
52800
|
+
const endpoint = profile.endpoints?.[api];
|
|
52801
|
+
if (model.api !== void 0 && endpoint === void 0 && api !== profile.api) {
|
|
52802
|
+
throw new Error(`Model "${model.id}" api ${api} requires profile endpoints.${api} (otherwise api must equal profile api)`);
|
|
52803
|
+
}
|
|
52804
|
+
return { api, baseUrl: endpoint ?? profile.baseUrl };
|
|
52805
|
+
}
|
|
52748
52806
|
function validateProfileConfig(profileId, profileConfig) {
|
|
52749
52807
|
if (!isPlainRecord(profileConfig)) throw new Error(`Profile "${profileId}" must be an object.`);
|
|
52750
52808
|
assertOnlyKeys(profileConfig, [
|
|
52751
52809
|
"baseUrl",
|
|
52810
|
+
"endpoints",
|
|
52752
52811
|
"api",
|
|
52753
52812
|
"apiKey",
|
|
52754
52813
|
"apiKeyEnv",
|
|
@@ -52756,6 +52815,7 @@ function validateProfileConfig(profileId, profileConfig) {
|
|
|
52756
52815
|
"displayName",
|
|
52757
52816
|
"filePlatform",
|
|
52758
52817
|
"attachmentPlatform",
|
|
52818
|
+
"transport",
|
|
52759
52819
|
"compat",
|
|
52760
52820
|
"cacheCapability",
|
|
52761
52821
|
"webSearch",
|
|
@@ -52787,7 +52847,9 @@ function validateProfileConfig(profileId, profileConfig) {
|
|
|
52787
52847
|
} catch {
|
|
52788
52848
|
throw new Error(`Profile "${profileId}" baseUrl must be an absolute HTTP(S) URL`);
|
|
52789
52849
|
}
|
|
52850
|
+
validateProfileEndpoints(profileConfig, `Profile "${profileId}"`);
|
|
52790
52851
|
assertHeadersShape(profileConfig.headers, `Profile "${profileId}"`);
|
|
52852
|
+
validateTransport(profileConfig.transport, `Profile "${profileId}"`);
|
|
52791
52853
|
validateCompat(profileConfig.compat, `Profile "${profileId}" compat`);
|
|
52792
52854
|
validateCacheCapability(profileConfig.cacheCapability, `Profile "${profileId}" cacheCapability`);
|
|
52793
52855
|
validateWebSearchCapability(profileConfig.webSearch, `Profile "${profileId}" webSearch`);
|
|
@@ -52797,12 +52859,14 @@ function validateProfileConfig(profileId, profileConfig) {
|
|
|
52797
52859
|
if (!isPlainRecord(modelConfig)) throw new Error(`Profile "${profileId}" model #${index} must be an object.`);
|
|
52798
52860
|
assertOnlyKeys(modelConfig, [
|
|
52799
52861
|
"id",
|
|
52862
|
+
"api",
|
|
52800
52863
|
"name",
|
|
52801
52864
|
"reasoning",
|
|
52802
52865
|
"input",
|
|
52803
52866
|
"cost",
|
|
52804
52867
|
"contextWindow",
|
|
52805
52868
|
"maxTokens",
|
|
52869
|
+
"transport",
|
|
52806
52870
|
"compat",
|
|
52807
52871
|
"cacheCapability",
|
|
52808
52872
|
"webSearch",
|
|
@@ -52826,6 +52890,7 @@ function validateProfileConfig(profileId, profileConfig) {
|
|
|
52826
52890
|
);
|
|
52827
52891
|
}
|
|
52828
52892
|
validateRemoteModel(profileId, modelConfig);
|
|
52893
|
+
resolveProfileRoute(profileConfig, modelConfig);
|
|
52829
52894
|
assertHeadersShape(modelConfig.headers, `Profile "${profileId}" model "${modelConfig.id}"`);
|
|
52830
52895
|
assertOptionalEnvName(modelConfig.apiKeyEnv, `Profile "${profileId}" model "${modelConfig.id}" apiKeyEnv`);
|
|
52831
52896
|
if (seenModelIds.has(modelConfig.id)) throw new Error(`Profile "${profileId}" contains duplicate model "${modelConfig.id}".`);
|
|
@@ -52916,12 +52981,13 @@ var ModelRegistry = class {
|
|
|
52916
52981
|
);
|
|
52917
52982
|
}
|
|
52918
52983
|
const existing = this.models.get(provider);
|
|
52919
|
-
if (existing && (providerConfig.baseUrl || providerConfig.api || providerConfig.headers)) {
|
|
52984
|
+
if (existing && (providerConfig.baseUrl || providerConfig.api || providerConfig.headers || providerConfig.transport)) {
|
|
52920
52985
|
for (const model of existing.values()) {
|
|
52921
52986
|
this.upsert({
|
|
52922
52987
|
...model,
|
|
52923
52988
|
baseUrl: providerConfig.baseUrl || model.baseUrl,
|
|
52924
52989
|
api: providerConfig.api || model.api,
|
|
52990
|
+
transport: providerConfig.transport ?? model.transport,
|
|
52925
52991
|
apiKeyEnv: providerConfig.apiKeyEnv || model.apiKeyEnv,
|
|
52926
52992
|
displayName: providerConfig.displayName || model.displayName || provider,
|
|
52927
52993
|
filePlatform: providerConfig.filePlatform || model.filePlatform,
|
|
@@ -52938,9 +53004,8 @@ var ModelRegistry = class {
|
|
|
52938
53004
|
this.upsert({
|
|
52939
53005
|
id: customModel.id,
|
|
52940
53006
|
name: customModel.name || baseModel?.name || customModel.id,
|
|
52941
|
-
|
|
53007
|
+
...resolveProfileRoute(providerConfig, customModel),
|
|
52942
53008
|
provider,
|
|
52943
|
-
baseUrl: providerConfig.baseUrl || baseModel?.baseUrl || "",
|
|
52944
53009
|
reasoning: customModel.reasoning ?? baseModel?.reasoning ?? false,
|
|
52945
53010
|
input: customModel.input || baseModel?.input || ["text"],
|
|
52946
53011
|
cost: customModel.cost || baseModel?.cost || { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
@@ -52951,6 +53016,7 @@ var ModelRegistry = class {
|
|
|
52951
53016
|
filePlatform: customModel.filePlatform || providerConfig.filePlatform || baseModel?.filePlatform,
|
|
52952
53017
|
attachmentPlatform: customModel.attachmentPlatform || providerConfig.attachmentPlatform || baseModel?.attachmentPlatform,
|
|
52953
53018
|
headers: providerConfig.headers ? { ...baseModel?.headers, ...providerConfig.headers, ...customModel.headers } : customModel.headers || baseModel?.headers,
|
|
53019
|
+
transport: customModel.transport ?? providerConfig.transport ?? baseModel?.transport,
|
|
52954
53020
|
compat: customModel.compat || providerConfig.compat || baseModel?.compat,
|
|
52955
53021
|
cacheCapability: customModel.cacheCapability || providerConfig.cacheCapability || baseModel?.cacheCapability,
|
|
52956
53022
|
webSearch: customModel.webSearch || providerConfig.webSearch || baseModel?.webSearch,
|
|
@@ -53003,6 +53069,7 @@ var ModelRegistry = class {
|
|
|
53003
53069
|
if (override.maxTokens !== void 0) patched.maxTokens = override.maxTokens;
|
|
53004
53070
|
if (override.cost !== void 0) patched.cost = { ...existing.cost, ...override.cost };
|
|
53005
53071
|
if (override.headers !== void 0) patched.headers = { ...existing.headers, ...override.headers };
|
|
53072
|
+
if (override.transport !== void 0) patched.transport = override.transport;
|
|
53006
53073
|
if (override.compat !== void 0) patched.compat = deepMergePlainRecords(existing.compat, override.compat);
|
|
53007
53074
|
if (override.cacheCapability !== void 0) patched.cacheCapability = { ...existing.cacheCapability, ...override.cacheCapability };
|
|
53008
53075
|
if (override.webSearch !== void 0) patched.webSearch = { ...existing.webSearch, ...override.webSearch };
|
|
@@ -53024,9 +53091,8 @@ var ModelRegistry = class {
|
|
|
53024
53091
|
this.upsert({
|
|
53025
53092
|
id: customModel.id,
|
|
53026
53093
|
name: customModel.name || customModel.id,
|
|
53027
|
-
|
|
53094
|
+
...resolveProfileRoute(providerConfig, customModel),
|
|
53028
53095
|
provider,
|
|
53029
|
-
baseUrl: providerConfig.baseUrl || "",
|
|
53030
53096
|
reasoning: customModel.reasoning ?? false,
|
|
53031
53097
|
input: customModel.input || ["text"],
|
|
53032
53098
|
cost: customModel.cost || { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
@@ -53037,6 +53103,7 @@ var ModelRegistry = class {
|
|
|
53037
53103
|
filePlatform: customModel.filePlatform || providerConfig.filePlatform,
|
|
53038
53104
|
attachmentPlatform: customModel.attachmentPlatform || providerConfig.attachmentPlatform,
|
|
53039
53105
|
headers: { ...providerConfig.headers, ...customModel.headers },
|
|
53106
|
+
transport: customModel.transport ?? providerConfig.transport,
|
|
53040
53107
|
compat: customModel.compat || providerConfig.compat,
|
|
53041
53108
|
cacheCapability: customModel.cacheCapability || providerConfig.cacheCapability,
|
|
53042
53109
|
webSearch: customModel.webSearch || providerConfig.webSearch,
|
|
@@ -53476,12 +53543,13 @@ var ModelRegistry = class {
|
|
|
53476
53543
|
this.authStorage.setProviderEnvVar(provider, config.apiKeyEnv);
|
|
53477
53544
|
}
|
|
53478
53545
|
const existing = this.models.get(provider);
|
|
53479
|
-
if (existing && (config.baseUrl || config.api || config.headers)) {
|
|
53546
|
+
if (existing && (config.baseUrl || config.api || config.headers || config.transport)) {
|
|
53480
53547
|
for (const model of existing.values()) {
|
|
53481
53548
|
this.upsert({
|
|
53482
53549
|
...model,
|
|
53483
53550
|
baseUrl: config.baseUrl || model.baseUrl,
|
|
53484
53551
|
api: config.api || model.api,
|
|
53552
|
+
transport: config.transport ?? model.transport,
|
|
53485
53553
|
headers: config.headers ? { ...model.headers, ...config.headers } : model.headers
|
|
53486
53554
|
});
|
|
53487
53555
|
}
|
|
@@ -53502,6 +53570,7 @@ var ModelRegistry = class {
|
|
|
53502
53570
|
apiKeyEnv: config.apiKeyEnv || baseModel?.apiKeyEnv,
|
|
53503
53571
|
displayName: customModel.displayName || baseModel?.displayName || provider,
|
|
53504
53572
|
headers: config.headers ? { ...baseModel?.headers, ...config.headers, ...customModel.headers } : customModel.headers || baseModel?.headers,
|
|
53573
|
+
transport: customModel.transport ?? config.transport ?? baseModel?.transport,
|
|
53505
53574
|
compat: customModel.compat || baseModel?.compat,
|
|
53506
53575
|
cacheCapability: customModel.cacheCapability || baseModel?.cacheCapability,
|
|
53507
53576
|
webSearch: customModel.webSearch || baseModel?.webSearch,
|
|
@@ -53794,6 +53863,16 @@ var SettingsManager = class {
|
|
|
53794
53863
|
this.settings.autoCompactReserveTokens = tokens;
|
|
53795
53864
|
this.writeSettings();
|
|
53796
53865
|
}
|
|
53866
|
+
/** Undefined means "no CLI override": the provider default applies. */
|
|
53867
|
+
getPromptCacheRetention() {
|
|
53868
|
+
const retention = this.settings.promptCacheRetention;
|
|
53869
|
+
return retention === "none" || retention === "short" || retention === "long" ? retention : void 0;
|
|
53870
|
+
}
|
|
53871
|
+
setPromptCacheRetention(retention) {
|
|
53872
|
+
if (retention === void 0) delete this.settings.promptCacheRetention;
|
|
53873
|
+
else this.settings.promptCacheRetention = retention;
|
|
53874
|
+
this.writeSettings();
|
|
53875
|
+
}
|
|
53797
53876
|
getWebSearchMode() {
|
|
53798
53877
|
const mode = this.settings.tools?.webSearch?.mode;
|
|
53799
53878
|
if (mode === "disabled" || mode === "cached" || mode === "live") {
|
|
@@ -54053,7 +54132,7 @@ function checkComputerUse() {
|
|
|
54053
54132
|
id: "computer_use_helper",
|
|
54054
54133
|
label: "computer-use helper",
|
|
54055
54134
|
status: "warn",
|
|
54056
|
-
message: `computer-use helper app is not installed yet; it installs on first
|
|
54135
|
+
message: `computer-use helper app is not installed yet; it installs on first computer-use-axi use to ${appPath}. Afterwards grant Accessibility and Screen Recording to pie-computer-use.app in System Settings \u2192 Privacy & Security.`,
|
|
54057
54136
|
details: { appPath }
|
|
54058
54137
|
};
|
|
54059
54138
|
}
|
|
@@ -54341,7 +54420,7 @@ var MODE_RULES = {
|
|
|
54341
54420
|
"~/.pie is allowlisted for Pie configuration and session support.",
|
|
54342
54421
|
"Shell commands run from the workspace and return structured output, timeout, and truncation details.",
|
|
54343
54422
|
"web_research is read-only, uses provider-native web/search/fetch capabilities, and does not grant bash/curl web scraping permission.",
|
|
54344
|
-
"computer-use
|
|
54423
|
+
"Desktop control runs through the computer-use-axi skill CLI via bash: observation commands only read the screen, while act synthesizes real desktop input and goes through normal shell permission prompts.",
|
|
54345
54424
|
"Protected paths from extensions can block reads/writes even when tools are present."
|
|
54346
54425
|
],
|
|
54347
54426
|
plan: [
|
|
@@ -54351,7 +54430,7 @@ var MODE_RULES = {
|
|
|
54351
54430
|
yolo: [
|
|
54352
54431
|
"/settings/yolo relaxes filesystem sandbox directory restrictions.",
|
|
54353
54432
|
"It does not make destructive shell commands safe; use it only in trusted workspaces.",
|
|
54354
|
-
"It also
|
|
54433
|
+
"It also auto-approves shell commands, including computer-use-axi desktop input."
|
|
54355
54434
|
],
|
|
54356
54435
|
subagents: [
|
|
54357
54436
|
"Subagents inherit the parent tool set, then runtime policy removes write and high-risk tools.",
|
|
@@ -55513,10 +55592,11 @@ async function forkStoredSession(params) {
|
|
|
55513
55592
|
timestamp: entry.timestamp
|
|
55514
55593
|
};
|
|
55515
55594
|
if (copy.compactionData) {
|
|
55595
|
+
const selfAnchored = copy.compactionData.firstKeptEntryId === entry.id;
|
|
55516
55596
|
const keptId = idMap.get(copy.compactionData.firstKeptEntryId);
|
|
55517
55597
|
copy.compactionData = {
|
|
55518
55598
|
...copy.compactionData,
|
|
55519
|
-
firstKeptEntryId: keptId ?? firstCopiedId ?? copy.id
|
|
55599
|
+
firstKeptEntryId: selfAnchored ? copy.id : keptId ?? firstCopiedId ?? copy.id
|
|
55520
55600
|
};
|
|
55521
55601
|
}
|
|
55522
55602
|
idMap.set(summary.id, copy.id);
|
|
@@ -56502,7 +56582,10 @@ function createExtensionContext(extension, cwd, uiContext, abortFn, isIdleFn, ha
|
|
|
56502
56582
|
},
|
|
56503
56583
|
get yoloMode() {
|
|
56504
56584
|
return actions?.yoloMode ?? false;
|
|
56505
|
-
}
|
|
56585
|
+
},
|
|
56586
|
+
// Only expose setYoloMode when the host can actually toggle it — plan-mode
|
|
56587
|
+
// gates the option on typeof ctx.setYoloMode === "function".
|
|
56588
|
+
...actions?.setYoloMode ? { setYoloMode: (enabled) => actions.setYoloMode(enabled) } : {}
|
|
56506
56589
|
};
|
|
56507
56590
|
return context;
|
|
56508
56591
|
}
|
|
@@ -60395,8 +60478,8 @@ var Editor = class {
|
|
|
60395
60478
|
this.historyIndex = -1;
|
|
60396
60479
|
this.lastAction = null;
|
|
60397
60480
|
this.pushUndoSnapshot();
|
|
60398
|
-
const
|
|
60399
|
-
const tabExpandedText =
|
|
60481
|
+
const cleanText = pastedText.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
60482
|
+
const tabExpandedText = cleanText.replace(/\t/g, " ");
|
|
60400
60483
|
let filteredText = tabExpandedText.split("").filter((char) => char === "\n" || char.charCodeAt(0) >= 32).join("");
|
|
60401
60484
|
if (/^[/~.]/.test(filteredText)) {
|
|
60402
60485
|
const currentLine = this.state.lines[this.state.cursorLine] || "";
|
|
@@ -61480,9 +61563,9 @@ var Input = class {
|
|
|
61480
61563
|
handlePaste(pastedText) {
|
|
61481
61564
|
this.lastAction = null;
|
|
61482
61565
|
this.pushUndo();
|
|
61483
|
-
const
|
|
61484
|
-
this.value = this.value.slice(0, this.cursor) +
|
|
61485
|
-
this.cursor +=
|
|
61566
|
+
const cleanText = pastedText.replace(/\r\n/g, "").replace(/\r/g, "").replace(/\n/g, "");
|
|
61567
|
+
this.value = this.value.slice(0, this.cursor) + cleanText + this.value.slice(this.cursor);
|
|
61568
|
+
this.cursor += cleanText.length;
|
|
61486
61569
|
}
|
|
61487
61570
|
invalidate() {
|
|
61488
61571
|
}
|
|
@@ -64255,7 +64338,10 @@ var ExtensionRunner = class {
|
|
|
64255
64338
|
},
|
|
64256
64339
|
get yoloMode() {
|
|
64257
64340
|
return runner.actions.yoloMode ?? false;
|
|
64258
|
-
}
|
|
64341
|
+
},
|
|
64342
|
+
// Only expose setYoloMode when the host can actually toggle it — plan-mode
|
|
64343
|
+
// gates the option on typeof ctx.setYoloMode === "function".
|
|
64344
|
+
...runner.actions.setYoloMode ? { setYoloMode: (enabled) => runner.actions.setYoloMode(enabled) } : {}
|
|
64259
64345
|
};
|
|
64260
64346
|
return createLoggedProxy(context, `ExtensionContext#${contextId}`);
|
|
64261
64347
|
}
|
|
@@ -65005,6 +65091,23 @@ function buildCliFileAccessOptions(params) {
|
|
|
65005
65091
|
};
|
|
65006
65092
|
}
|
|
65007
65093
|
|
|
65094
|
+
// src/runtime/computer-use-owner.ts
|
|
65095
|
+
var COMPUTER_USE_OWNER_ENV = "PIE_COMPUTER_USE_OWNER_ID";
|
|
65096
|
+
var COMPUTER_USE_EXECUTION_ENV = "PIE_COMPUTER_USE_EXECUTION_ID";
|
|
65097
|
+
var COMPUTER_USE_STANDALONE_OWNER = "standalone";
|
|
65098
|
+
var OWNER_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:@-]{0,255}$/;
|
|
65099
|
+
function normalizeComputerUseOwner(value) {
|
|
65100
|
+
if (typeof value !== "string") return COMPUTER_USE_STANDALONE_OWNER;
|
|
65101
|
+
const trimmed = value.trim();
|
|
65102
|
+
if (!trimmed) return COMPUTER_USE_STANDALONE_OWNER;
|
|
65103
|
+
return OWNER_PATTERN.test(trimmed) ? trimmed : COMPUTER_USE_STANDALONE_OWNER;
|
|
65104
|
+
}
|
|
65105
|
+
function computerUseOwnerEnv(ownerId, executionId) {
|
|
65106
|
+
const env = { [COMPUTER_USE_OWNER_ENV]: normalizeComputerUseOwner(ownerId) };
|
|
65107
|
+
if (executionId) env[COMPUTER_USE_EXECUTION_ENV] = executionId;
|
|
65108
|
+
return env;
|
|
65109
|
+
}
|
|
65110
|
+
|
|
65008
65111
|
// src/theme/theme.ts
|
|
65009
65112
|
import * as fs13 from "node:fs";
|
|
65010
65113
|
import * as path12 from "node:path";
|
|
@@ -70202,14 +70305,18 @@ function computePromptPrefixHash(systemPrompt, tools) {
|
|
|
70202
70305
|
function calculateCumulativeCacheHitRate(messages) {
|
|
70203
70306
|
let input = 0;
|
|
70204
70307
|
let cacheRead = 0;
|
|
70308
|
+
let cacheWrite = 0;
|
|
70309
|
+
let cacheWriteLong = 0;
|
|
70205
70310
|
for (const message of messages) {
|
|
70206
70311
|
if (message.role !== "assistant") continue;
|
|
70207
70312
|
const usage = message.usage;
|
|
70208
70313
|
if (!usage) continue;
|
|
70209
70314
|
input += usage.input;
|
|
70210
70315
|
cacheRead += usage.cacheRead;
|
|
70316
|
+
cacheWrite += usage.cacheWrite;
|
|
70317
|
+
cacheWriteLong += usage.cacheWriteLong ?? 0;
|
|
70211
70318
|
}
|
|
70212
|
-
const base = input + cacheRead;
|
|
70319
|
+
const base = input + cacheRead + cacheWrite + cacheWriteLong;
|
|
70213
70320
|
return base > 0 ? cacheRead / base : null;
|
|
70214
70321
|
}
|
|
70215
70322
|
var signalMemories = /* @__PURE__ */ new WeakMap();
|
|
@@ -70219,20 +70326,52 @@ function getLastContextSignals(hostKey) {
|
|
|
70219
70326
|
}
|
|
70220
70327
|
function computeContextSignals(hostKey, systemPrompt, tools, messages) {
|
|
70221
70328
|
const prefixHash = computePromptPrefixHash(systemPrompt, tools);
|
|
70329
|
+
const systemHash = computePromptPrefixHash(systemPrompt, []);
|
|
70330
|
+
const toolsHash = computePromptPrefixHash("", tools);
|
|
70222
70331
|
const previous = signalMemories.get(hostKey);
|
|
70223
70332
|
const prefixHashChanged = previous !== void 0 && previous.hash !== prefixHash;
|
|
70224
70333
|
if (previous?.hash !== prefixHash) {
|
|
70225
|
-
signalMemories.set(hostKey, { hash: prefixHash });
|
|
70334
|
+
signalMemories.set(hostKey, { hash: prefixHash, systemHash, toolsHash });
|
|
70226
70335
|
}
|
|
70227
70336
|
const signals = {
|
|
70228
70337
|
prefixHash,
|
|
70229
70338
|
prefixHashChanged,
|
|
70339
|
+
...prefixHashChanged && previous ? { previousPrefixHash: previous.hash } : {},
|
|
70340
|
+
systemPromptChanged: prefixHashChanged && previous !== void 0 && previous.systemHash !== systemHash,
|
|
70341
|
+
toolsChanged: prefixHashChanged && previous !== void 0 && previous.toolsHash !== toolsHash,
|
|
70230
70342
|
cacheHitRate: calculateCumulativeCacheHitRate(messages)
|
|
70231
70343
|
};
|
|
70232
70344
|
lastSignals.set(hostKey, signals);
|
|
70233
70345
|
return signals;
|
|
70234
70346
|
}
|
|
70235
70347
|
|
|
70348
|
+
// src/runtime/cache-invalidation-trace.ts
|
|
70349
|
+
function noteCacheInvalidationInChat(host, signals) {
|
|
70350
|
+
if (!signals || !signals.prefixHashChanged) return;
|
|
70351
|
+
const parts = [];
|
|
70352
|
+
if (signals.systemPromptChanged && signals.toolsChanged) parts.push("system prompt + tools rebuilt");
|
|
70353
|
+
else if (signals.toolsChanged) parts.push("tools rebuilt");
|
|
70354
|
+
else if (signals.systemPromptChanged) parts.push("system prompt rebuilt");
|
|
70355
|
+
else parts.push("prefix rebuilt");
|
|
70356
|
+
const from = signals.previousPrefixHash ?? "?";
|
|
70357
|
+
const line = `\u26A1 Prompt cache invalidated: \u2301${from} \u2192 \u2301${signals.prefixHash} (${parts.join(", ")})`;
|
|
70358
|
+
if (host.chatContainer && host.ui) {
|
|
70359
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
70360
|
+
host.chatContainer.addChild(new Text(theme.fg("warning", line), 1, 0));
|
|
70361
|
+
host.ui.requestRender();
|
|
70362
|
+
}
|
|
70363
|
+
host.sessionTrace?.noteRuntimeEvent("cache_prefix_invalidated", {
|
|
70364
|
+
from,
|
|
70365
|
+
to: signals.prefixHash,
|
|
70366
|
+
systemPromptChanged: signals.systemPromptChanged,
|
|
70367
|
+
toolsChanged: signals.toolsChanged
|
|
70368
|
+
});
|
|
70369
|
+
}
|
|
70370
|
+
function applyContextSignalsWithTrace(host) {
|
|
70371
|
+
applyContextSignalsToFooter(host);
|
|
70372
|
+
noteCacheInvalidationInChat(host, getLastContextSignals(host));
|
|
70373
|
+
}
|
|
70374
|
+
|
|
70236
70375
|
// src/commands/interactive-session-commands.ts
|
|
70237
70376
|
import * as os6 from "os";
|
|
70238
70377
|
|
|
@@ -70434,6 +70573,11 @@ function formatReportTokens(count) {
|
|
|
70434
70573
|
if (count < 1e7) return `${(count / 1e6).toFixed(1)}M`;
|
|
70435
70574
|
return `${Math.round(count / 1e6)}M`;
|
|
70436
70575
|
}
|
|
70576
|
+
function formatMeasuredTime(timestamp) {
|
|
70577
|
+
const date = new Date(timestamp);
|
|
70578
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
70579
|
+
return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
70580
|
+
}
|
|
70437
70581
|
function buildSystemPromptBlocks(systemPrompt, skillsSection, knowledgeSection) {
|
|
70438
70582
|
const totalTokens = estimateStringTokens(systemPrompt);
|
|
70439
70583
|
const skillsTokens = skillsSection && systemPrompt.includes(skillsSection.trim()) ? estimateStringTokens(skillsSection) : null;
|
|
@@ -70689,8 +70833,12 @@ ${file.content}`).join("\n\n");
|
|
|
70689
70833
|
messagesTokens,
|
|
70690
70834
|
dynamicContextTokens: 0,
|
|
70691
70835
|
estimatedTotalTokens,
|
|
70692
|
-
|
|
70836
|
+
estimatedCurrentTokens: inputs.estimatedCurrentTokens,
|
|
70837
|
+
providerMeasuredTokens: inputs.providerMeasuredTokens,
|
|
70838
|
+
providerMeasuredAt: inputs.providerMeasuredAt ?? null,
|
|
70839
|
+
measurementMatchesCurrentContext: inputs.measurementMatchesCurrentContext,
|
|
70693
70840
|
contextWindow: inputs.contextWindow,
|
|
70841
|
+
autoCompactEnabled: inputs.autoCompactEnabled,
|
|
70694
70842
|
autoCompactLimitTokens: inputs.autoCompactLimitTokens,
|
|
70695
70843
|
reserveTokens: inputs.reserveTokens,
|
|
70696
70844
|
promptPrefixHash: inputs.promptPrefixHash,
|
|
@@ -70747,13 +70895,14 @@ function buildContextOverviewText(data, themeInput) {
|
|
|
70747
70895
|
}
|
|
70748
70896
|
}
|
|
70749
70897
|
});
|
|
70750
|
-
const autoCompact = data.autoCompactLimitTokens ? `triggers > ~${formatReportTokens(data.autoCompactLimitTokens)} (reserve ${formatReportTokens(data.reserveTokens)})` : "
|
|
70898
|
+
const autoCompact = !data.autoCompactEnabled ? "Off (disabled in settings)" : data.autoCompactLimitTokens ? `On \xB7 triggers > ~${formatReportTokens(data.autoCompactLimitTokens)} (reserve ${formatReportTokens(data.reserveTokens)})` : "On \xB7 threshold unknown (context window unavailable)";
|
|
70751
70899
|
lines.push(
|
|
70752
70900
|
`${padEndVisible(` ${branch(sections.length)} auto-compact`, labelWidth)}${theme2.fg("dim", autoCompact)}`
|
|
70753
70901
|
);
|
|
70754
|
-
const
|
|
70755
|
-
|
|
70756
|
-
|
|
70902
|
+
const measuredAt = data.providerMeasuredAt !== null ? ` \xB7 measured ${formatMeasuredTime(data.providerMeasuredAt)}` : "";
|
|
70903
|
+
const reconciliation = data.providerMeasuredTokens !== null ? data.measurementMatchesCurrentContext ? `est current ~${formatReportTokens(data.estimatedCurrentTokens)} \xB7 provider-measured ${formatReportTokens(data.providerMeasuredTokens)} (last response${measuredAt}) \xB7 est\u2212measured \u2248 ${formatReportTokens(
|
|
70904
|
+
Math.abs(data.estimatedCurrentTokens - data.providerMeasuredTokens)
|
|
70905
|
+
)}${data.estimatedCurrentTokens >= data.providerMeasuredTokens ? " overhead" : " undercount"}` : `est current ~${formatReportTokens(data.estimatedCurrentTokens)} \xB7 provider-measured ${formatReportTokens(data.providerMeasuredTokens)} (last response${measuredAt}) \xB7 not comparable \u2014 context changed since measurement` : `est current ~${formatReportTokens(data.estimatedCurrentTokens)} \xB7 provider usage not reported yet`;
|
|
70757
70906
|
lines.push(` ${theme2.fg("dim", reconciliation)}`);
|
|
70758
70907
|
lines.push(theme2.fg("dim", " /debugs/context \xB7 Enter to drill into a section, Esc to go back"));
|
|
70759
70908
|
return lines.join("\n");
|
|
@@ -70772,23 +70921,37 @@ function buildWindowRows(data) {
|
|
|
70772
70921
|
label: "estimated total (prompt + tools + messages)",
|
|
70773
70922
|
estTokens: data.estimatedTotalTokens,
|
|
70774
70923
|
note: `prompt ~${formatReportTokens(data.systemPromptTokens)} \xB7 tools ~${formatReportTokens(data.toolsTokens)} \xB7 messages ~${formatReportTokens(data.messagesTokens)}`
|
|
70924
|
+
},
|
|
70925
|
+
{
|
|
70926
|
+
id: "window:estimated-current",
|
|
70927
|
+
label: "estimated current context (local estimate + tail)",
|
|
70928
|
+
estTokens: data.estimatedCurrentTokens,
|
|
70929
|
+
note: "local estimate \u2014 not a provider measurement"
|
|
70775
70930
|
}
|
|
70776
70931
|
];
|
|
70777
|
-
if (data.
|
|
70932
|
+
if (data.providerMeasuredTokens !== null) {
|
|
70933
|
+
const measuredAt = data.providerMeasuredAt !== null ? formatMeasuredTime(data.providerMeasuredAt) : "unknown time";
|
|
70778
70934
|
rows.push({
|
|
70779
|
-
id: "window:
|
|
70780
|
-
label: "
|
|
70781
|
-
estTokens: data.
|
|
70782
|
-
valueText: formatReportTokens(data.
|
|
70783
|
-
note: `
|
|
70935
|
+
id: "window:provider-measured",
|
|
70936
|
+
label: "provider-measured (last response)",
|
|
70937
|
+
estTokens: data.providerMeasuredTokens,
|
|
70938
|
+
valueText: formatReportTokens(data.providerMeasuredTokens),
|
|
70939
|
+
note: data.measurementMatchesCurrentContext ? `est\u2212measured \u2248 ${formatReportTokens(Math.abs(data.estimatedCurrentTokens - data.providerMeasuredTokens))} \xB7 ${measuredAt}` : `not comparable \u2014 context changed since measurement \xB7 ${measuredAt}`
|
|
70784
70940
|
});
|
|
70785
70941
|
}
|
|
70786
70942
|
rows.push({
|
|
70787
70943
|
id: "window:auto-compact",
|
|
70944
|
+
label: "auto-compact",
|
|
70945
|
+
estTokens: 0,
|
|
70946
|
+
valueText: data.autoCompactEnabled ? "On" : "Off",
|
|
70947
|
+
note: data.autoCompactEnabled ? "enabled in settings" : "disabled in settings"
|
|
70948
|
+
});
|
|
70949
|
+
rows.push({
|
|
70950
|
+
id: "window:auto-compact-threshold",
|
|
70788
70951
|
label: "auto-compact threshold",
|
|
70789
|
-
estTokens: data.autoCompactLimitTokens ?? 0,
|
|
70790
|
-
valueText: data.autoCompactLimitTokens ? `>${formatReportTokens(data.autoCompactLimitTokens)}` : "
|
|
70791
|
-
note: data.autoCompactLimitTokens ? `reserve ${formatReportTokens(data.reserveTokens)}` : "
|
|
70952
|
+
estTokens: data.autoCompactEnabled ? data.autoCompactLimitTokens ?? 0 : 0,
|
|
70953
|
+
valueText: data.autoCompactEnabled ? data.autoCompactLimitTokens ? `>${formatReportTokens(data.autoCompactLimitTokens)}` : "unknown" : "\u2014",
|
|
70954
|
+
note: data.autoCompactEnabled ? data.autoCompactLimitTokens ? `reserve ${formatReportTokens(data.reserveTokens)}` : "context window unavailable" : "not applied while Off"
|
|
70792
70955
|
});
|
|
70793
70956
|
if (data.promptPrefixHash) {
|
|
70794
70957
|
rows.push({
|
|
@@ -71171,6 +71334,9 @@ var TreeSelectorComponent = class {
|
|
|
71171
71334
|
pageNext() {
|
|
71172
71335
|
if (this.goToNextPage()) {
|
|
71173
71336
|
this.statusMessage = null;
|
|
71337
|
+
} else if (this.filteredRows.length > 0) {
|
|
71338
|
+
this.selectedIndex = Math.max(0, this.filteredRows.length - 1);
|
|
71339
|
+
this.statusMessage = "latest page - at newest entry";
|
|
71174
71340
|
} else {
|
|
71175
71341
|
this.statusMessage = this.pageSummaries.length === 0 ? "no entries" : "latest page";
|
|
71176
71342
|
}
|
|
@@ -71178,10 +71344,58 @@ var TreeSelectorComponent = class {
|
|
|
71178
71344
|
pagePrev() {
|
|
71179
71345
|
if (this.goToPreviousPage()) {
|
|
71180
71346
|
this.statusMessage = null;
|
|
71347
|
+
} else if (this.filteredRows.length > 0) {
|
|
71348
|
+
this.selectedIndex = 0;
|
|
71349
|
+
this.statusMessage = "oldest page - at first entry";
|
|
71181
71350
|
} else {
|
|
71182
71351
|
this.statusMessage = this.pageSummaries.length === 0 ? "no entries" : "oldest page";
|
|
71183
71352
|
}
|
|
71184
71353
|
}
|
|
71354
|
+
/** Jump to the oldest page (seqs start at 1; afterSeq 0 = from the start). */
|
|
71355
|
+
jumpToFirstPage() {
|
|
71356
|
+
if (this.pageSummaries.length > 0 && !this.hasPrev) {
|
|
71357
|
+
this.selectedIndex = 0;
|
|
71358
|
+
this.statusMessage = "oldest page - at first entry";
|
|
71359
|
+
return;
|
|
71360
|
+
}
|
|
71361
|
+
if (this.fetchWindow(0, null)) {
|
|
71362
|
+
this.selectedIndex = 0;
|
|
71363
|
+
this.statusMessage = null;
|
|
71364
|
+
}
|
|
71365
|
+
}
|
|
71366
|
+
/** Jump to the newest page. Seqs are 1..total (append-only journal), so the last window starts at total - pageSize. */
|
|
71367
|
+
jumpToLastPage() {
|
|
71368
|
+
if (this.pageSummaries.length > 0 && !this.hasNext) {
|
|
71369
|
+
this.selectedIndex = Math.max(0, this.filteredRows.length - 1);
|
|
71370
|
+
this.statusMessage = "latest page - at newest entry";
|
|
71371
|
+
return;
|
|
71372
|
+
}
|
|
71373
|
+
let anchor = Math.max(0, this.totalEntries - this.pageSizeValue);
|
|
71374
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
71375
|
+
if (this.fetchWindow(anchor, null)) {
|
|
71376
|
+
if (this.hasNext) {
|
|
71377
|
+
anchor = this.pageSummaries[this.pageSummaries.length - 1].seq;
|
|
71378
|
+
continue;
|
|
71379
|
+
}
|
|
71380
|
+
this.selectedIndex = Math.max(0, this.filteredRows.length - 1);
|
|
71381
|
+
this.statusMessage = null;
|
|
71382
|
+
return;
|
|
71383
|
+
}
|
|
71384
|
+
if (anchor === 0 || !this.hasNext) break;
|
|
71385
|
+
anchor = Math.max(0, anchor - this.pageSizeValue);
|
|
71386
|
+
}
|
|
71387
|
+
}
|
|
71388
|
+
/** Move the cursor one viewport within the resident page; ←/→ change pages. */
|
|
71389
|
+
screenScroll(delta) {
|
|
71390
|
+
if (this.filteredRows.length === 0) return;
|
|
71391
|
+
const next = Math.max(0, Math.min(this.selectedIndex + delta, this.filteredRows.length - 1));
|
|
71392
|
+
if (next === this.selectedIndex) {
|
|
71393
|
+
this.statusMessage = delta > 0 ? "end of page - \u2192 for next page" : "start of page - \u2190 for previous page";
|
|
71394
|
+
return;
|
|
71395
|
+
}
|
|
71396
|
+
this.selectedIndex = next;
|
|
71397
|
+
this.statusMessage = null;
|
|
71398
|
+
}
|
|
71185
71399
|
/**
|
|
71186
71400
|
* Bounded "next match": step to the next in-page match, otherwise scan
|
|
71187
71401
|
* forward at most SEARCH_SCAN_PAGE_LIMIT pages per press. Never scans
|
|
@@ -71235,7 +71449,7 @@ var TreeSelectorComponent = class {
|
|
|
71235
71449
|
lines.push(createLine(" Conversation Tree", width, false));
|
|
71236
71450
|
lines.push(
|
|
71237
71451
|
createLine(
|
|
71238
|
-
" \u2191\u2193:move \u2190\u2192:page e:collapse tab:
|
|
71452
|
+
" \u2191\u2193:move \u2190\u2192:page PgUp/PgDn:screen Home/End:jump e:collapse tab:match F:fork Enter:go Esc:cancel",
|
|
71239
71453
|
width,
|
|
71240
71454
|
false
|
|
71241
71455
|
)
|
|
@@ -71304,10 +71518,18 @@ var TreeSelectorComponent = class {
|
|
|
71304
71518
|
this.moveUp();
|
|
71305
71519
|
} else if (kb.matches(keyData, "selectDown")) {
|
|
71306
71520
|
this.moveDown();
|
|
71307
|
-
} else if (kb.matches(keyData, "cursorRight")
|
|
71521
|
+
} else if (kb.matches(keyData, "cursorRight")) {
|
|
71308
71522
|
this.pageNext();
|
|
71309
|
-
} else if (kb.matches(keyData, "cursorLeft")
|
|
71523
|
+
} else if (kb.matches(keyData, "cursorLeft")) {
|
|
71310
71524
|
this.pagePrev();
|
|
71525
|
+
} else if (kb.matches(keyData, "selectPageDown")) {
|
|
71526
|
+
this.screenScroll(this.maxVisibleLines);
|
|
71527
|
+
} else if (kb.matches(keyData, "selectPageUp")) {
|
|
71528
|
+
this.screenScroll(-this.maxVisibleLines);
|
|
71529
|
+
} else if (kb.matches(keyData, "cursorLineStart")) {
|
|
71530
|
+
this.jumpToFirstPage();
|
|
71531
|
+
} else if (kb.matches(keyData, "cursorLineEnd")) {
|
|
71532
|
+
this.jumpToLastPage();
|
|
71311
71533
|
} else if (keyData === "e" || keyData === "E") {
|
|
71312
71534
|
this.toggleCollapse();
|
|
71313
71535
|
} else if (kb.matches(keyData, "selectConfirm")) {
|
|
@@ -72622,7 +72844,9 @@ function calculateSessionUsageTotals(messages) {
|
|
|
72622
72844
|
let output = 0;
|
|
72623
72845
|
let cacheRead = 0;
|
|
72624
72846
|
let cacheWrite = 0;
|
|
72847
|
+
let cacheWriteLong = 0;
|
|
72625
72848
|
let cost = 0;
|
|
72849
|
+
let costEstimated = false;
|
|
72626
72850
|
for (const message of messages) {
|
|
72627
72851
|
if (message.role !== "assistant") continue;
|
|
72628
72852
|
const usage = message.usage;
|
|
@@ -72631,9 +72855,11 @@ function calculateSessionUsageTotals(messages) {
|
|
|
72631
72855
|
output += usage.output;
|
|
72632
72856
|
cacheRead += usage.cacheRead;
|
|
72633
72857
|
cacheWrite += usage.cacheWrite;
|
|
72858
|
+
cacheWriteLong += usage.cacheWriteLong ?? 0;
|
|
72634
72859
|
cost += usage.cost?.total ?? 0;
|
|
72860
|
+
if (usage.cost?.cacheWriteLongEstimated === true) costEstimated = true;
|
|
72635
72861
|
}
|
|
72636
|
-
return { input, output, cacheRead, cacheWrite, cost };
|
|
72862
|
+
return { input, output, cacheRead, cacheWrite, cacheWriteLong, cacheWriteTotal: cacheWrite + cacheWriteLong, cost, costEstimated };
|
|
72637
72863
|
}
|
|
72638
72864
|
function formatTokensCompact(count) {
|
|
72639
72865
|
if (count < 1e3) return String(count);
|
|
@@ -72679,16 +72905,18 @@ ${options.theme.bold("Usage (active context)")}
|
|
|
72679
72905
|
info += `${options.theme.fg("dim", "Cache Read:")} ${totals.cacheRead.toLocaleString()}
|
|
72680
72906
|
`;
|
|
72681
72907
|
}
|
|
72682
|
-
if (totals.
|
|
72683
|
-
|
|
72908
|
+
if (totals.cacheWriteTotal > 0) {
|
|
72909
|
+
const split = totals.cacheWriteLong > 0 ? options.theme.fg("dim", ` (short ${totals.cacheWrite.toLocaleString()} \xB7 long ${totals.cacheWriteLong.toLocaleString()})`) : "";
|
|
72910
|
+
info += `${options.theme.fg("dim", "Cache Write:")} ${totals.cacheWriteTotal.toLocaleString()}${split}
|
|
72684
72911
|
`;
|
|
72685
72912
|
}
|
|
72686
72913
|
if (totals.cost > 0) {
|
|
72687
|
-
|
|
72914
|
+
const estimateNote = totals.costEstimated ? " (long-TTL estimate)" : "";
|
|
72915
|
+
info += `${options.theme.fg("dim", "Cost:")} $${totals.cost.toFixed(4)}${estimateNote}
|
|
72688
72916
|
`;
|
|
72689
72917
|
}
|
|
72690
|
-
const hitRateBase = totals.input + totals.cacheRead;
|
|
72691
|
-
if (hitRateBase > 0
|
|
72918
|
+
const hitRateBase = totals.input + totals.cacheRead + totals.cacheWriteTotal;
|
|
72919
|
+
if (hitRateBase > 0) {
|
|
72692
72920
|
const hitRate = (totals.cacheRead / hitRateBase * 100).toFixed(1);
|
|
72693
72921
|
info += `${options.theme.fg("dim", "Cache Hit Rate:")} ${hitRate}% (~${formatTokensCompact(hitRateBase)} served)
|
|
72694
72922
|
`;
|
|
@@ -72822,11 +73050,13 @@ async function loadSession(host, sessionId) {
|
|
|
72822
73050
|
outputTokens: contextUsage.output,
|
|
72823
73051
|
cacheRead: contextUsage.cacheRead,
|
|
72824
73052
|
cacheWrite: contextUsage.cacheWrite,
|
|
73053
|
+
cacheWriteLong: contextUsage.cacheWriteLong,
|
|
72825
73054
|
cost: contextUsage.cost,
|
|
73055
|
+
costEstimated: contextUsage.costEstimated,
|
|
72826
73056
|
contextPercent,
|
|
72827
73057
|
contextWindow
|
|
72828
73058
|
});
|
|
72829
|
-
|
|
73059
|
+
applyContextSignalsWithTrace(host);
|
|
72830
73060
|
host.ui.requestRender();
|
|
72831
73061
|
setTimeout(() => host.ui.requestRender(), 100);
|
|
72832
73062
|
} catch (error) {
|
|
@@ -73860,11 +74090,13 @@ function bindInteractiveRuntimeEvents(host) {
|
|
|
73860
74090
|
outputTokens: contextUsage.output,
|
|
73861
74091
|
cacheRead: contextUsage.cacheRead,
|
|
73862
74092
|
cacheWrite: contextUsage.cacheWrite,
|
|
74093
|
+
cacheWriteLong: contextUsage.cacheWriteLong,
|
|
73863
74094
|
cost: contextUsage.cost,
|
|
74095
|
+
costEstimated: contextUsage.costEstimated,
|
|
73864
74096
|
contextPercent,
|
|
73865
74097
|
contextWindow
|
|
73866
74098
|
});
|
|
73867
|
-
|
|
74099
|
+
applyContextSignalsWithTrace(host);
|
|
73868
74100
|
host.safeRequestRender();
|
|
73869
74101
|
host.sessionManager.save().catch((err) => {
|
|
73870
74102
|
console.error("[Session] Auto-save failed:", err);
|
|
@@ -74612,7 +74844,7 @@ function listDiscoveredSkills(host) {
|
|
|
74612
74844
|
function applyReloadedSkills(host, result) {
|
|
74613
74845
|
host.skills = result.skills.filter((skill) => host.options.settingsManager.isSkillEnabled(skill.name));
|
|
74614
74846
|
host.skillsSection = formatSkillsForPrompt(host.skills);
|
|
74615
|
-
host.applyRuntimeToolMode(
|
|
74847
|
+
host.applyRuntimeToolMode();
|
|
74616
74848
|
host.updateSystemPromptTools();
|
|
74617
74849
|
for (const skill of host.skills) {
|
|
74618
74850
|
const skillPath = ["skills", `skill:${skill.name}`];
|
|
@@ -74913,9 +75145,9 @@ function collectKnownToolNames(host) {
|
|
|
74913
75145
|
function describeToggleEffect(host, name, enabled) {
|
|
74914
75146
|
const loaded = collectKnownToolNames(host).active.includes(name);
|
|
74915
75147
|
if (enabled) {
|
|
74916
|
-
return loaded ? `Tool "${name}" enabled (active now).` : `Tool "${name}" enabled in ~/.pie/settings.json (loads on next start \u2014 it was not loaded this session).`;
|
|
75148
|
+
return loaded ? `Tool "${name}" enabled (saved to ~/.pie/settings.json; active now).` : `Tool "${name}" enabled in ~/.pie/settings.json (loads on next start \u2014 it was not loaded this session).`;
|
|
74917
75149
|
}
|
|
74918
|
-
return loaded ? `Tool "${name}" disabled (removed from this
|
|
75150
|
+
return loaded ? `Tool "${name}" disabled (saved to ~/.pie/settings.json; removed from this and future sessions).` : `Tool "${name}" disabled in ~/.pie/settings.json.`;
|
|
74919
75151
|
}
|
|
74920
75152
|
function showToolsManager(host) {
|
|
74921
75153
|
host.showSelector((done) => {
|
|
@@ -75020,7 +75252,7 @@ function handleToolsCommand(host, args) {
|
|
|
75020
75252
|
host.chatContainer.addChild(new Text(theme.fg("dim", " No tools available."), 1, 0));
|
|
75021
75253
|
}
|
|
75022
75254
|
for (const name of active) {
|
|
75023
|
-
const state = host.options.settingsManager.isToolEnabled(name) ? "enabled" : "disabled (removed
|
|
75255
|
+
const state = host.options.settingsManager.isToolEnabled(name) ? "enabled" : "disabled (saved to ~/.pie/settings.json; removed this session)";
|
|
75024
75256
|
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: ${state}`), 1, 0));
|
|
75025
75257
|
}
|
|
75026
75258
|
for (const name of disabled) {
|
|
@@ -75040,6 +75272,23 @@ function handleToolsCommand(host, args) {
|
|
|
75040
75272
|
var RESET2 = "\x1B[0m";
|
|
75041
75273
|
var INVERSE2 = "\x1B[7m";
|
|
75042
75274
|
var ROLE_FILTER_CYCLE = ["all", "user", "assistant", "toolResult", "compaction"];
|
|
75275
|
+
function buildWrappedLines(rawLines, contentWidth) {
|
|
75276
|
+
const width = Math.max(1, contentWidth);
|
|
75277
|
+
const lines = [];
|
|
75278
|
+
const sourceStart = [];
|
|
75279
|
+
for (const rawLine of rawLines) {
|
|
75280
|
+
sourceStart.push(lines.length);
|
|
75281
|
+
lines.push(...wrapTextWithAnsi(rawLine, width));
|
|
75282
|
+
}
|
|
75283
|
+
return { lines: lines.length > 0 ? lines : [""], sourceStart };
|
|
75284
|
+
}
|
|
75285
|
+
function anchorFor(scroll, sourceStart, sourceCount) {
|
|
75286
|
+
if (sourceStart.length === 0) return { source: 0, offset: 0 };
|
|
75287
|
+
const target = Math.max(0, Math.min(scroll, sourceCount - 1));
|
|
75288
|
+
let source = sourceStart.length - 1;
|
|
75289
|
+
while (source > 0 && sourceStart[source] > target) source -= 1;
|
|
75290
|
+
return { source, offset: target - sourceStart[source] };
|
|
75291
|
+
}
|
|
75043
75292
|
function createLine2(content, width, isSelected) {
|
|
75044
75293
|
const normalized = content.replace(/[\r\n]+/g, " ");
|
|
75045
75294
|
const body = isSelected ? INVERSE2 + normalized : normalized;
|
|
@@ -75180,12 +75429,33 @@ var ContextReportSelectorComponent = class {
|
|
|
75180
75429
|
this.views.push({
|
|
75181
75430
|
kind: "text",
|
|
75182
75431
|
title,
|
|
75183
|
-
|
|
75432
|
+
rawLines: text.replace(/\r\n/g, "\n").split("\n"),
|
|
75433
|
+
lines: [],
|
|
75434
|
+
sourceStart: [],
|
|
75435
|
+
wrapWidth: 0,
|
|
75184
75436
|
scroll: 0
|
|
75185
75437
|
});
|
|
75186
75438
|
this.selectedIndex = 0;
|
|
75187
75439
|
this.statusMessage = null;
|
|
75188
75440
|
}
|
|
75441
|
+
/** Re-wrap a text view for the current terminal width, preserving the anchor. */
|
|
75442
|
+
ensureTextWrapped(view, width) {
|
|
75443
|
+
const contentWidth = Math.max(1, width - 2);
|
|
75444
|
+
if (view.wrapWidth === contentWidth) return;
|
|
75445
|
+
const previousCount = view.lines.length;
|
|
75446
|
+
const anchor = view.wrapWidth > 0 && previousCount > 0 ? anchorFor(view.scroll, view.sourceStart, previousCount) : { source: 0, offset: 0 };
|
|
75447
|
+
const rebuilt = buildWrappedLines(view.rawLines, contentWidth);
|
|
75448
|
+
view.lines = rebuilt.lines;
|
|
75449
|
+
view.sourceStart = rebuilt.sourceStart;
|
|
75450
|
+
view.wrapWidth = contentWidth;
|
|
75451
|
+
const source = Math.min(anchor.source, Math.max(0, rebuilt.sourceStart.length - 1));
|
|
75452
|
+
const nextSourceStart = rebuilt.sourceStart[source + 1] ?? rebuilt.lines.length;
|
|
75453
|
+
const sourceLineCount = Math.max(1, nextSourceStart - rebuilt.sourceStart[source]);
|
|
75454
|
+
view.scroll = Math.min(
|
|
75455
|
+
Math.max(0, rebuilt.lines.length - 1),
|
|
75456
|
+
rebuilt.sourceStart[source] + Math.min(anchor.offset, sourceLineCount - 1)
|
|
75457
|
+
);
|
|
75458
|
+
}
|
|
75189
75459
|
drillIntoSelected() {
|
|
75190
75460
|
const view = this.currentView;
|
|
75191
75461
|
if (view.kind !== "list") return;
|
|
@@ -75367,6 +75637,8 @@ var ContextReportSelectorComponent = class {
|
|
|
75367
75637
|
)
|
|
75368
75638
|
);
|
|
75369
75639
|
} else {
|
|
75640
|
+
this.ensureTextWrapped(view, width);
|
|
75641
|
+
view.scroll = Math.max(0, Math.min(view.scroll, view.lines.length - 1));
|
|
75370
75642
|
const total = view.lines.length;
|
|
75371
75643
|
const start = Math.min(view.scroll, Math.max(0, total - 1));
|
|
75372
75644
|
const end = Math.min(start + this.maxVisibleLines, total);
|
|
@@ -75531,6 +75803,7 @@ function handleContextReportCommand(host) {
|
|
|
75531
75803
|
const usage = host.calculateContextUsage();
|
|
75532
75804
|
const contextWindow = host.options.model?.contextWindow ?? 0;
|
|
75533
75805
|
const reserveTokens = host.options.settingsManager.getAutoCompactReserveTokens();
|
|
75806
|
+
const autoCompactEnabled = host.options.settingsManager.getAutoCompactEnabled();
|
|
75534
75807
|
const autoCompactLimit = contextWindow > 0 ? getAutoCompactTokenLimit(contextWindow, reserveTokens) ?? null : null;
|
|
75535
75808
|
const prefixHash = computePromptPrefixHash(
|
|
75536
75809
|
systemPrompt,
|
|
@@ -75562,7 +75835,11 @@ function handleContextReportCommand(host) {
|
|
|
75562
75835
|
entries,
|
|
75563
75836
|
compactionTokensBefore: (entryId) => host.sessionManager.getEntry(entryId)?.compactionData?.tokensBefore,
|
|
75564
75837
|
contextWindow,
|
|
75565
|
-
|
|
75838
|
+
estimatedCurrentTokens: usage.estimatedCurrentTokens,
|
|
75839
|
+
providerMeasuredTokens: usage.providerMeasuredTokens,
|
|
75840
|
+
providerMeasuredAt: usage.providerMeasuredAt,
|
|
75841
|
+
measurementMatchesCurrentContext: usage.measurementMatchesCurrentContext,
|
|
75842
|
+
autoCompactEnabled,
|
|
75566
75843
|
autoCompactLimitTokens: autoCompactLimit,
|
|
75567
75844
|
reserveTokens,
|
|
75568
75845
|
promptPrefixHash: prefixHash,
|
|
@@ -76394,11 +76671,13 @@ async function handleClearCommand(host) {
|
|
|
76394
76671
|
outputTokens: contextUsage.output,
|
|
76395
76672
|
cacheRead: contextUsage.cacheRead,
|
|
76396
76673
|
cacheWrite: contextUsage.cacheWrite,
|
|
76674
|
+
cacheWriteLong: contextUsage.cacheWriteLong,
|
|
76397
76675
|
cost: contextUsage.cost,
|
|
76676
|
+
costEstimated: contextUsage.costEstimated,
|
|
76398
76677
|
contextPercent: contextWindow > 0 && contextUsage.tokens !== null ? contextUsage.tokens / contextWindow * 100 : 0,
|
|
76399
76678
|
contextWindow
|
|
76400
76679
|
});
|
|
76401
|
-
|
|
76680
|
+
applyContextSignalsWithTrace(host);
|
|
76402
76681
|
host.updateTerminalTitle();
|
|
76403
76682
|
host.chatContainer.clear();
|
|
76404
76683
|
host.streamingComponent = void 0;
|
|
@@ -76487,7 +76766,10 @@ function createExtensionContextForCommands(host) {
|
|
|
76487
76766
|
console.error(`[Extension] Tools restricted to: ${tools.join(", ")}`);
|
|
76488
76767
|
}
|
|
76489
76768
|
},
|
|
76490
|
-
getActiveTools: () =>
|
|
76769
|
+
getActiveTools: () => {
|
|
76770
|
+
const tools = host.agent.state.tools;
|
|
76771
|
+
return (host.planModeEnabled ? tools.filter((tool) => isToolAllowedInPlanMode(tool)) : tools).map((tool) => tool.name);
|
|
76772
|
+
},
|
|
76491
76773
|
sendUserMessage: (content) => {
|
|
76492
76774
|
if (host.editor.onSubmit) {
|
|
76493
76775
|
void host.editor.onSubmit(content);
|
|
@@ -76754,11 +77036,16 @@ async function handleCompactCommand(host) {
|
|
|
76754
77036
|
host.showStatus("Nothing to compact yet");
|
|
76755
77037
|
return;
|
|
76756
77038
|
}
|
|
76757
|
-
const
|
|
76758
|
-
|
|
77039
|
+
const preparation = prepareSessionCompaction({
|
|
77040
|
+
sessionManager: host.sessionManager,
|
|
77041
|
+
messages: existingMessages,
|
|
77042
|
+
budgetTokens: host.options.model?.contextWindow
|
|
77043
|
+
});
|
|
77044
|
+
if (preparation.entries.length === 0) {
|
|
76759
77045
|
host.showStatus("Need at least one real user message before compacting");
|
|
76760
77046
|
return;
|
|
76761
77047
|
}
|
|
77048
|
+
const tokensBefore = calculateTotalTokens(preparation.messages);
|
|
76762
77049
|
const compactOptions = {
|
|
76763
77050
|
model: host.options.model,
|
|
76764
77051
|
apiKey: host.options.apiKey,
|
|
@@ -76777,13 +77064,31 @@ async function handleCompactCommand(host) {
|
|
|
76777
77064
|
if (beforeCompact?.summary) {
|
|
76778
77065
|
summary = beforeCompact.summary;
|
|
76779
77066
|
} else {
|
|
76780
|
-
summary = await createCompactionSummary(
|
|
77067
|
+
summary = await createCompactionSummary(preparation.messages, compactOptions);
|
|
76781
77068
|
}
|
|
76782
|
-
const
|
|
76783
|
-
|
|
77069
|
+
const verified = verifyPreparedCompactionCommit({
|
|
77070
|
+
preparation,
|
|
77071
|
+
sessionManager: host.sessionManager,
|
|
77072
|
+
messages: host.agent.state.messages,
|
|
77073
|
+
result: { summary, retainedTail: preparation.retainedTail.retainedTail, tokensBefore }
|
|
77074
|
+
});
|
|
77075
|
+
if (verified.ok === false) {
|
|
77076
|
+
if (verified.kind === "stale") {
|
|
77077
|
+
host.showStatus("Session changed during compaction; nothing was published");
|
|
77078
|
+
return;
|
|
77079
|
+
}
|
|
77080
|
+
throw new Error(`Compaction abandoned: ${verified.reason}`);
|
|
77081
|
+
}
|
|
77082
|
+
host.sessionManager.appendCompactionCheckpoint({
|
|
77083
|
+
summary,
|
|
77084
|
+
retainedTail: verified.retainedTail,
|
|
77085
|
+
tokensBefore,
|
|
77086
|
+
excludeFailure: preparation.excludedFailure
|
|
77087
|
+
});
|
|
76784
77088
|
const compactedMessages = host.sessionManager.getMessages();
|
|
76785
77089
|
host.replaceAgentMessagesAndMarkSynced(compactedMessages);
|
|
76786
77090
|
host.resetFileObservationState();
|
|
77091
|
+
host.resetRuntimeModeBlocks?.();
|
|
76787
77092
|
host.streamingComponent = void 0;
|
|
76788
77093
|
host.pendingTools.clear();
|
|
76789
77094
|
host.chatContainer.clear();
|
|
@@ -76804,11 +77109,13 @@ async function handleCompactCommand(host) {
|
|
|
76804
77109
|
outputTokens: contextUsage.output,
|
|
76805
77110
|
cacheRead: contextUsage.cacheRead,
|
|
76806
77111
|
cacheWrite: contextUsage.cacheWrite,
|
|
77112
|
+
cacheWriteLong: contextUsage.cacheWriteLong,
|
|
76807
77113
|
cost: contextUsage.cost,
|
|
77114
|
+
costEstimated: contextUsage.costEstimated,
|
|
76808
77115
|
contextPercent,
|
|
76809
77116
|
contextWindow
|
|
76810
77117
|
});
|
|
76811
|
-
|
|
77118
|
+
applyContextSignalsWithTrace(host);
|
|
76812
77119
|
await host.sessionManager.save();
|
|
76813
77120
|
host.safeRequestRender();
|
|
76814
77121
|
} catch (error) {
|
|
@@ -78927,8 +79234,12 @@ function queueMessage(host, text, mode, options = {}) {
|
|
|
78927
79234
|
}
|
|
78928
79235
|
const clearEditor = options.clearEditor ?? true;
|
|
78929
79236
|
host.sessionTrace.notePendingUserText(text);
|
|
79237
|
+
const runtimeBlock = host.runtimeModeBlockForNextMessage?.();
|
|
79238
|
+
const content = runtimeBlock ? `${runtimeBlock}
|
|
79239
|
+
|
|
79240
|
+
${text}` : text;
|
|
78930
79241
|
void host.agentSessionController.prompt(
|
|
78931
|
-
{ role: "user", content
|
|
79242
|
+
{ role: "user", content, timestamp: Date.now() },
|
|
78932
79243
|
{
|
|
78933
79244
|
source: "interactive",
|
|
78934
79245
|
streamingBehavior: mode,
|
|
@@ -79183,8 +79494,12 @@ var FooterComponent = class {
|
|
|
79183
79494
|
if (state.inputTokens) statsParts.push(`\u2191${formatTokens(state.inputTokens)}`);
|
|
79184
79495
|
if (state.outputTokens) statsParts.push(`\u2193${formatTokens(state.outputTokens)}`);
|
|
79185
79496
|
if (state.cacheRead) statsParts.push(`R${formatTokens(state.cacheRead)}`);
|
|
79186
|
-
|
|
79187
|
-
|
|
79497
|
+
const cacheWriteShort = state.cacheWrite ?? 0;
|
|
79498
|
+
const cacheWriteLong = state.cacheWriteLong ?? 0;
|
|
79499
|
+
const cacheWriteTotal = cacheWriteShort + cacheWriteLong;
|
|
79500
|
+
if (cacheWriteTotal) statsParts.push(`W${formatTokens(cacheWriteTotal)}`);
|
|
79501
|
+
if (cacheWriteLong) statsParts.push(`W1h${formatTokens(cacheWriteLong)}`);
|
|
79502
|
+
if (state.cost) statsParts.push(`${state.costEstimated ? "~" : ""}$${state.cost.toFixed(3)}`);
|
|
79188
79503
|
if (state.cacheHitRate != null) {
|
|
79189
79504
|
statsParts.push(theme.fg("dim", `ca ${(state.cacheHitRate * 100).toFixed(0)}%`));
|
|
79190
79505
|
}
|
|
@@ -79334,13 +79649,23 @@ function calculateCliContextUsage(params) {
|
|
|
79334
79649
|
const estimate = estimateContextTokens(messages);
|
|
79335
79650
|
const usageMessage = estimate.lastUsageIndex !== null ? messages[estimate.lastUsageIndex] : void 0;
|
|
79336
79651
|
const usage = usageMessage?.role === "assistant" ? usageMessage.usage : void 0;
|
|
79652
|
+
const hasProviderMeasurement = usage !== void 0 && estimate.lastUsageIndex !== null;
|
|
79337
79653
|
return {
|
|
79338
79654
|
tokens: estimate.tokens,
|
|
79655
|
+
estimatedCurrentTokens: estimate.tokens,
|
|
79656
|
+
providerMeasuredTokens: hasProviderMeasurement ? estimate.providerTokens : null,
|
|
79657
|
+
providerMeasuredAt: hasProviderMeasurement && usageMessage ? usageMessage.timestamp : null,
|
|
79658
|
+
// A provider total describes the context AT that response. Any trailing
|
|
79659
|
+
// tool/user message (or a compaction reset, which zeroes stale usage)
|
|
79660
|
+
// makes the two figures different snapshots, so no error may be shown.
|
|
79661
|
+
measurementMatchesCurrentContext: hasProviderMeasurement && estimate.lastUsageIndex === messages.length - 1,
|
|
79339
79662
|
input: usage?.input ?? 0,
|
|
79340
79663
|
output: usage?.output ?? 0,
|
|
79341
79664
|
cacheRead: usage?.cacheRead ?? 0,
|
|
79342
79665
|
cacheWrite: usage?.cacheWrite ?? 0,
|
|
79343
|
-
|
|
79666
|
+
cacheWriteLong: usage?.cacheWriteLong ?? 0,
|
|
79667
|
+
cost: usage?.cost.total ?? 0,
|
|
79668
|
+
costEstimated: usage?.cost?.cacheWriteLongEstimated === true
|
|
79344
79669
|
};
|
|
79345
79670
|
}
|
|
79346
79671
|
function createCliAutoCompactDecision(params) {
|
|
@@ -79371,6 +79696,11 @@ function shouldCliAutoCompactTokens(params) {
|
|
|
79371
79696
|
const tokenLimit = getAutoCompactTokenLimit(params.contextWindow, params.reserveTokens);
|
|
79372
79697
|
return tokenLimit !== void 0 && params.tokens > tokenLimit;
|
|
79373
79698
|
}
|
|
79699
|
+
function createCliCompactionBudget(params) {
|
|
79700
|
+
const contextWindow = params.contextWindow ?? 0;
|
|
79701
|
+
const reserveTokens = params.reserveTokens ?? DEFAULT_COMPACTION_CONFIG.reserveTokens;
|
|
79702
|
+
return () => getAutoCompactTokenLimit(contextWindow, reserveTokens);
|
|
79703
|
+
}
|
|
79374
79704
|
async function createCliAutoCompactionResult(params) {
|
|
79375
79705
|
if (params.context.signal?.aborted) {
|
|
79376
79706
|
return { aborted: true };
|
|
@@ -79379,8 +79709,9 @@ async function createCliAutoCompactionResult(params) {
|
|
|
79379
79709
|
if (!activeEntryId) {
|
|
79380
79710
|
return { aborted: true };
|
|
79381
79711
|
}
|
|
79382
|
-
const
|
|
79383
|
-
|
|
79712
|
+
const legacyCutId = params.context.preparation ? null : findFirstKeptEntrySummaryId(params.context.sessionManager.getActiveContextSummaries());
|
|
79713
|
+
const retainedTail = params.context.preparation ? params.context.preparation.retainedTail.retainedTail : legacyCutId ? { kind: "from-entry", entryId: legacyCutId } : void 0;
|
|
79714
|
+
if (!retainedTail) {
|
|
79384
79715
|
return { aborted: true };
|
|
79385
79716
|
}
|
|
79386
79717
|
const compactOptions = {
|
|
@@ -79395,7 +79726,8 @@ async function createCliAutoCompactionResult(params) {
|
|
|
79395
79726
|
}
|
|
79396
79727
|
return {
|
|
79397
79728
|
summary,
|
|
79398
|
-
|
|
79729
|
+
retainedTail,
|
|
79730
|
+
...retainedTail.kind === "from-entry" ? { firstKeptEntryId: retainedTail.entryId } : {},
|
|
79399
79731
|
tokensBefore: calculateTotalTokens(params.context.messages)
|
|
79400
79732
|
};
|
|
79401
79733
|
}
|
|
@@ -79556,7 +79888,20 @@ function createCliRetryPolicy(isRetryableErrorOverride) {
|
|
|
79556
79888
|
function calculateContextUsage(host) {
|
|
79557
79889
|
const messages = host.agent?.state.messages ?? [];
|
|
79558
79890
|
if (messages.length === 0) {
|
|
79559
|
-
return {
|
|
79891
|
+
return {
|
|
79892
|
+
tokens: 0,
|
|
79893
|
+
estimatedCurrentTokens: 0,
|
|
79894
|
+
providerMeasuredTokens: null,
|
|
79895
|
+
providerMeasuredAt: null,
|
|
79896
|
+
measurementMatchesCurrentContext: false,
|
|
79897
|
+
input: 0,
|
|
79898
|
+
output: 0,
|
|
79899
|
+
cacheRead: 0,
|
|
79900
|
+
cacheWrite: 0,
|
|
79901
|
+
cacheWriteLong: 0,
|
|
79902
|
+
cost: 0,
|
|
79903
|
+
costEstimated: false
|
|
79904
|
+
};
|
|
79560
79905
|
}
|
|
79561
79906
|
return calculateCliContextUsage({
|
|
79562
79907
|
messages,
|
|
@@ -80307,6 +80652,9 @@ function createInteractiveAgentSessionController(host) {
|
|
|
80307
80652
|
}
|
|
80308
80653
|
return void 0;
|
|
80309
80654
|
},
|
|
80655
|
+
// Same auto-compact limit the threshold decision uses; a checkpoint whose
|
|
80656
|
+
// summary + retained tail would still exceed it is refused.
|
|
80657
|
+
getCompactionBudgetTokens: createCliCompactionBudget({ contextWindow: host.options.model?.contextWindow }),
|
|
80310
80658
|
getAutoContinueMessage: () => host.getTodoAutoContinueMessage(),
|
|
80311
80659
|
classifyFailure: (context) => classifyCliFailure(context),
|
|
80312
80660
|
retry: createCliRetryPolicy(
|
|
@@ -80324,9 +80672,16 @@ function createInteractiveAgentSessionController(host) {
|
|
|
80324
80672
|
return { aborted: true };
|
|
80325
80673
|
}
|
|
80326
80674
|
if (beforeCompact?.summary) {
|
|
80327
|
-
const
|
|
80328
|
-
|
|
80329
|
-
|
|
80675
|
+
const retainedTail = context.preparation?.retainedTail.retainedTail ?? (() => {
|
|
80676
|
+
const legacyCutId = findFirstKeptEntrySummaryId(context.sessionManager.getActiveContextSummaries());
|
|
80677
|
+
return legacyCutId ? { kind: "from-entry", entryId: legacyCutId } : void 0;
|
|
80678
|
+
})();
|
|
80679
|
+
if (!retainedTail) return { aborted: true };
|
|
80680
|
+
return {
|
|
80681
|
+
summary: beforeCompact.summary,
|
|
80682
|
+
retainedTail,
|
|
80683
|
+
...retainedTail.kind === "from-entry" ? { firstKeptEntryId: retainedTail.entryId } : {}
|
|
80684
|
+
};
|
|
80330
80685
|
}
|
|
80331
80686
|
autoCompactBeforeStats = summarizeActiveContext(context.sessionManager.getActiveContextSummaries());
|
|
80332
80687
|
return createCliAutoCompactionResult({
|
|
@@ -80488,6 +80843,13 @@ function createInteractiveAgentSessionController(host) {
|
|
|
80488
80843
|
host.isProcessing = true;
|
|
80489
80844
|
host.footer.setState({ status: "processing", lifecycleEvent: "auto_compact" });
|
|
80490
80845
|
host.showStatus(event.reason === "overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context...");
|
|
80846
|
+
} else if (event.type === "compaction_committed") {
|
|
80847
|
+
host.resetFileObservationState();
|
|
80848
|
+
host.resetRuntimeModeBlocks?.();
|
|
80849
|
+
host.sessionTrace.noteRuntimeEvent("compaction_committed", {
|
|
80850
|
+
reason: event.reason,
|
|
80851
|
+
willRetry: event.willRetry
|
|
80852
|
+
});
|
|
80491
80853
|
} else if (event.type === "auto_compaction_end") {
|
|
80492
80854
|
host.isCompacting = false;
|
|
80493
80855
|
host.isProcessing = false;
|
|
@@ -80500,7 +80862,6 @@ function createInteractiveAgentSessionController(host) {
|
|
|
80500
80862
|
autoCompactBeforeStats = null;
|
|
80501
80863
|
return;
|
|
80502
80864
|
}
|
|
80503
|
-
host.resetFileObservationState();
|
|
80504
80865
|
if (!event.result?.aborted) {
|
|
80505
80866
|
host.streamingComponent = void 0;
|
|
80506
80867
|
host.pendingTools.clear();
|
|
@@ -80519,11 +80880,13 @@ function createInteractiveAgentSessionController(host) {
|
|
|
80519
80880
|
outputTokens: contextUsage.output,
|
|
80520
80881
|
cacheRead: contextUsage.cacheRead,
|
|
80521
80882
|
cacheWrite: contextUsage.cacheWrite,
|
|
80883
|
+
cacheWriteLong: contextUsage.cacheWriteLong,
|
|
80522
80884
|
cost: contextUsage.cost,
|
|
80885
|
+
costEstimated: contextUsage.costEstimated,
|
|
80523
80886
|
contextPercent,
|
|
80524
80887
|
contextWindow
|
|
80525
80888
|
});
|
|
80526
|
-
|
|
80889
|
+
applyContextSignalsWithTrace(host);
|
|
80527
80890
|
host.safeRequestRender();
|
|
80528
80891
|
if (!event.result?.aborted) {
|
|
80529
80892
|
if (autoCompactBeforeStats !== null) {
|
|
@@ -80552,94 +80915,80 @@ function createInteractiveAgentSessionController(host) {
|
|
|
80552
80915
|
}
|
|
80553
80916
|
|
|
80554
80917
|
// src/runtime/runtime-mode-context.ts
|
|
80555
|
-
|
|
80556
|
-
|
|
80557
|
-
var STALE_SYSTEM_REMINDER_RE = /<system-reminder>\s*# Plan Mode[\s\S]*?<\/system-reminder>\s*/gi;
|
|
80558
|
-
var STALE_RUNTIME_CONTEXT_RE = /<runtime-mode-context>[\s\S]*?<\/runtime-mode-context>\s*/gi;
|
|
80559
|
-
function isRecord3(value) {
|
|
80560
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
80918
|
+
function isAgentMessage(value) {
|
|
80919
|
+
return !!value && typeof value === "object" && "role" in value;
|
|
80561
80920
|
}
|
|
80562
|
-
function
|
|
80563
|
-
|
|
80564
|
-
|
|
80565
|
-
|
|
80566
|
-
|
|
80567
|
-
|
|
80568
|
-
const withoutPlanReminder = withoutRuntime.replace(STALE_SYSTEM_REMINDER_RE, () => {
|
|
80569
|
-
stripped++;
|
|
80570
|
-
return "";
|
|
80571
|
-
});
|
|
80572
|
-
return { text: withoutPlanReminder, stripped };
|
|
80573
|
-
}
|
|
80574
|
-
function stripUserMessage(message) {
|
|
80575
|
-
if (!isRecord3(message) || message.role !== "user") {
|
|
80576
|
-
return { message, stripped: 0 };
|
|
80921
|
+
function prependRuntimeModeBlockToPrompt(input, block) {
|
|
80922
|
+
if (!block) return input;
|
|
80923
|
+
if (typeof input === "string") {
|
|
80924
|
+
return input.trim() ? `${block}
|
|
80925
|
+
|
|
80926
|
+
${input}` : block;
|
|
80577
80927
|
}
|
|
80578
|
-
|
|
80579
|
-
|
|
80580
|
-
|
|
80581
|
-
|
|
80582
|
-
return {
|
|
80583
|
-
message: {
|
|
80584
|
-
...message,
|
|
80585
|
-
content: cleaned.text
|
|
80586
|
-
},
|
|
80587
|
-
stripped: cleaned.stripped
|
|
80588
|
-
};
|
|
80928
|
+
if (Array.isArray(input)) {
|
|
80929
|
+
if (input.length > 0 && isAgentMessage(input[0])) {
|
|
80930
|
+
return prependBlockToMessages(input, block);
|
|
80931
|
+
}
|
|
80932
|
+
return [{ type: "text", text: block }, ...input];
|
|
80589
80933
|
}
|
|
80590
|
-
if (
|
|
80591
|
-
return
|
|
80592
|
-
}
|
|
80593
|
-
|
|
80594
|
-
const nextContent = content.map((block) => {
|
|
80595
|
-
if (!isRecord3(block) || block.type !== "text" || typeof block.text !== "string") {
|
|
80596
|
-
return block;
|
|
80597
|
-
}
|
|
80598
|
-
const cleaned = cleanText(block.text);
|
|
80599
|
-
stripped += cleaned.stripped;
|
|
80600
|
-
return { ...block, text: cleaned.text };
|
|
80601
|
-
}).filter((block) => !(isRecord3(block) && block.type === "text" && String(block.text ?? "").length === 0));
|
|
80602
|
-
if (stripped === 0) return { message, stripped: 0 };
|
|
80603
|
-
return {
|
|
80604
|
-
message: {
|
|
80605
|
-
...message,
|
|
80606
|
-
content: nextContent
|
|
80607
|
-
},
|
|
80608
|
-
stripped
|
|
80609
|
-
};
|
|
80934
|
+
if (isAgentMessage(input)) {
|
|
80935
|
+
return prependBlockToMessages([input], block)[0];
|
|
80936
|
+
}
|
|
80937
|
+
return [{ type: "text", text: block }, ...input];
|
|
80610
80938
|
}
|
|
80611
|
-
function
|
|
80612
|
-
|
|
80613
|
-
|
|
80614
|
-
for (
|
|
80615
|
-
|
|
80616
|
-
|
|
80617
|
-
|
|
80618
|
-
const content = result.message.content;
|
|
80619
|
-
if (typeof content === "string" && content.trim().length === 0) {
|
|
80620
|
-
continue;
|
|
80621
|
-
}
|
|
80622
|
-
if (Array.isArray(content) && content.length === 0) {
|
|
80623
|
-
continue;
|
|
80624
|
-
}
|
|
80939
|
+
function prependBlockToMessages(messages, block) {
|
|
80940
|
+
const next = [...messages];
|
|
80941
|
+
let target = -1;
|
|
80942
|
+
for (let index = next.length - 1; index >= 0; index--) {
|
|
80943
|
+
if (next[index]?.role === "user") {
|
|
80944
|
+
target = index;
|
|
80945
|
+
break;
|
|
80625
80946
|
}
|
|
80626
|
-
nextMessages.push(result.message);
|
|
80627
80947
|
}
|
|
80628
|
-
|
|
80948
|
+
if (target < 0) {
|
|
80949
|
+
next.push({ role: "user", content: block, timestamp: Date.now() });
|
|
80950
|
+
return next;
|
|
80951
|
+
}
|
|
80952
|
+
const message = next[target];
|
|
80953
|
+
if (typeof message.content === "string") {
|
|
80954
|
+
next[target] = { ...message, content: `${block}
|
|
80955
|
+
|
|
80956
|
+
${message.content}` };
|
|
80957
|
+
} else if (Array.isArray(message.content)) {
|
|
80958
|
+
next[target] = { ...message, content: [{ type: "text", text: block }, ...message.content] };
|
|
80959
|
+
} else {
|
|
80960
|
+
next.splice(target, 0, { role: "user", content: block, timestamp: Date.now() });
|
|
80961
|
+
}
|
|
80962
|
+
return next;
|
|
80629
80963
|
}
|
|
80964
|
+
var RUNTIME_MODE_CONTEXT_MARKER = "<runtime-mode-context>";
|
|
80965
|
+
var RUNTIME_MODE_CONTEXT_END_MARKER = "</runtime-mode-context>";
|
|
80630
80966
|
function buildRuntimeModeContext(state) {
|
|
80631
80967
|
const lines = [
|
|
80632
80968
|
RUNTIME_MODE_CONTEXT_MARKER,
|
|
80633
|
-
"Current runtime mode:"
|
|
80634
|
-
|
|
80969
|
+
"Current runtime mode:"
|
|
80970
|
+
];
|
|
80971
|
+
if (state.planMode === "planning") {
|
|
80972
|
+
lines.push(
|
|
80973
|
+
"- Plan mode: active (workspace read-only; plan_scratch permits session-local temporary drafts; submit the finished plan by calling plan_submit with the ordered steps for user approval)."
|
|
80974
|
+
);
|
|
80975
|
+
if (state.planDisabledToolNames.length > 0) {
|
|
80976
|
+
lines.push(
|
|
80977
|
+
`- Disabled this turn by plan mode (calls are denied): ${state.planDisabledToolNames.join(", ")}. Do not call them while planning.`
|
|
80978
|
+
);
|
|
80979
|
+
}
|
|
80980
|
+
} else {
|
|
80981
|
+
lines.push("- Plan mode: off.");
|
|
80982
|
+
}
|
|
80983
|
+
lines.push(
|
|
80635
80984
|
`- YOLO mode: ${state.yoloMode ? "on (filesystem sandbox directory restrictions are disabled)" : "off (workspace/protected-path restrictions apply)"}.`,
|
|
80636
80985
|
`- Filesystem scope: ${state.filesystemScope === "all" ? "all local paths may be passed directly to file tools when permitted" : "workspace paths and configured safe roots only"}.`
|
|
80637
|
-
|
|
80986
|
+
);
|
|
80638
80987
|
if (state.pendingTransition) {
|
|
80639
80988
|
const transitionText = {
|
|
80640
80989
|
entered_yolo: "YOLO mode was just enabled for this turn.",
|
|
80641
80990
|
exited_yolo: "YOLO mode was just disabled; do not assume previous absolute-path access still applies.",
|
|
80642
|
-
entered_plan: "Plan mode was just enabled; analyze and plan without changing the workspace. Use plan_scratch for temporary drafts.",
|
|
80991
|
+
entered_plan: "Plan mode was just enabled; analyze and plan without changing the workspace. Use plan_scratch for temporary drafts, then submit the finished plan by calling plan_submit with the ordered steps for user approval.",
|
|
80643
80992
|
exited_plan: "Plan mode was just disabled; execution tools may be used when the task requires them."
|
|
80644
80993
|
};
|
|
80645
80994
|
lines.push(`- Transition: ${transitionText[state.pendingTransition]}`);
|
|
@@ -80653,44 +81002,195 @@ function buildRuntimeModeContext(state) {
|
|
|
80653
81002
|
lines.push(RUNTIME_MODE_CONTEXT_END_MARKER);
|
|
80654
81003
|
return lines.join("\n");
|
|
80655
81004
|
}
|
|
80656
|
-
function
|
|
80657
|
-
|
|
81005
|
+
function runtimeModeBlockKey(state) {
|
|
81006
|
+
return JSON.stringify({
|
|
81007
|
+
planMode: state.planMode,
|
|
81008
|
+
yoloMode: state.yoloMode,
|
|
81009
|
+
filesystemScope: state.filesystemScope,
|
|
81010
|
+
currentDate: state.currentDate ?? null,
|
|
81011
|
+
activeToolNames: state.activeToolNames,
|
|
81012
|
+
planDisabledToolNames: state.planDisabledToolNames
|
|
81013
|
+
});
|
|
81014
|
+
}
|
|
81015
|
+
function shouldInjectRuntimeModeBlock(lastKey, state) {
|
|
81016
|
+
if (lastKey === null) return true;
|
|
81017
|
+
return runtimeModeBlockKey(state) !== lastKey;
|
|
81018
|
+
}
|
|
81019
|
+
function runtimeModeTraceData(state) {
|
|
81020
|
+
return {
|
|
81021
|
+
yoloMode: state.yoloMode,
|
|
81022
|
+
planMode: state.planMode,
|
|
81023
|
+
filesystemScope: state.filesystemScope,
|
|
81024
|
+
pendingTransition: state.pendingTransition,
|
|
81025
|
+
currentDate: state.currentDate,
|
|
81026
|
+
timeZone: state.timeZone,
|
|
81027
|
+
activeToolCount: state.activeToolNames.length,
|
|
81028
|
+
planDisabledToolCount: state.planDisabledToolNames.length
|
|
81029
|
+
};
|
|
81030
|
+
}
|
|
81031
|
+
function currentDateInZone(timeZone) {
|
|
81032
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
81033
|
+
year: "numeric",
|
|
81034
|
+
month: "2-digit",
|
|
81035
|
+
day: "2-digit",
|
|
81036
|
+
timeZone
|
|
81037
|
+
}).formatToParts(/* @__PURE__ */ new Date());
|
|
81038
|
+
const part = (type) => parts.find((p) => p.type === type)?.value ?? "00";
|
|
81039
|
+
return `${part("year")}-${part("month")}-${part("day")}`;
|
|
81040
|
+
}
|
|
81041
|
+
var RUNTIME_MODE_BLOCK_START_MARKER = "<runtime-mode-context>";
|
|
81042
|
+
function leadingRuntimeBlock(text) {
|
|
81043
|
+
const withoutLeadingWhitespace = text.replace(/^[\t ]+/, "");
|
|
81044
|
+
if (!withoutLeadingWhitespace.startsWith(RUNTIME_MODE_BLOCK_START_MARKER)) return null;
|
|
81045
|
+
const markerStart = text.length - withoutLeadingWhitespace.length;
|
|
81046
|
+
const endIndex = text.indexOf(RUNTIME_MODE_CONTEXT_END_MARKER, markerStart);
|
|
81047
|
+
if (endIndex < 0) return null;
|
|
81048
|
+
const block = text.slice(markerStart, endIndex + RUNTIME_MODE_CONTEXT_END_MARKER.length);
|
|
81049
|
+
const rest = text.slice(endIndex + RUNTIME_MODE_CONTEXT_END_MARKER.length).replace(/^[\t ]*(?:\r?\n){0,2}/, "");
|
|
81050
|
+
return { block, rest };
|
|
81051
|
+
}
|
|
81052
|
+
function stripLeadingRuntimeBlock(text) {
|
|
81053
|
+
const leading = leadingRuntimeBlock(text);
|
|
81054
|
+
return leading ? { rest: leading.rest } : null;
|
|
81055
|
+
}
|
|
81056
|
+
function leadingRuntimeBlockOfMessage(message) {
|
|
81057
|
+
if (message.role !== "user") return null;
|
|
81058
|
+
const content = message.content;
|
|
81059
|
+
if (typeof content === "string") return leadingRuntimeBlock(content)?.block ?? null;
|
|
81060
|
+
if (!Array.isArray(content)) return null;
|
|
81061
|
+
const first = content[0];
|
|
81062
|
+
if (first?.type !== "text" || typeof first.text !== "string") return null;
|
|
81063
|
+
return leadingRuntimeBlock(first.text)?.block ?? null;
|
|
81064
|
+
}
|
|
81065
|
+
function lastUserMessageCarriesRuntimeBlock(messages, block) {
|
|
81066
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
80658
81067
|
const message = messages[index];
|
|
80659
|
-
if (
|
|
80660
|
-
|
|
80661
|
-
}
|
|
81068
|
+
if (message?.role !== "user") continue;
|
|
81069
|
+
return leadingRuntimeBlockOfMessage(message) === block;
|
|
80662
81070
|
}
|
|
80663
|
-
return
|
|
81071
|
+
return false;
|
|
80664
81072
|
}
|
|
80665
|
-
function
|
|
80666
|
-
const
|
|
80667
|
-
|
|
80668
|
-
|
|
80669
|
-
|
|
80670
|
-
|
|
80671
|
-
|
|
80672
|
-
|
|
80673
|
-
|
|
81073
|
+
function applyRuntimeBlockToText(text, block) {
|
|
81074
|
+
const split = stripLeadingRuntimeBlock(text);
|
|
81075
|
+
const rest = split ? split.rest : text;
|
|
81076
|
+
const next = rest.length > 0 ? `${block}
|
|
81077
|
+
|
|
81078
|
+
${rest}` : block;
|
|
81079
|
+
return next === text ? text : next;
|
|
81080
|
+
}
|
|
81081
|
+
function applyRuntimeBlockToContentArray(content, block) {
|
|
81082
|
+
const first = content[0];
|
|
81083
|
+
if (first && typeof first === "object" && first.type === "text" && typeof first.text === "string") {
|
|
81084
|
+
const text = first.text;
|
|
81085
|
+
if (stripLeadingRuntimeBlock(text)) {
|
|
81086
|
+
const nextText = applyRuntimeBlockToText(text, block);
|
|
81087
|
+
if (nextText === text) return content;
|
|
81088
|
+
const copy = [...content];
|
|
81089
|
+
copy[0] = { ...first, text: nextText };
|
|
81090
|
+
return copy;
|
|
81091
|
+
}
|
|
80674
81092
|
}
|
|
80675
|
-
return [
|
|
80676
|
-
...messages.slice(0, latestUserIndex),
|
|
80677
|
-
contextMessage,
|
|
80678
|
-
...messages.slice(latestUserIndex)
|
|
80679
|
-
];
|
|
81093
|
+
return [{ type: "text", text: block }, ...content];
|
|
80680
81094
|
}
|
|
80681
|
-
function
|
|
80682
|
-
|
|
80683
|
-
const
|
|
80684
|
-
if (
|
|
80685
|
-
|
|
81095
|
+
function refreshRuntimeModeBlockOnLastUserMessage(messages, block) {
|
|
81096
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
81097
|
+
const message = messages[i];
|
|
81098
|
+
if (message?.role !== "user") continue;
|
|
81099
|
+
const content = message.content;
|
|
81100
|
+
if (typeof content === "string") {
|
|
81101
|
+
const next = applyRuntimeBlockToText(content, block);
|
|
81102
|
+
if (next === content) return messages;
|
|
81103
|
+
const copy = [...messages];
|
|
81104
|
+
copy[i] = { ...message, content: next };
|
|
81105
|
+
return copy;
|
|
81106
|
+
}
|
|
81107
|
+
if (Array.isArray(content)) {
|
|
81108
|
+
const next = applyRuntimeBlockToContentArray(content, block);
|
|
81109
|
+
if (next === content) return messages;
|
|
81110
|
+
const copy = [...messages];
|
|
81111
|
+
copy[i] = { ...message, content: next };
|
|
81112
|
+
return copy;
|
|
80686
81113
|
}
|
|
80687
|
-
|
|
80688
|
-
|
|
80689
|
-
|
|
80690
|
-
|
|
80691
|
-
|
|
81114
|
+
return messages;
|
|
81115
|
+
}
|
|
81116
|
+
return messages;
|
|
81117
|
+
}
|
|
81118
|
+
var RuntimeModeBlockInjector = class {
|
|
81119
|
+
constructor(options) {
|
|
81120
|
+
this.options = options;
|
|
81121
|
+
}
|
|
81122
|
+
options;
|
|
81123
|
+
lastKey = null;
|
|
81124
|
+
/**
|
|
81125
|
+
* Request-view overlay. While active, the CURRENT block is re-derived on
|
|
81126
|
+
* every request from the live message snapshot and applied to the latest
|
|
81127
|
+
* user message. It is not cached into history and it ends only when a real
|
|
81128
|
+
* user message freezes the current block (see `nextBlock` + the transform),
|
|
81129
|
+
* so consecutive tool rounds after a compaction retry keep the fresh state
|
|
81130
|
+
* instead of losing it after one request.
|
|
81131
|
+
*/
|
|
81132
|
+
overlayActive = false;
|
|
81133
|
+
reset() {
|
|
81134
|
+
this.lastKey = null;
|
|
81135
|
+
this.overlayActive = true;
|
|
81136
|
+
}
|
|
81137
|
+
/**
|
|
81138
|
+
* Arm the request-view overlay without resetting the frozen-block key. Used
|
|
81139
|
+
* when the runtime shape changed while a turn is still running (compaction
|
|
81140
|
+
* checkpoint committed, plan approval, YOLO toggle inside a tool turn): the
|
|
81141
|
+
* next and subsequent model requests must see the current state even though
|
|
81142
|
+
* no new user message has been accepted yet.
|
|
81143
|
+
*/
|
|
81144
|
+
armRefresh() {
|
|
81145
|
+
this.overlayActive = true;
|
|
81146
|
+
}
|
|
81147
|
+
/**
|
|
81148
|
+
* Block to prepend to the next user message, or null when unchanged. Does
|
|
81149
|
+
* NOT end the overlay: the block is only proof once the message carrying it
|
|
81150
|
+
* reaches the request transform.
|
|
81151
|
+
*/
|
|
81152
|
+
nextBlock() {
|
|
81153
|
+
return this.freshBlock();
|
|
81154
|
+
}
|
|
81155
|
+
/**
|
|
81156
|
+
* Current block for a request that reuses existing history (overflow retry
|
|
81157
|
+
* after compaction, manual-compact continue, or the tool rounds that follow
|
|
81158
|
+
* a mid-turn mode change). Returns the same block for every request until
|
|
81159
|
+
* the latest user message itself carries that block; then the overlay is
|
|
81160
|
+
* retired and null is returned. Derivation is per request from the given
|
|
81161
|
+
* snapshot; no message array is cached.
|
|
81162
|
+
*/
|
|
81163
|
+
consumeRetryRefreshBlock(messages) {
|
|
81164
|
+
if (!this.overlayActive) return null;
|
|
81165
|
+
const state = this.options.getState();
|
|
81166
|
+
const block = buildRuntimeModeContext(state);
|
|
81167
|
+
if (messages && lastUserMessageCarriesRuntimeBlock(messages, block)) {
|
|
81168
|
+
this.overlayActive = false;
|
|
81169
|
+
return null;
|
|
80692
81170
|
}
|
|
80693
|
-
return
|
|
81171
|
+
return block;
|
|
81172
|
+
}
|
|
81173
|
+
freshBlock() {
|
|
81174
|
+
const state = this.options.getState();
|
|
81175
|
+
if (!shouldInjectRuntimeModeBlock(this.lastKey, state)) return null;
|
|
81176
|
+
this.lastKey = runtimeModeBlockKey(state);
|
|
81177
|
+
if (state.pendingTransition) this.options.consumeTransition();
|
|
81178
|
+
this.options.noteTrace(state);
|
|
81179
|
+
return buildRuntimeModeContext(state);
|
|
81180
|
+
}
|
|
81181
|
+
};
|
|
81182
|
+
|
|
81183
|
+
// src/runtime/cache-retention.ts
|
|
81184
|
+
function createCacheRetentionStreamFn(configured, getConfiguredRetention) {
|
|
81185
|
+
const base = configured ?? ((model, context, options) => streamSimple(model, context, options));
|
|
81186
|
+
return (model, context, options) => {
|
|
81187
|
+
const requested = options?.cacheRetention;
|
|
81188
|
+
const configuredRetention = model.api === "anthropic-messages" ? getConfiguredRetention?.() : void 0;
|
|
81189
|
+
const cacheRetention = requested ?? configuredRetention;
|
|
81190
|
+
return base(model, context, {
|
|
81191
|
+
...options,
|
|
81192
|
+
...cacheRetention === void 0 ? {} : { cacheRetention }
|
|
81193
|
+
});
|
|
80694
81194
|
};
|
|
80695
81195
|
}
|
|
80696
81196
|
|
|
@@ -80706,12 +81206,19 @@ function isMarkerOnlyUserMessage(message) {
|
|
|
80706
81206
|
function stripGuardAdvisories(messages) {
|
|
80707
81207
|
return messages.filter((message) => !isMarkerOnlyUserMessage(message));
|
|
80708
81208
|
}
|
|
80709
|
-
function
|
|
81209
|
+
function findLatestUserIndex(messages) {
|
|
80710
81210
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
80711
81211
|
if (messages[index].role === "user") return index;
|
|
80712
81212
|
}
|
|
80713
81213
|
return -1;
|
|
80714
81214
|
}
|
|
81215
|
+
function applyRuntimeRequestTransform(messages, options) {
|
|
81216
|
+
const advisory = options.takeAdvisory();
|
|
81217
|
+
let next = advisory ? injectGuardAdvisory(messages, advisory) : stripGuardAdvisories(messages);
|
|
81218
|
+
const retryBlock = options.takeRetryBlock(next);
|
|
81219
|
+
if (retryBlock) next = refreshRuntimeModeBlockOnLastUserMessage(next, retryBlock);
|
|
81220
|
+
return next;
|
|
81221
|
+
}
|
|
80715
81222
|
function injectGuardAdvisory(messages, guidance) {
|
|
80716
81223
|
const advisoryMessage = {
|
|
80717
81224
|
role: "user",
|
|
@@ -80720,7 +81227,7 @@ ${guidance}
|
|
|
80720
81227
|
${GUARD_ADVISORY_END_MARKER}`,
|
|
80721
81228
|
timestamp: Date.now()
|
|
80722
81229
|
};
|
|
80723
|
-
const latestUserIndex =
|
|
81230
|
+
const latestUserIndex = findLatestUserIndex(messages);
|
|
80724
81231
|
if (latestUserIndex < 0) {
|
|
80725
81232
|
return [...messages, advisoryMessage];
|
|
80726
81233
|
}
|
|
@@ -80731,11 +81238,6 @@ ${GUARD_ADVISORY_END_MARKER}`,
|
|
|
80731
81238
|
];
|
|
80732
81239
|
}
|
|
80733
81240
|
|
|
80734
|
-
// src/runtime/tool-policy.ts
|
|
80735
|
-
function selectToolsForRuntimeMode(tools, mode) {
|
|
80736
|
-
return selectToolsForRuntimePolicy(tools, mode);
|
|
80737
|
-
}
|
|
80738
|
-
|
|
80739
81241
|
// src/runtime/terminal-bell.ts
|
|
80740
81242
|
var BEL = "\x07";
|
|
80741
81243
|
var DEFAULT_MIN_INTERVAL_MS = 500;
|
|
@@ -80933,7 +81435,7 @@ function createInteractiveExtensionUIContext(host) {
|
|
|
80933
81435
|
}
|
|
80934
81436
|
};
|
|
80935
81437
|
return {
|
|
80936
|
-
notify: (message, type = "info") => showExtensionNotification(host, message, type),
|
|
81438
|
+
notify: (message, type = "info", opts) => showExtensionNotification(host, message, type, opts),
|
|
80937
81439
|
select: (title, options, opts) => interact(() => showExtensionSelector2(host, title, options, opts)),
|
|
80938
81440
|
confirm: async (title, message, opts) => await interact(() => showExtensionConfirm(host, title, message, opts)) === true,
|
|
80939
81441
|
input: (title, placeholder, opts) => interact(() => showExtensionInput(host, title, placeholder, opts)),
|
|
@@ -81081,10 +81583,14 @@ function installInteractiveInteractionHandler(host) {
|
|
|
81081
81583
|
}
|
|
81082
81584
|
});
|
|
81083
81585
|
}
|
|
81084
|
-
function showExtensionNotification(host, message, type = "info") {
|
|
81586
|
+
function showExtensionNotification(host, message, type = "info", opts) {
|
|
81085
81587
|
const prefix = type === "error" ? "Error: " : type === "warning" ? "Warning: " : "";
|
|
81086
81588
|
host.chatContainer.addChild(new Spacer(1));
|
|
81087
|
-
|
|
81589
|
+
if (opts?.markdown) {
|
|
81590
|
+
host.chatContainer.addChild(new Markdown(`${prefix}${message}`, 1, 0, getMarkdownTheme()));
|
|
81591
|
+
} else {
|
|
81592
|
+
host.chatContainer.addChild(new Text(theme.fg(type === "error" ? "error" : type === "warning" ? "warning" : "dim", `${prefix}${message}`), 1, 0));
|
|
81593
|
+
}
|
|
81088
81594
|
host.ui.requestRender();
|
|
81089
81595
|
}
|
|
81090
81596
|
function showExtensionSelector2(host, title, options, opts) {
|
|
@@ -81455,7 +81961,10 @@ async function loadInteractiveExtensions(host) {
|
|
|
81455
81961
|
console.error(`[Extension] Tools set to: ${toolNames.join(", ")}`);
|
|
81456
81962
|
}
|
|
81457
81963
|
},
|
|
81458
|
-
getActiveTools: () =>
|
|
81964
|
+
getActiveTools: () => {
|
|
81965
|
+
const tools = host.agent.state.tools;
|
|
81966
|
+
return (host.planModeEnabled ? tools.filter((tool) => isToolAllowedInPlanMode(tool)) : tools).map((tool) => tool.name);
|
|
81967
|
+
},
|
|
81459
81968
|
sendUserMessage: (content) => {
|
|
81460
81969
|
if (host.editor.onSubmit) {
|
|
81461
81970
|
void host.editor.onSubmit(content);
|
|
@@ -81545,7 +82054,8 @@ async function loadInteractiveExtensions(host) {
|
|
|
81545
82054
|
reload: () => host.reloadRuntime(),
|
|
81546
82055
|
get yoloMode() {
|
|
81547
82056
|
return host.yoloMode;
|
|
81548
|
-
}
|
|
82057
|
+
},
|
|
82058
|
+
setYoloMode: host.setYoloMode ? (enabled) => host.setYoloMode?.(enabled) : void 0
|
|
81549
82059
|
};
|
|
81550
82060
|
const contextActions = {
|
|
81551
82061
|
isIdle: () => !host.isProcessing,
|
|
@@ -81576,13 +82086,24 @@ async function loadInteractiveExtensions(host) {
|
|
|
81576
82086
|
console.error(`[Extension] Failed to load ${path34}: ${error}`);
|
|
81577
82087
|
}
|
|
81578
82088
|
}
|
|
81579
|
-
const
|
|
82089
|
+
const policyContext = () => ({
|
|
82090
|
+
mode: host.planModeEnabled ? "plan" : "normal",
|
|
82091
|
+
yoloMode: host.yoloMode,
|
|
82092
|
+
confirmationPolicy: "allow"
|
|
82093
|
+
});
|
|
82094
|
+
const extensionTools = filterEnabledTools(
|
|
82095
|
+
createPolicyEnforcedTools(convertExtensionTools(extensions), { getContext: policyContext }),
|
|
82096
|
+
host.options.settingsManager
|
|
82097
|
+
);
|
|
81580
82098
|
const activeTools = [...host.agent.state.tools, ...extensionTools];
|
|
81581
82099
|
host.agent.state.tools = wrapToolsWithExtensions(activeTools, host.extensionRunner);
|
|
81582
82100
|
const availableTools = [
|
|
81583
|
-
|
|
82101
|
+
// Prefer the pristine (extension-unwrapped) assembly; re-deriving from
|
|
82102
|
+
// already extension-wrapped `allTools` would nest interceptors.
|
|
82103
|
+
...host.pristineTools && host.pristineTools.length > 0 ? host.pristineTools : host.allTools.length > 0 ? host.allTools : host.originalTools.length > 0 ? host.originalTools : host.agent.state.tools,
|
|
81584
82104
|
...extensionTools
|
|
81585
82105
|
];
|
|
82106
|
+
host.pristineTools = [...availableTools];
|
|
81586
82107
|
host.allTools = wrapToolsWithExtensions(availableTools, host.extensionRunner);
|
|
81587
82108
|
host.originalTools = [...host.allTools];
|
|
81588
82109
|
if (host.options.compositionTrace) {
|
|
@@ -81653,12 +82174,20 @@ var InteractiveMode = class {
|
|
|
81653
82174
|
pendingYoloModeTransition = null;
|
|
81654
82175
|
executionReminder = null;
|
|
81655
82176
|
pendingRuntimeGuardAdvisory = null;
|
|
82177
|
+
/** Freezes runtime mode blocks into user messages (cache-stable history). */
|
|
82178
|
+
runtimeModeBlocks = new RuntimeModeBlockInjector({
|
|
82179
|
+
getState: () => this.getRuntimeModeState(),
|
|
82180
|
+
consumeTransition: () => this.consumeRuntimeModeTransition(),
|
|
82181
|
+
noteTrace: (state) => this.sessionTrace.noteRuntimeEvent("runtime_context_injected", runtimeModeTraceData(state))
|
|
82182
|
+
});
|
|
81656
82183
|
fileManager;
|
|
81657
82184
|
mentionHandler;
|
|
81658
82185
|
mentionPickerComponent;
|
|
81659
82186
|
mentionPickerOptions = [];
|
|
81660
82187
|
attachmentResolver;
|
|
81661
82188
|
yoloMode = false;
|
|
82189
|
+
pristineTools = [];
|
|
82190
|
+
// Pristine (extension-unwrapped) tool assembly: the mode-rebuild source.
|
|
81662
82191
|
/** Calm mode: render only questions and answers (display-only; persisted). */
|
|
81663
82192
|
calmMode = false;
|
|
81664
82193
|
originalTools = [];
|
|
@@ -81815,11 +82344,16 @@ var InteractiveMode = class {
|
|
|
81815
82344
|
get controllerSetupHost() {
|
|
81816
82345
|
return this;
|
|
81817
82346
|
}
|
|
82347
|
+
getPolicyContext = () => ({
|
|
82348
|
+
mode: this.planModeEnabled ? "plan" : "normal",
|
|
82349
|
+
yoloMode: this.yoloMode,
|
|
82350
|
+
confirmationPolicy: "allow"
|
|
82351
|
+
});
|
|
81818
82352
|
rebuildSkillAwareTools(sourceTools) {
|
|
81819
82353
|
const preservedTools = sourceTools.filter(
|
|
81820
82354
|
(tool) => !CLI_FILESYSTEM_TOOL_NAMES.includes(tool.name) && tool.name !== "bash"
|
|
81821
82355
|
);
|
|
81822
|
-
const bashTool = createBashTool(this.options.cwd, { isYoloMode: () => this.yoloMode });
|
|
82356
|
+
const bashTool = createBashTool(this.options.cwd, { isYoloMode: () => this.yoloMode, getEnv: () => computerUseOwnerEnv(this.sessionManager.getActiveSessionId() || COMPUTER_USE_STANDALONE_OWNER, String(process.pid)) });
|
|
81823
82357
|
const fileSystemToolOptions = (allowlistedDirs) => ({
|
|
81824
82358
|
...buildCliFileAccessOptions({
|
|
81825
82359
|
cwd: this.options.cwd,
|
|
@@ -81840,19 +82374,14 @@ var InteractiveMode = class {
|
|
|
81840
82374
|
});
|
|
81841
82375
|
const normalFsTools = createCliFileSystemTools(this.options.cwd, fileSystemToolOptions([this.options.configDir]));
|
|
81842
82376
|
const currentFsTools = this.yoloMode ? createCliFileSystemTools(this.options.cwd, fileSystemToolOptions(["/"])) : normalFsTools;
|
|
81843
|
-
const getPolicyContext = () => ({
|
|
81844
|
-
mode: this.planModeEnabled ? "plan" : "normal",
|
|
81845
|
-
yoloMode: this.yoloMode,
|
|
81846
|
-
confirmationPolicy: "allow"
|
|
81847
|
-
});
|
|
81848
82377
|
return {
|
|
81849
82378
|
currentTools: createPolicyEnforcedTools(
|
|
81850
82379
|
[...currentFsTools, bashTool, ...preservedTools],
|
|
81851
|
-
{ getContext: getPolicyContext }
|
|
82380
|
+
{ getContext: this.getPolicyContext }
|
|
81852
82381
|
),
|
|
81853
82382
|
originalTools: createPolicyEnforcedTools(
|
|
81854
82383
|
[...normalFsTools, bashTool, ...preservedTools],
|
|
81855
|
-
{ getContext: getPolicyContext }
|
|
82384
|
+
{ getContext: this.getPolicyContext }
|
|
81856
82385
|
)
|
|
81857
82386
|
};
|
|
81858
82387
|
}
|
|
@@ -81860,26 +82389,27 @@ var InteractiveMode = class {
|
|
|
81860
82389
|
this.options.fileObservationState.clear();
|
|
81861
82390
|
}
|
|
81862
82391
|
getRuntimeModeState() {
|
|
81863
|
-
const pendingTransition = this.getPendingRuntimeModeTransition();
|
|
81864
82392
|
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || "local";
|
|
81865
|
-
const
|
|
81866
|
-
year: "numeric",
|
|
81867
|
-
month: "2-digit",
|
|
81868
|
-
day: "2-digit",
|
|
81869
|
-
timeZone
|
|
81870
|
-
}).formatToParts(/* @__PURE__ */ new Date());
|
|
81871
|
-
const datePart = (type) => dateParts.find((part) => part.type === type)?.value ?? "00";
|
|
81872
|
-
const currentDate = `${datePart("year")}-${datePart("month")}-${datePart("day")}`;
|
|
82393
|
+
const activeTools = this.agent?.state?.tools ?? [];
|
|
81873
82394
|
return {
|
|
81874
82395
|
yoloMode: this.yoloMode,
|
|
81875
82396
|
planMode: this.planModeEnabled ? "planning" : "off",
|
|
81876
82397
|
filesystemScope: this.yoloMode ? "all" : "workspace",
|
|
81877
|
-
...
|
|
81878
|
-
currentDate,
|
|
82398
|
+
...this.getPendingRuntimeModeTransition() ? { pendingTransition: this.getPendingRuntimeModeTransition() } : {},
|
|
82399
|
+
currentDate: currentDateInZone(timeZone),
|
|
81879
82400
|
timeZone,
|
|
81880
|
-
activeToolNames:
|
|
82401
|
+
activeToolNames: activeTools.map((tool) => tool.name),
|
|
82402
|
+
planDisabledToolNames: this.planModeEnabled ? activeTools.filter((tool) => !isToolAllowedInPlanMode(tool)).map((tool) => tool.name) : []
|
|
81881
82403
|
};
|
|
81882
82404
|
}
|
|
82405
|
+
/** Public reset for compaction flows (compaction may drop the latest block). */
|
|
82406
|
+
resetRuntimeModeBlocks() {
|
|
82407
|
+
this.runtimeModeBlocks.reset();
|
|
82408
|
+
}
|
|
82409
|
+
/** Runtime mode block for the next user message; frozen into it (append-only history, cache-stable prefixes). */
|
|
82410
|
+
runtimeModeBlockForNextMessage() {
|
|
82411
|
+
return this.runtimeModeBlocks.nextBlock();
|
|
82412
|
+
}
|
|
81883
82413
|
getPendingRuntimeModeTransition() {
|
|
81884
82414
|
if (this.pendingYoloModeTransition === "enter") return "entered_yolo";
|
|
81885
82415
|
if (this.pendingYoloModeTransition === "exit") return "exited_yolo";
|
|
@@ -81893,15 +82423,12 @@ var InteractiveMode = class {
|
|
|
81893
82423
|
}
|
|
81894
82424
|
applyRuntimeToolMode(sourceTools) {
|
|
81895
82425
|
if (!this.agent) return;
|
|
81896
|
-
const completeToolSet = sourceTools ?? (this.
|
|
82426
|
+
const completeToolSet = sourceTools ?? ((this.pristineTools?.length ?? 0) > 0 ? this.pristineTools : this.allTools) ?? this.agent.state.tools;
|
|
81897
82427
|
const rebuilt = this.rebuildSkillAwareTools(completeToolSet);
|
|
81898
82428
|
const currentTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.currentTools, this.extensionRunner) : rebuilt.currentTools;
|
|
81899
82429
|
const originalTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.originalTools, this.extensionRunner) : rebuilt.originalTools;
|
|
81900
82430
|
const activeTools = filterEnabledTools(
|
|
81901
|
-
|
|
81902
|
-
currentTools,
|
|
81903
|
-
this.planModeEnabled ? "plan" : "normal"
|
|
81904
|
-
),
|
|
82431
|
+
currentTools,
|
|
81905
82432
|
this.options.settingsManager
|
|
81906
82433
|
);
|
|
81907
82434
|
this.agent.setTools(activeTools);
|
|
@@ -81918,6 +82445,7 @@ var InteractiveMode = class {
|
|
|
81918
82445
|
});
|
|
81919
82446
|
}
|
|
81920
82447
|
noteRuntimeModeChanged(trigger) {
|
|
82448
|
+
this.runtimeModeBlocks?.armRefresh();
|
|
81921
82449
|
const state = this.getRuntimeModeState();
|
|
81922
82450
|
this.sessionTrace.noteRuntimeEvent("runtime_mode_changed", {
|
|
81923
82451
|
trigger,
|
|
@@ -81934,7 +82462,8 @@ var InteractiveMode = class {
|
|
|
81934
82462
|
this.safeRequestRender();
|
|
81935
82463
|
}
|
|
81936
82464
|
promptAgent(input) {
|
|
81937
|
-
|
|
82465
|
+
const prompt = prependRuntimeModeBlockToPrompt(input, this.runtimeModeBlockForNextMessage());
|
|
82466
|
+
return this.agentSessionController.prompt(prompt, { source: "interactive" });
|
|
81938
82467
|
}
|
|
81939
82468
|
continueAgent() {
|
|
81940
82469
|
return this.agentSessionController.continue();
|
|
@@ -81964,6 +82493,7 @@ var InteractiveMode = class {
|
|
|
81964
82493
|
this.persistExecutionState();
|
|
81965
82494
|
}
|
|
81966
82495
|
this.executionReminder = this.executionState.getReminder();
|
|
82496
|
+
this.resetRuntimeModeBlocks();
|
|
81967
82497
|
await this.refreshTodoWidget();
|
|
81968
82498
|
await this.emitExtensionEvent({
|
|
81969
82499
|
type: "session:changed",
|
|
@@ -81974,7 +82504,7 @@ var InteractiveMode = class {
|
|
|
81974
82504
|
async init() {
|
|
81975
82505
|
const activeSession = this.sessionManager.getActiveSession();
|
|
81976
82506
|
this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
|
|
81977
|
-
const { Agent } = await import("./chunks/src-
|
|
82507
|
+
const { Agent } = await import("./chunks/src-C4KA4G75.js");
|
|
81978
82508
|
this.agent = new Agent({
|
|
81979
82509
|
initialState: {
|
|
81980
82510
|
systemPrompt: this.buildSystemPrompt(),
|
|
@@ -81984,28 +82514,15 @@ var InteractiveMode = class {
|
|
|
81984
82514
|
},
|
|
81985
82515
|
apiKey: this.options.apiKey,
|
|
81986
82516
|
sessionId: activeSession?.id,
|
|
81987
|
-
streamFn: this.options.streamFn,
|
|
81988
|
-
transformContext: async (messages) => {
|
|
81989
|
-
|
|
81990
|
-
|
|
81991
|
-
|
|
81992
|
-
|
|
81993
|
-
|
|
81994
|
-
|
|
81995
|
-
|
|
81996
|
-
pendingTransition: state.pendingTransition,
|
|
81997
|
-
currentDate: state.currentDate,
|
|
81998
|
-
timeZone: state.timeZone,
|
|
81999
|
-
activeToolCount: state.activeToolNames.length
|
|
82000
|
-
}),
|
|
82001
|
-
onStripped: (count) => this.sessionTrace.noteRuntimeEvent("stale_runtime_context_stripped", { count })
|
|
82002
|
-
});
|
|
82003
|
-
let transformed = await runtimeModeTransform(messages);
|
|
82004
|
-
const advisory = this.pendingRuntimeGuardAdvisory;
|
|
82005
|
-
this.pendingRuntimeGuardAdvisory = null;
|
|
82006
|
-
transformed = advisory ? injectGuardAdvisory(transformed, advisory) : stripGuardAdvisories(transformed);
|
|
82007
|
-
return transformed;
|
|
82008
|
-
}
|
|
82517
|
+
streamFn: createTransportDiagnosticsStreamFn(createCacheRetentionStreamFn(this.options.streamFn, () => this.options.settingsManager.getPromptCacheRetention()), createTraceTransportSink((type, meta) => this.sessionTrace.noteRuntimeEvent(type, meta))),
|
|
82518
|
+
transformContext: async (messages) => applyRuntimeRequestTransform(messages, {
|
|
82519
|
+
takeAdvisory: () => {
|
|
82520
|
+
const advisory = this.pendingRuntimeGuardAdvisory;
|
|
82521
|
+
this.pendingRuntimeGuardAdvisory = null;
|
|
82522
|
+
return advisory;
|
|
82523
|
+
},
|
|
82524
|
+
takeRetryBlock: (snapshot) => this.runtimeModeBlocks.consumeRetryRefreshBlock(snapshot)
|
|
82525
|
+
})
|
|
82009
82526
|
});
|
|
82010
82527
|
this.agentSessionController = createInteractiveAgentSessionController(this.controllerSetupHost);
|
|
82011
82528
|
this.updateTerminalTitle();
|
|
@@ -82097,6 +82614,7 @@ var InteractiveMode = class {
|
|
|
82097
82614
|
}
|
|
82098
82615
|
this.allTools = [...this.options.allTools];
|
|
82099
82616
|
this.originalTools = [...this.options.allTools];
|
|
82617
|
+
this.pristineTools = [...this.options.allTools];
|
|
82100
82618
|
this.agent.state.tools = [...this.options.allTools];
|
|
82101
82619
|
await this.extensionRunner?.dispose("reload");
|
|
82102
82620
|
this.extensionWidgets?.clearAll();
|
|
@@ -82189,6 +82707,9 @@ var InteractiveMode = class {
|
|
|
82189
82707
|
async handleYoloCommand(args) {
|
|
82190
82708
|
return handleYoloCommand(this, args);
|
|
82191
82709
|
}
|
|
82710
|
+
setYoloMode(enabled) {
|
|
82711
|
+
void this.handleYoloCommand(enabled ? "on" : "off");
|
|
82712
|
+
}
|
|
82192
82713
|
/**
|
|
82193
82714
|
* Toggle calm mode and rebuild the chat so already-rendered rows follow
|
|
82194
82715
|
* the new mode. Delivery, tool execution, and session storage are
|
|
@@ -82390,6 +82911,7 @@ var InteractiveMode = class {
|
|
|
82390
82911
|
|
|
82391
82912
|
// src/app/runtime-composition.ts
|
|
82392
82913
|
import { existsSync as existsSync18, mkdirSync as mkdirSync13 } from "fs";
|
|
82914
|
+
import { randomUUID } from "crypto";
|
|
82393
82915
|
import * as path31 from "path";
|
|
82394
82916
|
var CliMissingApiKeyError = class extends Error {
|
|
82395
82917
|
constructor(message) {
|
|
@@ -82519,6 +83041,7 @@ async function composeCliRuntime(params) {
|
|
|
82519
83041
|
await sessionManager.save();
|
|
82520
83042
|
}
|
|
82521
83043
|
const sessionId = sessionManager.getActiveSession()?.id;
|
|
83044
|
+
const computerUseExecutionId = randomUUID();
|
|
82522
83045
|
const fileObservationState = createFileObservationState();
|
|
82523
83046
|
if (sessionId) {
|
|
82524
83047
|
if (process.env.PIE_DEBUG && !fileLogger.isEnabled()) {
|
|
@@ -82547,7 +83070,8 @@ async function composeCliRuntime(params) {
|
|
|
82547
83070
|
getWebSearchMode: () => settingsManager.getWebSearchMode(),
|
|
82548
83071
|
resolveToolModel: (purpose) => modelRegistry.resolveToolModel(purpose, getCurrentModel()),
|
|
82549
83072
|
resolveToolModelCandidates: (purpose) => modelRegistry.resolveToolModelCandidates(purpose, getCurrentModel()),
|
|
82550
|
-
configDir: paths.configDir
|
|
83073
|
+
configDir: paths.configDir,
|
|
83074
|
+
getBashEnv: () => computerUseOwnerEnv(sessionManager.getActiveSessionId() || COMPUTER_USE_STANDALONE_OWNER, computerUseExecutionId)
|
|
82551
83075
|
});
|
|
82552
83076
|
const fileSystemToolOptions = {
|
|
82553
83077
|
...buildCliFileAccessOptions({ cwd, configDir: paths.configDir, skills, allowlistedDirs: [paths.configDir] }),
|
|
@@ -82560,6 +83084,7 @@ async function composeCliRuntime(params) {
|
|
|
82560
83084
|
getPolicyContext: () => ({ mode: "normal", confirmationPolicy: "allow" })
|
|
82561
83085
|
};
|
|
82562
83086
|
const rawTools = [
|
|
83087
|
+
createSearchContextTool(() => sessionManager),
|
|
82563
83088
|
...createCliFileSystemTools(cwd, fileSystemToolOptions),
|
|
82564
83089
|
...cliHostCapabilities.tools
|
|
82565
83090
|
];
|
|
@@ -82674,6 +83199,38 @@ function createPrintModeRetryStatusReporter() {
|
|
|
82674
83199
|
};
|
|
82675
83200
|
}
|
|
82676
83201
|
|
|
83202
|
+
// src/app/print-mode-compaction.ts
|
|
83203
|
+
function createPrintModeCompactionHandler(params) {
|
|
83204
|
+
return {
|
|
83205
|
+
compact: async (context) => {
|
|
83206
|
+
const beforeCompact = await params.runner.emitSessionBeforeCompact({
|
|
83207
|
+
type: "session:before_compact",
|
|
83208
|
+
reason: context.reason === "overflow" ? "overflow" : "threshold",
|
|
83209
|
+
messageCount: context.messages.length
|
|
83210
|
+
});
|
|
83211
|
+
if (beforeCompact.cancel) return { aborted: true };
|
|
83212
|
+
if (beforeCompact.summary) {
|
|
83213
|
+
const retainedTail = context.preparation?.retainedTail.retainedTail ?? (() => {
|
|
83214
|
+
const legacyCutId = findFirstKeptEntrySummaryId(context.sessionManager.getActiveContextSummaries());
|
|
83215
|
+
return legacyCutId ? { kind: "from-entry", entryId: legacyCutId } : void 0;
|
|
83216
|
+
})();
|
|
83217
|
+
if (!retainedTail) return { aborted: true };
|
|
83218
|
+
return {
|
|
83219
|
+
summary: beforeCompact.summary,
|
|
83220
|
+
retainedTail,
|
|
83221
|
+
...retainedTail.kind === "from-entry" ? { firstKeptEntryId: retainedTail.entryId } : {}
|
|
83222
|
+
};
|
|
83223
|
+
}
|
|
83224
|
+
return createCliAutoCompactionResult({
|
|
83225
|
+
context,
|
|
83226
|
+
model: params.model,
|
|
83227
|
+
apiKey: params.apiKey,
|
|
83228
|
+
systemPrompt: params.systemPrompt
|
|
83229
|
+
});
|
|
83230
|
+
}
|
|
83231
|
+
};
|
|
83232
|
+
}
|
|
83233
|
+
|
|
82677
83234
|
// src/app/print-mode.ts
|
|
82678
83235
|
function createNoOpExtensionUIContext() {
|
|
82679
83236
|
return {
|
|
@@ -82805,7 +83362,7 @@ async function runPrintMode(params) {
|
|
|
82805
83362
|
`);
|
|
82806
83363
|
console.log("Assistant: ");
|
|
82807
83364
|
}
|
|
82808
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
83365
|
+
const { Agent: AgentClass } = await import("./chunks/src-C4KA4G75.js");
|
|
82809
83366
|
let agent;
|
|
82810
83367
|
const printModeExtensions = await loadPrintModeExtensions({
|
|
82811
83368
|
cwd: runtime.cwd,
|
|
@@ -82849,7 +83406,8 @@ async function runPrintMode(params) {
|
|
|
82849
83406
|
thinkingLevel: printThinkingLevel
|
|
82850
83407
|
},
|
|
82851
83408
|
apiKey: runtime.apiKey,
|
|
82852
|
-
|
|
83409
|
+
// Body-free transport timeline for the main (print-mode) agent.
|
|
83410
|
+
streamFn: createTransportDiagnosticsStreamFn(params.streamFn ?? streamSimple, logTransportLifecycle)
|
|
82853
83411
|
});
|
|
82854
83412
|
const sessionTrace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
|
|
82855
83413
|
const reportRetryStatus = createPrintModeRetryStatusReporter();
|
|
@@ -82883,28 +83441,16 @@ async function runPrintMode(params) {
|
|
|
82883
83441
|
latestCompactionTimestamp: runtime.sessionManager.getLatestCompactionTimestamp(),
|
|
82884
83442
|
isContextOverflowError: isCliContextOverflowError
|
|
82885
83443
|
}),
|
|
82886
|
-
|
|
82887
|
-
|
|
82888
|
-
|
|
82889
|
-
|
|
82890
|
-
|
|
82891
|
-
|
|
82892
|
-
|
|
82893
|
-
|
|
82894
|
-
|
|
82895
|
-
|
|
82896
|
-
const firstKeptEntryId = activeEntryId ? findFirstKeptEntrySummaryId(context.sessionManager.getActiveContextSummaries()) : void 0;
|
|
82897
|
-
if (!firstKeptEntryId) return { aborted: true };
|
|
82898
|
-
return { summary: beforeCompact.summary, firstKeptEntryId };
|
|
82899
|
-
}
|
|
82900
|
-
return createCliAutoCompactionResult({
|
|
82901
|
-
context,
|
|
82902
|
-
model: runtime.model,
|
|
82903
|
-
apiKey: runtime.apiKey,
|
|
82904
|
-
systemPrompt: agent?.state.systemPrompt ?? baseSystemPrompt
|
|
82905
|
-
});
|
|
82906
|
-
}
|
|
82907
|
-
},
|
|
83444
|
+
getCompactionBudgetTokens: createCliCompactionBudget({
|
|
83445
|
+
contextWindow: runtime.model.contextWindow,
|
|
83446
|
+
reserveTokens: runtime.settingsManager.getAutoCompactReserveTokens()
|
|
83447
|
+
}),
|
|
83448
|
+
compaction: createPrintModeCompactionHandler({
|
|
83449
|
+
runner: printModeExtensions.runner,
|
|
83450
|
+
model: runtime.model,
|
|
83451
|
+
apiKey: runtime.apiKey,
|
|
83452
|
+
systemPrompt: agent?.state.systemPrompt ?? baseSystemPrompt
|
|
83453
|
+
}),
|
|
82908
83454
|
classifyFailure: (context) => classifyCliFailure(context),
|
|
82909
83455
|
onEvent: (event) => {
|
|
82910
83456
|
sessionTrace.noteRuntimeEvent(event.type, event);
|
|
@@ -82912,7 +83458,7 @@ async function runPrintMode(params) {
|
|
|
82912
83458
|
console.error(event.failure.kind === "context_overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context before retry...");
|
|
82913
83459
|
} else if (event.type === "auto_compaction_start") {
|
|
82914
83460
|
console.error(event.reason === "overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context...");
|
|
82915
|
-
} else if (event.type === "
|
|
83461
|
+
} else if (event.type === "compaction_committed") {
|
|
82916
83462
|
runtime.fileObservationState.clear();
|
|
82917
83463
|
} else {
|
|
82918
83464
|
reportRetryStatus(event);
|
|
@@ -83045,7 +83591,7 @@ function toJsonValue(value, depth = 0, cap = MAX_EVENT_STRING_LENGTH) {
|
|
|
83045
83591
|
}
|
|
83046
83592
|
return result;
|
|
83047
83593
|
}
|
|
83048
|
-
function
|
|
83594
|
+
function isRecord3(value) {
|
|
83049
83595
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
83050
83596
|
}
|
|
83051
83597
|
function truncateForEvent(text, cap) {
|
|
@@ -83071,7 +83617,7 @@ function parseInput(line) {
|
|
|
83071
83617
|
} catch {
|
|
83072
83618
|
return null;
|
|
83073
83619
|
}
|
|
83074
|
-
if (!
|
|
83620
|
+
if (!isRecord3(parsed) || typeof parsed.type !== "string") return null;
|
|
83075
83621
|
if (parsed.type === "shutdown") {
|
|
83076
83622
|
return { type: "shutdown", reason: typeof parsed.reason === "string" ? parsed.reason : void 0 };
|
|
83077
83623
|
}
|
|
@@ -83122,7 +83668,7 @@ function parseInput(line) {
|
|
|
83122
83668
|
prompt: parsed.prompt,
|
|
83123
83669
|
streamingBehavior,
|
|
83124
83670
|
cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0,
|
|
83125
|
-
metadata:
|
|
83671
|
+
metadata: isRecord3(parsed.metadata) ? parsed.metadata : void 0
|
|
83126
83672
|
};
|
|
83127
83673
|
}
|
|
83128
83674
|
return null;
|
|
@@ -83162,15 +83708,15 @@ function readProgressText(value) {
|
|
|
83162
83708
|
function extractJsonEventsToolProgressText(partialResult) {
|
|
83163
83709
|
const plainText = readProgressText(partialResult).trim();
|
|
83164
83710
|
if (plainText) return plainText;
|
|
83165
|
-
if (!
|
|
83711
|
+
if (!isRecord3(partialResult)) return "";
|
|
83166
83712
|
const content = partialResult.content;
|
|
83167
83713
|
if (Array.isArray(content)) {
|
|
83168
|
-
return content.map((block) =>
|
|
83714
|
+
return content.map((block) => isRecord3(block) && block.type === "text" ? readProgressText(block.text) : "").filter(Boolean).join("\n").trim();
|
|
83169
83715
|
}
|
|
83170
83716
|
const directText = readProgressText(partialResult.text) || readProgressText(partialResult.message);
|
|
83171
83717
|
if (directText) return directText.trim();
|
|
83172
83718
|
const details = partialResult.details;
|
|
83173
|
-
if (
|
|
83719
|
+
if (isRecord3(details)) {
|
|
83174
83720
|
return (readProgressText(details.text) || readProgressText(details.message)).trim();
|
|
83175
83721
|
}
|
|
83176
83722
|
return "";
|
|
@@ -83266,6 +83812,9 @@ async function loadJsonModeExtensions(params) {
|
|
|
83266
83812
|
extensionCount: extensions.length
|
|
83267
83813
|
};
|
|
83268
83814
|
}
|
|
83815
|
+
function createJsonEventsTransportStreamFn(streamFn) {
|
|
83816
|
+
return createTransportDiagnosticsStreamFn(streamFn ?? streamSimple, logTransportLifecycle);
|
|
83817
|
+
}
|
|
83269
83818
|
async function runJsonEventsMode(params) {
|
|
83270
83819
|
const eventDetail = params.eventDetail === FULL_DETAIL ? FULL_DETAIL : COMPACT_DETAIL;
|
|
83271
83820
|
const eventStringCap = eventDetail === FULL_DETAIL ? MAX_EVENT_STRING_LENGTH : COMPACT_EVENT_STRING_LENGTH;
|
|
@@ -83666,7 +84215,7 @@ async function runJsonEventsMode(params) {
|
|
|
83666
84215
|
return;
|
|
83667
84216
|
}
|
|
83668
84217
|
const parent = agent;
|
|
83669
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
84218
|
+
const { Agent: AgentClass } = await import("./chunks/src-C4KA4G75.js");
|
|
83670
84219
|
const sideAgent = new AgentClass({
|
|
83671
84220
|
initialState: {
|
|
83672
84221
|
systemPrompt: parent.state.systemPrompt,
|
|
@@ -83676,7 +84225,11 @@ async function runJsonEventsMode(params) {
|
|
|
83676
84225
|
messages: structuredClone(parent.state.messages)
|
|
83677
84226
|
},
|
|
83678
84227
|
apiKey: runtime.apiKey,
|
|
83679
|
-
|
|
84228
|
+
// Same body-free transport timeline as the main agent: a sidechat is
|
|
84229
|
+
// an independent Responses request and previously had no record at all
|
|
84230
|
+
// when it stalled. `streamSimple` matches the host default when the
|
|
84231
|
+
// caller injected no stream function.
|
|
84232
|
+
streamFn: createJsonEventsTransportStreamFn(params.streamFn)
|
|
83680
84233
|
});
|
|
83681
84234
|
sidechatController.signal.addEventListener("abort", () => sideAgent.abort(), { once: true });
|
|
83682
84235
|
const timer = setTimeout(() => {
|
|
@@ -83834,7 +84387,7 @@ async function runJsonEventsMode(params) {
|
|
|
83834
84387
|
}
|
|
83835
84388
|
function handleControllerEvent(event) {
|
|
83836
84389
|
trace?.noteRuntimeEvent(event.type, event);
|
|
83837
|
-
if (event.type === "
|
|
84390
|
+
if (event.type === "compaction_committed") {
|
|
83838
84391
|
runtime?.fileObservationState.clear();
|
|
83839
84392
|
}
|
|
83840
84393
|
if (event.type === "turn_settled" && activeTurn) {
|
|
@@ -84010,7 +84563,7 @@ async function runJsonEventsMode(params) {
|
|
|
84010
84563
|
if (runtime.initialModel.unconfigured || controller) {
|
|
84011
84564
|
return;
|
|
84012
84565
|
}
|
|
84013
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
84566
|
+
const { Agent: AgentClass } = await import("./chunks/src-C4KA4G75.js");
|
|
84014
84567
|
const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
|
|
84015
84568
|
extensionRunner = jsonModeExtensions.runner;
|
|
84016
84569
|
const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
|
|
@@ -84042,7 +84595,8 @@ async function runJsonEventsMode(params) {
|
|
|
84042
84595
|
thinkingLevel
|
|
84043
84596
|
},
|
|
84044
84597
|
apiKey: runtime.apiKey,
|
|
84045
|
-
|
|
84598
|
+
// Body-free transport timeline for the main (JSON-events) agent.
|
|
84599
|
+
streamFn: createJsonEventsTransportStreamFn(params.streamFn)
|
|
84046
84600
|
});
|
|
84047
84601
|
controller = new AgentSessionController({
|
|
84048
84602
|
agent,
|
|
@@ -84071,6 +84625,10 @@ async function runJsonEventsMode(params) {
|
|
|
84071
84625
|
latestCompactionTimestamp: runtime.sessionManager.getLatestCompactionTimestamp(),
|
|
84072
84626
|
isContextOverflowError: isCliContextOverflowError
|
|
84073
84627
|
}),
|
|
84628
|
+
getCompactionBudgetTokens: createCliCompactionBudget({
|
|
84629
|
+
contextWindow: runtime.model.contextWindow,
|
|
84630
|
+
reserveTokens: runtime.settingsManager.getAutoCompactReserveTokens()
|
|
84631
|
+
}),
|
|
84074
84632
|
compaction: {
|
|
84075
84633
|
compact: async (context) => createCliAutoCompactionResult({
|
|
84076
84634
|
context,
|
|
@@ -84604,7 +85162,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
|
|
|
84604
85162
|
}
|
|
84605
85163
|
async function createCliTestStreamFnFromEnv() {
|
|
84606
85164
|
if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
|
|
84607
|
-
return (await import("./chunks/test-stream-
|
|
85165
|
+
return (await import("./chunks/test-stream-A5ZELKNG.js")).createTestStreamFnFromSequenceEnv();
|
|
84608
85166
|
}
|
|
84609
85167
|
function resolveJsonEventsDetailFlag() {
|
|
84610
85168
|
for (let index = 0; index < process.argv.length; index += 1) {
|