privateer-agent 0.12.7 → 0.12.10
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 +29 -10
- package/SECURITY.md +41 -5
- package/bin/privateer-launch.mjs +85 -5
- package/bin/privateer-splash.mjs +247 -0
- package/bin/privateer-verify.d.mts +10 -0
- package/bin/privateer-verify.mjs +289 -0
- package/bin/update-route.d.mts +6 -0
- package/bin/update-route.mjs +35 -0
- package/extensions/privateer-brand.ts +35 -24
- package/extensions/privateer-hints.ts +8 -2
- package/extensions/privateer-update.ts +187 -0
- package/package.json +25 -25
- package/patches/{@earendil-works+pi-coding-agent+0.80.3.patch → @earendil-works+pi-coding-agent+0.84.1.patch} +221 -132
- package/src/acp/run.ts +5 -4
- package/src/channels/run.ts +3 -1
- package/src/cli/chat.ts +7 -5
- package/src/config/moatManifest.json +1 -0
- package/src/context.ts +9 -1
- package/src/harbor/index.ts +7 -6
- package/src/providers/account.ts +37 -29
- package/src/providers/piAuthStore.ts +129 -0
- package/src/remote/liveTaskSession.ts +6 -6
- package/src/session.ts +26 -9
- package/src/updates.ts +106 -0
|
@@ -68,12 +68,12 @@ index 4600b23..075ecae 100644
|
|
|
68
68
|
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
|
|
69
69
|
export const ENV_SESSION_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_SESSION_DIR`;
|
|
70
70
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js
|
|
71
|
-
index
|
|
71
|
+
index ce8a9a2..1ae7b25 100644
|
|
72
72
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js
|
|
73
73
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js
|
|
74
|
-
@@ -
|
|
74
|
+
@@ -186,6 +186,14 @@ export class AgentSession {
|
|
75
75
|
}
|
|
76
|
-
const isOAuth = this.
|
|
76
|
+
const isOAuth = this._modelRuntime.isUsingOAuth(model.provider);
|
|
77
77
|
if (isOAuth) {
|
|
78
78
|
+ // Privateer patch: the account channel has no API key that could expire —
|
|
79
79
|
+ // the terminal is simply not signed in yet (a fresh install now boots on
|
|
@@ -86,7 +86,7 @@ index e223ce1..cc853e7 100644
|
|
|
86
86
|
throw new Error(`Authentication failed for "${model.provider}". ` +
|
|
87
87
|
`Credentials may have expired or network is unavailable. ` +
|
|
88
88
|
`Run '/login ${model.provider}' to re-authenticate.`);
|
|
89
|
-
@@ -
|
|
89
|
+
@@ -772,6 +780,15 @@ export class AgentSession {
|
|
90
90
|
finalError: msg.errorMessage,
|
|
91
91
|
});
|
|
92
92
|
this._retryAttempt = 0;
|
|
@@ -102,7 +102,22 @@ index e223ce1..cc853e7 100644
|
|
|
102
102
|
}
|
|
103
103
|
if (await this._checkCompaction(msg)) {
|
|
104
104
|
return true;
|
|
105
|
-
@@ -
|
|
105
|
+
@@ -852,6 +869,14 @@ export class AgentSession {
|
|
106
|
+
if (!hasConfiguredAuth) {
|
|
107
|
+
const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
|
|
108
|
+
if (isOAuth) {
|
|
109
|
+
+ // Privateer patch: the account channel has no API key that could expire —
|
|
110
|
+
+ // the terminal is simply not signed in yet (a fresh install now boots on
|
|
111
|
+
+ // `privateer/*`, which is the model it will run once logged in). Stock Pi's
|
|
112
|
+
+ // wording describes a state that user was never in, and its "/login
|
|
113
|
+
+ // privateer" bypasses the branded sign-in. auth-guidance owns the words.
|
|
114
|
+
+ if (this.model.provider === "privateer") {
|
|
115
|
+
+ throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
|
|
116
|
+
+ }
|
|
117
|
+
throw new Error(`Authentication failed for "${this.model.provider}". ` +
|
|
118
|
+
`Credentials may have expired or network is unavailable. ` +
|
|
119
|
+
`Run '/login ${this.model.provider}' to re-authenticate.`);
|
|
120
|
+
@@ -2084,6 +2109,18 @@ export class AgentSession {
|
|
106
121
|
// Context overflow is handled by compaction, not retry.
|
|
107
122
|
if (isContextOverflow(message, this.model?.contextWindow ?? 0))
|
|
108
123
|
return false;
|
|
@@ -167,10 +182,10 @@ index 197bccc..bc9ac3f 100644
|
|
|
167
182
|
//# sourceMappingURL=auth-guidance.js.map
|
|
168
183
|
|
|
169
184
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js
|
|
170
|
-
index
|
|
185
|
+
index 324d30a..e613e92 100644
|
|
171
186
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js
|
|
172
187
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js
|
|
173
|
-
@@ -
|
|
188
|
+
@@ -18,7 +18,7 @@ import { createJiti } from "jiti/static";
|
|
174
189
|
import * as _bundledTypebox from "typebox";
|
|
175
190
|
import * as _bundledTypeboxCompile from "typebox/compile";
|
|
176
191
|
import * as _bundledTypeboxValue from "typebox/value";
|
|
@@ -179,7 +194,7 @@ index 4b79482..a81b452 100644
|
|
|
179
194
|
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
|
180
195
|
// avoiding a circular dependency. Extensions can import from @earendil-works/pi-coding-agent.
|
|
181
196
|
import * as _bundledPiCodingAgent from "../../index.js";
|
|
182
|
-
@@ -
|
|
197
|
+
@@ -554,9 +554,23 @@ export async function discoverAndLoadExtensions(configuredPaths, cwd, agentDir =
|
|
183
198
|
}
|
|
184
199
|
}
|
|
185
200
|
};
|
|
@@ -207,7 +222,7 @@ index 4b79482..a81b452 100644
|
|
|
207
222
|
const globalExtDir = path.join(resolvedAgentDir, "extensions");
|
|
208
223
|
addPaths(discoverExtensionsInDir(globalExtDir));
|
|
209
224
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js
|
|
210
|
-
index
|
|
225
|
+
index e806af3..9b00ebd 100644
|
|
211
226
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js
|
|
212
227
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js
|
|
213
228
|
@@ -25,7 +25,7 @@ import { globSync } from "glob";
|
|
@@ -219,7 +234,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
219
234
|
import { spawnProcess, spawnProcessSync } from "../utils/child-process.js";
|
|
220
235
|
import { parseGitUrl } from "../utils/git.js";
|
|
221
236
|
import { canonicalizePath, isLocalPath, markPathIgnoredByCloudSync, resolvePath } from "../utils/paths.js";
|
|
222
|
-
@@ -
|
|
237
|
+
@@ -698,23 +698,29 @@ export class DefaultPackageManager {
|
|
223
238
|
const packageSources = this.dedupePackages(allPackages);
|
|
224
239
|
await this.resolvePackageSources(packageSources, accumulator, onMissing);
|
|
225
240
|
const globalBaseDir = this.agentDir;
|
|
@@ -256,7 +271,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
256
271
|
return this.toResolvedPaths(accumulator);
|
|
257
272
|
}
|
|
258
273
|
async resolveExtensionSources(sources, options) {
|
|
259
|
-
@@ -
|
|
274
|
+
@@ -1668,13 +1674,30 @@ export class DefaultPackageManager {
|
|
260
275
|
writeFileSync(ignorePath, "*\n!.gitignore\n", "utf-8");
|
|
261
276
|
}
|
|
262
277
|
}
|
|
@@ -288,7 +303,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
288
303
|
}
|
|
289
304
|
return join(this.agentDir, "npm");
|
|
290
305
|
}
|
|
291
|
-
@@ -
|
|
306
|
+
@@ -1713,7 +1736,9 @@ export class DefaultPackageManager {
|
|
292
307
|
}
|
|
293
308
|
if (scope === "project") {
|
|
294
309
|
this.assertProjectTrustedForScope(scope);
|
|
@@ -299,7 +314,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
299
314
|
}
|
|
300
315
|
return join(this.agentDir, "npm", "node_modules", source.name);
|
|
301
316
|
}
|
|
302
|
-
@@ -
|
|
317
|
+
@@ -1749,7 +1774,7 @@ export class DefaultPackageManager {
|
|
303
318
|
}
|
|
304
319
|
if (scope === "project") {
|
|
305
320
|
this.assertProjectTrustedForScope(scope);
|
|
@@ -308,7 +323,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
308
323
|
}
|
|
309
324
|
return join(this.agentDir, "git");
|
|
310
325
|
}
|
|
311
|
-
@@ -
|
|
326
|
+
@@ -1772,7 +1797,7 @@ export class DefaultPackageManager {
|
|
312
327
|
getBaseDirForScope(scope) {
|
|
313
328
|
if (scope === "project") {
|
|
314
329
|
this.assertProjectTrustedForScope(scope);
|
|
@@ -317,7 +332,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
317
332
|
}
|
|
318
333
|
if (scope === "user") {
|
|
319
334
|
return this.agentDir;
|
|
320
|
-
@@ -
|
|
335
|
+
@@ -1783,7 +1808,30 @@ export class DefaultPackageManager {
|
|
321
336
|
return resolvePath(input, this.cwd, { homeDir: getHomeDir(), trim: true });
|
|
322
337
|
}
|
|
323
338
|
resolvePathFromBase(input, baseDir) {
|
|
@@ -349,7 +364,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
349
364
|
}
|
|
350
365
|
collectPackageResources(packageRoot, accumulator, filter, metadata) {
|
|
351
366
|
if (filter) {
|
|
352
|
-
@@ -
|
|
367
|
+
@@ -1928,19 +1976,24 @@ export class DefaultPackageManager {
|
|
353
368
|
this.addResource(target, f, metadata, enabledPaths.has(f));
|
|
354
369
|
}
|
|
355
370
|
}
|
|
@@ -378,7 +393,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
378
393
|
const userOverrides = {
|
|
379
394
|
extensions: (globalSettings.extensions ?? []),
|
|
380
395
|
skills: (globalSettings.skills ?? []),
|
|
381
|
-
@@ -
|
|
396
|
+
@@ -1959,12 +2012,12 @@ export class DefaultPackageManager {
|
|
382
397
|
prompts: join(globalBaseDir, "prompts"),
|
|
383
398
|
themes: join(globalBaseDir, "themes"),
|
|
384
399
|
};
|
|
@@ -397,7 +412,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
397
412
|
const userAgentsSkillsDir = join(getHomeDir(), ".agents", "skills");
|
|
398
413
|
const projectTrusted = this.settingsManager.isProjectTrusted();
|
|
399
414
|
const projectAgentsSkillDirs = projectTrusted
|
|
400
|
-
@@ -
|
|
415
|
+
@@ -1978,10 +2031,13 @@ export class DefaultPackageManager {
|
|
401
416
|
}
|
|
402
417
|
};
|
|
403
418
|
if (projectTrusted) {
|
|
@@ -415,7 +430,7 @@ index a125c9a..5ca0ccc 100644
|
|
|
415
430
|
}
|
|
416
431
|
// Project skills from .agents/ (each with its own baseDir)
|
|
417
432
|
for (const agentsSkillsDir of projectAgentsSkillDirs) {
|
|
418
|
-
@@ -
|
|
433
|
+
@@ -1993,8 +2049,11 @@ export class DefaultPackageManager {
|
|
419
434
|
addResources("skills", collectAutoSkillEntries(agentsSkillsDir, "agents"), agentsMetadata, projectOverrides.skills, agentsBaseDir);
|
|
420
435
|
}
|
|
421
436
|
if (projectTrusted) {
|
|
@@ -445,7 +460,7 @@ index c4f2509..a4402df 100644
|
|
|
445
460
|
async function selectProjectTrustOption(cwd, ctx) {
|
|
446
461
|
const options = getProjectTrustOptions(cwd, { includeSessionOnly: true });
|
|
447
462
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/prompt-templates.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/prompt-templates.js
|
|
448
|
-
index
|
|
463
|
+
index 3700c08..79cb85e 100644
|
|
449
464
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/prompt-templates.js
|
|
450
465
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/prompt-templates.js
|
|
451
466
|
@@ -1,6 +1,6 @@
|
|
@@ -488,19 +503,19 @@ index ae4a7d4..a251c37 100644
|
|
|
488
503
|
// 3. Load explicit prompt paths
|
|
489
504
|
for (const rawPath of promptPaths) {
|
|
490
505
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js
|
|
491
|
-
index
|
|
506
|
+
index 97af6cd..74d5d52 100644
|
|
492
507
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js
|
|
493
508
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js
|
|
494
509
|
@@ -1,7 +1,7 @@
|
|
495
510
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
496
|
-
import { join, resolve, sep } from "node:path";
|
|
511
|
+
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
497
512
|
import chalk from "chalk";
|
|
498
513
|
-import { CONFIG_DIR_NAME } from "../config.js";
|
|
499
514
|
+import { findProjectConfigPath, projectConfigDirCandidates, projectConfigDirs } from "../config.js";
|
|
500
515
|
import { loadThemeFromPath } from "../modes/interactive/theme/theme.js";
|
|
501
516
|
import { canonicalizePath, isLocalPath, resolvePath } from "../utils/paths.js";
|
|
502
517
|
import { createEventBus } from "./event-bus.js";
|
|
503
|
-
@@ -
|
|
518
|
+
@@ -624,12 +624,14 @@ export class DefaultResourceLoader {
|
|
504
519
|
join(this.agentDir, "themes"),
|
|
505
520
|
join(this.agentDir, "extensions"),
|
|
506
521
|
];
|
|
@@ -521,7 +536,7 @@ index 74e36fe..7dfef45 100644
|
|
|
521
536
|
for (const root of agentRoots) {
|
|
522
537
|
if (this.isUnderPath(normalizedPath, root)) {
|
|
523
538
|
return { path: filePath, source: "local", scope: "user", origin: "top-level", baseDir: root };
|
|
524
|
-
@@ -
|
|
539
|
+
@@ -668,7 +670,11 @@ export class DefaultResourceLoader {
|
|
525
540
|
const themes = [];
|
|
526
541
|
const diagnostics = [];
|
|
527
542
|
if (includeDefaults) {
|
|
@@ -534,7 +549,7 @@ index 74e36fe..7dfef45 100644
|
|
|
534
549
|
for (const dir of defaultDirs) {
|
|
535
550
|
this.loadThemesFromDir(dir, themes, diagnostics);
|
|
536
551
|
}
|
|
537
|
-
@@ -
|
|
552
|
+
@@ -806,8 +812,9 @@ export class DefaultResourceLoader {
|
|
538
553
|
return { themes: Array.from(seen.values()), diagnostics };
|
|
539
554
|
}
|
|
540
555
|
discoverSystemPromptFile() {
|
|
@@ -546,7 +561,7 @@ index 74e36fe..7dfef45 100644
|
|
|
546
561
|
return projectPath;
|
|
547
562
|
}
|
|
548
563
|
const globalPath = join(this.agentDir, "SYSTEM.md");
|
|
549
|
-
@@ -
|
|
564
|
+
@@ -817,8 +824,9 @@ export class DefaultResourceLoader {
|
|
550
565
|
return undefined;
|
|
551
566
|
}
|
|
552
567
|
discoverAppendSystemPromptFile() {
|
|
@@ -559,7 +574,7 @@ index 74e36fe..7dfef45 100644
|
|
|
559
574
|
}
|
|
560
575
|
const globalPath = join(this.agentDir, "APPEND_SYSTEM.md");
|
|
561
576
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js
|
|
562
|
-
index
|
|
577
|
+
index cb06c10..930a0de 100644
|
|
563
578
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js
|
|
564
579
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js
|
|
565
580
|
@@ -2,7 +2,7 @@ import { randomUUID } from "crypto";
|
|
@@ -570,8 +585,8 @@ index 5910aac..f379c0f 100644
|
|
|
570
585
|
+import { getAgentDir, projectConfigDirCandidates, projectConfigWriteDir } from "../config.js";
|
|
571
586
|
import { normalizePath, resolvePath } from "../utils/paths.js";
|
|
572
587
|
import { DEFAULT_HTTP_IDLE_TIMEOUT_MS, parseHttpIdleTimeoutMs } from "./http-dispatcher.js";
|
|
573
|
-
|
|
574
|
-
@@ -
|
|
588
|
+
function isMergeableObject(value) {
|
|
589
|
+
@@ -37,14 +37,112 @@ function parseTimeoutSetting(value, settingName) {
|
|
575
590
|
}
|
|
576
591
|
return undefined;
|
|
577
592
|
}
|
|
@@ -685,7 +700,7 @@ index 5910aac..f379c0f 100644
|
|
|
685
700
|
}
|
|
686
701
|
acquireLockSyncWithRetry(path) {
|
|
687
702
|
const maxAttempts = 10;
|
|
688
|
-
@@ -
|
|
703
|
+
@@ -71,7 +169,13 @@ export class FileSettingsStorage {
|
|
689
704
|
throw lastError ?? new Error("Failed to acquire settings lock");
|
|
690
705
|
}
|
|
691
706
|
withLock(scope, fn) {
|
|
@@ -770,11 +785,37 @@ index 17af938..6d97caa 100644
|
|
|
770
785
|
}
|
|
771
786
|
while (true) {
|
|
772
787
|
const agentsSkillsDir = join(currentDir, ".agents", "skills");
|
|
788
|
+
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts b/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts
|
|
789
|
+
index 7d3e24c..578ada5 100644
|
|
790
|
+
--- a/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts
|
|
791
|
+
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts
|
|
792
|
+
@@ -1,7 +1,7 @@
|
|
793
|
+
export { type Args, parseArgs } from "./cli/args.ts";
|
|
794
|
+
export { CONFIG_DIR_NAME, getAgentDir, getDocsPath, getExamplesPath, getPackageDir, getReadmePath, VERSION, } from "./config.ts";
|
|
795
|
+
export { AgentSession, type AgentSessionConfig, type AgentSessionEvent, type AgentSessionEventListener, type ModelCycleResult, type ParsedSkillBlock, type PromptOptions, parseSkillBlock, type SessionStats, } from "./core/agent-session.ts";
|
|
796
|
+
-export { readStoredCredential } from "./core/auth-storage.ts";
|
|
797
|
+
+export { AuthStorage, readStoredCredential } from "./core/auth-storage.ts";
|
|
798
|
+
export { type BranchPreparation, type BranchSummaryResult, type CollectEntriesResult, type CompactionResult, type CutPointResult, calculateContextTokens, collectEntriesForBranchSummary, compact, DEFAULT_COMPACTION_SETTINGS, estimateTokens, type FileOperations, findCutPoint, findTurnStartIndex, type GenerateBranchSummaryOptions, generateBranchSummary, generateSummary, generateSummaryWithUsage, getLastAssistantUsage, prepareBranchEntries, serializeConversation, shouldCompact, } from "./core/compaction/index.ts";
|
|
799
|
+
export { createEventBus, type EventBus, type EventBusController } from "./core/event-bus.ts";
|
|
800
|
+
export type { AgentEndEvent, AgentSettledEvent, AgentStartEvent, AgentToolResult, AgentToolUpdateCallback, AppKeybinding, AutocompleteProviderFactory, BashToolCallEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderHeadersEvent, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, BuildSystemPromptOptions, CompactOptions, ContextEvent, ContextUsage, CustomToolCallEvent, EditToolCallEvent, EntryRenderer, EntryRenderOptions, ExecOptions, ExecResult, Extension, ExtensionActions, ExtensionAPI, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFactory, ExtensionFlag, ExtensionHandler, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetOptions, FindToolCallEvent, GrepToolCallEvent, InlineExtension, InputEvent, InputEventResult, InputSource, KeybindingsManager, LoadExtensionsResult, LsToolCallEvent, MarkdownTransformContext, MarkdownTransformer, MessageEndEvent, MessageRenderer, MessageRenderOptions, MessageStartEvent, MessageUpdateEvent, ProjectTrustContext, ProjectTrustEvent, ProjectTrustEventDecision, ProjectTrustEventResult, ProjectTrustHandler, ProviderConfig, ProviderModelConfig, ReadToolCallEvent, RegisteredCommand, RegisteredTool, ResolvedCommand, SessionBeforeCompactEvent, SessionBeforeForkEvent, SessionBeforeSwitchEvent, SessionBeforeTreeEvent, SessionCompactEvent, SessionInfoChangedEvent, SessionShutdownEvent, SessionStartEvent, SessionTreeEvent, SlashCommandInfo, SlashCommandSource, SourceInfo, TerminalInputHandler, ToolCallEvent, ToolCallEventResult, ToolDefinition, ToolExecutionEndEvent, ToolExecutionMode, ToolExecutionStartEvent, ToolExecutionUpdateEvent, ToolInfo, ToolRenderResultOptions, ToolResultEvent, TurnEndEvent, TurnStartEvent, UserBashEvent, UserBashEventResult, WidgetPlacement, WorkingIndicatorOptions, WriteToolCallEvent, } from "./core/extensions/index.ts";
|
|
801
|
+
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/index.js b/node_modules/@earendil-works/pi-coding-agent/dist/index.js
|
|
802
|
+
index 76d728e..2b2c892 100644
|
|
803
|
+
--- a/node_modules/@earendil-works/pi-coding-agent/dist/index.js
|
|
804
|
+
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/index.js
|
|
805
|
+
@@ -3,7 +3,7 @@ export { parseArgs } from "./cli/args.js";
|
|
806
|
+
// Config paths
|
|
807
|
+
export { CONFIG_DIR_NAME, getAgentDir, getDocsPath, getExamplesPath, getPackageDir, getReadmePath, VERSION, } from "./config.js";
|
|
808
|
+
export { AgentSession, parseSkillBlock, } from "./core/agent-session.js";
|
|
809
|
+
-export { readStoredCredential } from "./core/auth-storage.js";
|
|
810
|
+
+export { AuthStorage, readStoredCredential } from "./core/auth-storage.js";
|
|
811
|
+
// Compaction
|
|
812
|
+
export { calculateContextTokens, collectEntriesForBranchSummary, compact, DEFAULT_COMPACTION_SETTINGS, estimateTokens, findCutPoint, findTurnStartIndex, generateBranchSummary, generateSummary, generateSummaryWithUsage, getLastAssistantUsage, prepareBranchEntries, serializeConversation, shouldCompact, } from "./core/compaction/index.js";
|
|
813
|
+
export { createEventBus } from "./core/event-bus.js";
|
|
773
814
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/main.js b/node_modules/@earendil-works/pi-coding-agent/dist/main.js
|
|
774
|
-
index
|
|
815
|
+
index 5ff9c80..5b91d5f 100644
|
|
775
816
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/main.js
|
|
776
817
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/main.js
|
|
777
|
-
@@ -
|
|
818
|
+
@@ -786,7 +786,58 @@ export async function main(args, options) {
|
|
778
819
|
if (exitCode !== 0) {
|
|
779
820
|
process.exitCode = exitCode;
|
|
780
821
|
}
|
|
@@ -869,7 +910,7 @@ index e3a5ccf..a561a8a 100644
|
|
|
869
910
|
return warnings;
|
|
870
911
|
}
|
|
871
912
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js
|
|
872
|
-
index
|
|
913
|
+
index 6f7ed6a..b0ed0ae 100644
|
|
873
914
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js
|
|
874
915
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js
|
|
875
916
|
@@ -4,7 +4,7 @@
|
|
@@ -877,11 +918,11 @@ index 3355a47..8c6bba9 100644
|
|
|
877
918
|
import { basename, dirname, join, relative } from "node:path";
|
|
878
919
|
import { Container, getKeybindings, Input, matchesKey, Spacer, truncateToWidth, visibleWidth, } from "@earendil-works/pi-tui";
|
|
879
920
|
-import { CONFIG_DIR_NAME } from "../../../config.js";
|
|
880
|
-
+import { formatProjectConfigDirNames, projectConfigDirs, projectConfigWriteDir } from "../../../config.js";
|
|
921
|
+
+import { CONFIG_DIR_NAME, PROJECT_CONFIG_DIR_NAMES, formatProjectConfigDirNames, projectConfigDirs, projectConfigWriteDir } from "../../../config.js";
|
|
922
|
+
import { canonicalizePath, isLocalPath, resolvePath } from "../../../utils/paths.js";
|
|
881
923
|
import { theme } from "../theme/theme.js";
|
|
882
924
|
import { DynamicBorder } from "./dynamic-border.js";
|
|
883
|
-
|
|
884
|
-
@@ -41,7 +41,7 @@ function getGroupLabel(metadata, agentDir) {
|
|
925
|
+
@@ -43,7 +43,7 @@ function getGroupLabel(metadata, agentDir) {
|
|
885
926
|
? `User (${formatBaseDir(metadata.baseDir)})`
|
|
886
927
|
: `Project (${formatBaseDir(metadata.baseDir)})`;
|
|
887
928
|
}
|
|
@@ -890,8 +931,17 @@ index 3355a47..8c6bba9 100644
|
|
|
890
931
|
}
|
|
891
932
|
return metadata.scope === "user" ? "User settings" : "Project settings";
|
|
892
933
|
}
|
|
893
|
-
@@ -
|
|
894
|
-
|
|
934
|
+
@@ -141,7 +141,7 @@ class ConfigSelectorHeader {
|
|
935
|
+
const hint = switchHint + actionHint + sep + rawKeyHint("esc", "close");
|
|
936
|
+
const spacing = Math.max(1, width - visibleWidth(title) - visibleWidth(hint));
|
|
937
|
+
const scopeHint = this.writeScope === "project"
|
|
938
|
+
- ? theme.fg("muted", `${CONFIG_DIR_NAME}/settings.json · inherited global resources are dimmed`)
|
|
939
|
+
+ ? theme.fg("muted", `${PROJECT_CONFIG_DIR_NAMES[0]}/settings.json · inherited global resources are dimmed`)
|
|
940
|
+
: theme.fg("muted", `~/${CONFIG_DIR_NAME}/agent/settings.json`);
|
|
941
|
+
return [
|
|
942
|
+
truncateToWidth(`${title}${" ".repeat(spacing)}${hint}`, width, ""),
|
|
943
|
+
@@ -695,7 +695,12 @@ class ResourceList {
|
|
944
|
+
return item.metadata.scope === "project" ? "project" : "user";
|
|
895
945
|
}
|
|
896
946
|
getTopLevelBaseDir(scope) {
|
|
897
947
|
- return scope === "project" ? join(this.cwd, CONFIG_DIR_NAME) : this.agentDir;
|
|
@@ -904,20 +954,88 @@ index 3355a47..8c6bba9 100644
|
|
|
904
954
|
}
|
|
905
955
|
getResourcePattern(item) {
|
|
906
956
|
const scope = item.metadata.scope;
|
|
957
|
+
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js
|
|
958
|
+
index 1d9f046..2a1fba8 100644
|
|
959
|
+
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js
|
|
960
|
+
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js
|
|
961
|
+
@@ -1,5 +1,5 @@
|
|
962
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
963
|
+
-import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
964
|
+
+import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
965
|
+
import { areExperimentalFeaturesEnabled } from "../../../core/experimental.js";
|
|
966
|
+
import { addUsageToTotals, createUsageTotals } from "../../../core/usage-totals.js";
|
|
967
|
+
import { theme } from "../theme/theme.js";
|
|
968
|
+
@@ -14,6 +14,43 @@ function sanitizeStatusText(text) {
|
|
969
|
+
.replace(/ +/g, " ")
|
|
970
|
+
.trim();
|
|
971
|
+
}
|
|
972
|
+
+/**
|
|
973
|
+
+ * Lay extension statuses out over as many lines as the terminal needs, keeping
|
|
974
|
+
+ * each status whole. Upstream joined them into ONE line and truncated it to the
|
|
975
|
+
+ * width, which silently hid whatever didn't fit — and what didn't fit was often
|
|
976
|
+
+ * the loudest indicator on screen (Privateer's "permission gate OFF" flag). A
|
|
977
|
+
+ * status too wide to fit on a line of its own is wrapped, never clipped.
|
|
978
|
+
+ */
|
|
979
|
+
+function packStatusLines(statuses, width) {
|
|
980
|
+
+ if (width <= 0)
|
|
981
|
+
+ return [];
|
|
982
|
+
+ const lines = [];
|
|
983
|
+
+ let current = "";
|
|
984
|
+
+ let currentWidth = 0;
|
|
985
|
+
+ const flush = () => {
|
|
986
|
+
+ if (current)
|
|
987
|
+
+ lines.push(current);
|
|
988
|
+
+ current = "";
|
|
989
|
+
+ currentWidth = 0;
|
|
990
|
+
+ };
|
|
991
|
+
+ for (const status of statuses) {
|
|
992
|
+
+ if (!status)
|
|
993
|
+
+ continue;
|
|
994
|
+
+ const statusWidth = visibleWidth(status);
|
|
995
|
+
+ if (statusWidth > width) {
|
|
996
|
+
+ flush();
|
|
997
|
+
+ lines.push(...wrapTextWithAnsi(status, width));
|
|
998
|
+
+ continue;
|
|
999
|
+
+ }
|
|
1000
|
+
+ const separator = current ? 1 : 0;
|
|
1001
|
+
+ if (currentWidth + separator + statusWidth > width)
|
|
1002
|
+
+ flush();
|
|
1003
|
+
+ current = current ? `${current} ${status}` : status;
|
|
1004
|
+
+ currentWidth += separator + statusWidth;
|
|
1005
|
+
+ }
|
|
1006
|
+
+ flush();
|
|
1007
|
+
+ return lines;
|
|
1008
|
+
+}
|
|
1009
|
+
/**
|
|
1010
|
+
* Format token counts for compact footer display.
|
|
1011
|
+
*/
|
|
1012
|
+
@@ -212,9 +249,9 @@ export class FooterComponent {
|
|
1013
|
+
const sortedStatuses = Array.from(extensionStatuses.entries())
|
|
1014
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
1015
|
+
.map(([, text]) => sanitizeStatusText(text));
|
|
1016
|
+
- const statusLine = sortedStatuses.join(" ");
|
|
1017
|
+
- // Truncate to terminal width with dim ellipsis for consistency with footer style
|
|
1018
|
+
- lines.push(truncateToWidth(statusLine, width, theme.fg("dim", "...")));
|
|
1019
|
+
+ // Wrap onto extra lines instead of truncating: a status is there because
|
|
1020
|
+
+ // something wants to be seen, so none of them may be cut off.
|
|
1021
|
+
+ lines.push(...packStatusLines(sortedStatuses, width));
|
|
1022
|
+
}
|
|
1023
|
+
return lines;
|
|
1024
|
+
}
|
|
907
1025
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js
|
|
908
|
-
index
|
|
1026
|
+
index 42e655d..d00bec9 100644
|
|
909
1027
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js
|
|
910
1028
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js
|
|
911
|
-
@@ -10,7 +10,7 @@ import
|
|
912
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText,
|
|
1029
|
+
@@ -10,7 +10,7 @@ import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
1030
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
913
1031
|
import chalk from "chalk";
|
|
914
1032
|
import { spawn, spawnSync } from "child_process";
|
|
915
1033
|
-import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
|
|
916
1034
|
+import { APP_NAME, APP_TITLE, formatProjectConfigDirNames, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
|
|
917
1035
|
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
918
1036
|
import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
|
|
919
|
-
import {
|
|
920
|
-
@@ -
|
|
1037
|
+
import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
|
|
1038
|
+
@@ -119,7 +119,12 @@ export function formatResumeCommand(sessionManager) {
|
|
921
1039
|
const sessionFile = sessionManager.getSessionFile();
|
|
922
1040
|
if (!sessionFile || !fs.existsSync(sessionFile))
|
|
923
1041
|
return undefined;
|
|
@@ -931,7 +1049,7 @@ index 5d65200..f827cd7 100644
|
|
|
931
1049
|
if (!sessionManager.usesDefaultSessionDir()) {
|
|
932
1050
|
args.push("--session-dir", quoteIfNeeded(sessionManager.getSessionDir()));
|
|
933
1051
|
}
|
|
934
|
-
@@ -
|
|
1052
|
+
@@ -405,9 +410,15 @@ export class InteractiveMode {
|
|
935
1053
|
}
|
|
936
1054
|
getBuiltInCommandConflictDiagnostics(extensionRunner) {
|
|
937
1055
|
const builtinNames = new Set(BUILTIN_SLASH_COMMANDS.map((command) => command.name));
|
|
@@ -948,7 +1066,40 @@ index 5d65200..f827cd7 100644
|
|
|
948
1066
|
.map((command) => ({
|
|
949
1067
|
type: "warning",
|
|
950
1068
|
message: command.invocationName === command.name
|
|
951
|
-
@@ -
|
|
1069
|
+
@@ -754,20 +765,18 @@ export class InteractiveMode {
|
|
1070
|
+
this.showNewVersionNotification(newRelease);
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
- // Start package update check asynchronously
|
|
1074
|
+
- this.checkForPackageUpdates()
|
|
1075
|
+
- .then((updates) => {
|
|
1076
|
+
- if (updates.length > 0) {
|
|
1077
|
+
- this.showPackageUpdateNotification(updates);
|
|
1078
|
+
- }
|
|
1079
|
+
- })
|
|
1080
|
+
- .finally(() => {
|
|
1081
|
+
- // On Windows, npm can overwrite the shared console title while checking
|
|
1082
|
+
- // extension package versions. Restore Pi's title after the startup check.
|
|
1083
|
+
- if (process.platform === "win32" && this.isInitialized) {
|
|
1084
|
+
- this.updateTerminalTitle();
|
|
1085
|
+
- }
|
|
1086
|
+
- });
|
|
1087
|
+
+ // Privateer owns the package ("tool pack") update surface — see
|
|
1088
|
+
+ // extensions/privateer-update.ts. Upstream ran its own check here and drew a
|
|
1089
|
+
+ // warning-bordered box telling the user to run `pi update --extensions`: a
|
|
1090
|
+
+ // binary that is installed nowhere on a Privateer machine, so the only
|
|
1091
|
+
+ // instruction on screen could not be followed. We replace it with a single
|
|
1092
|
+
+ // line in the startup banner plus /update, which applies packs in place. The
|
|
1093
|
+
+ // CHECK is removed too, not just the box, so this costs no registry round
|
|
1094
|
+
+ // trip — the extension does exactly one, on the same startup.
|
|
1095
|
+
+ //
|
|
1096
|
+
+ // 0.84.1 added a .finally() here restoring the Windows console title after
|
|
1097
|
+
+ // npm overwrote it. That repair existed only because of this check, so it
|
|
1098
|
+
+ // goes with it — nothing is left to scribble on the title.
|
|
1099
|
+
// Check tmux keyboard setup asynchronously
|
|
1100
|
+
this.checkTmuxKeyboardSetup().then((warning) => {
|
|
1101
|
+
if (warning) {
|
|
1102
|
+
@@ -2310,7 +2319,17 @@ export class InteractiveMode {
|
|
952
1103
|
if (text === "/model" || text.startsWith("/model ")) {
|
|
953
1104
|
const searchTerm = text.startsWith("/model ") ? text.slice(7).trim() : undefined;
|
|
954
1105
|
this.editor.setText("");
|
|
@@ -967,14 +1118,11 @@ index 5d65200..f827cd7 100644
|
|
|
967
1118
|
return;
|
|
968
1119
|
}
|
|
969
1120
|
if (text === "/export" || text.startsWith("/export ")) {
|
|
970
|
-
@@ -
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
}
|
|
974
|
-
- if (text === "/login") {
|
|
975
|
-
- this.showOAuthSelector("login");
|
|
976
|
-
+ if (text === "/login" || text.startsWith("/login ")) {
|
|
1121
|
+
@@ -2376,12 +2395,42 @@ export class InteractiveMode {
|
|
1122
|
+
if (text === "/login" || text.startsWith("/login ")) {
|
|
1123
|
+
const providerRef = text.startsWith("/login ") ? text.slice(7).trim() : undefined;
|
|
977
1124
|
this.editor.setText("");
|
|
1125
|
+
- await this.handleLoginCommand(providerRef);
|
|
978
1126
|
+ // Privateer redirect: a bare /login IS the account sign-in. Pi's built-in
|
|
979
1127
|
+ // opens a two-step menu ("Use a subscription" → a list of 20+ providers)
|
|
980
1128
|
+ // that buries the one option a Privateer user wants, and — because it
|
|
@@ -982,14 +1130,14 @@ index 5d65200..f827cd7 100644
|
|
|
982
1130
|
+ // successful login through it left the terminal on its launch model and
|
|
983
1131
|
+ // the next prompt died on "No API key found". The extension's own flow
|
|
984
1132
|
+ // signs in, arms the account channel, and selects the model.
|
|
985
|
-
+ // `/login <anything>` (documented as `/login keys`) still
|
|
986
|
-
+ //
|
|
987
|
-
+ // isn't loaded we fall back to Pi
|
|
988
|
-
+ if (
|
|
1133
|
+
+ // `/login <anything>` (documented as `/login keys`) still reaches Pi's
|
|
1134
|
+
+ // own flow, so BYO provider keys stay reachable; and if the extension
|
|
1135
|
+
+ // isn't loaded we fall back to Pi for both.
|
|
1136
|
+
+ if (!providerRef && this.isExtensionCommand("/privateer")) {
|
|
989
1137
|
+ await this.session.prompt("/privateer login");
|
|
990
1138
|
+ }
|
|
991
1139
|
+ else {
|
|
992
|
-
+ this.
|
|
1140
|
+
+ await this.handleLoginCommand(providerRef);
|
|
993
1141
|
+ }
|
|
994
1142
|
return;
|
|
995
1143
|
}
|
|
@@ -1015,7 +1163,7 @@ index 5d65200..f827cd7 100644
|
|
|
1015
1163
|
return;
|
|
1016
1164
|
}
|
|
1017
1165
|
if (text === "/new") {
|
|
1018
|
-
@@ -
|
|
1166
|
+
@@ -3024,7 +3073,7 @@ export class InteractiveMode {
|
|
1019
1167
|
if (this.chatContainer.children.length > 0) {
|
|
1020
1168
|
this.chatContainer.addChild(new Spacer(1));
|
|
1021
1169
|
}
|
|
@@ -1025,19 +1173,28 @@ index 5d65200..f827cd7 100644
|
|
|
1025
1173
|
async getUserInput() {
|
|
1026
1174
|
const queuedInput = this.pendingUserInputs.shift();
|
|
1027
1175
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js b/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js
|
|
1028
|
-
index
|
|
1176
|
+
index 4230b18..f47e80f 100644
|
|
1029
1177
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js
|
|
1030
1178
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js
|
|
1031
|
-
@@ -
|
|
1179
|
+
@@ -3,7 +3,7 @@ import { Markdown } from "@earendil-works/pi-tui";
|
|
1032
1180
|
import chalk from "chalk";
|
|
1033
1181
|
import { selectConfig } from "./cli/config-selector.js";
|
|
1034
1182
|
import { createProjectTrustContext } from "./cli/project-trust.js";
|
|
1035
1183
|
-import { APP_NAME, CONFIG_DIR_NAME, detectInstallMethod, getAgentDir, getPackageDir, getSelfUpdateCommand, getSelfUpdateUnavailableInstruction, PACKAGE_NAME, VERSION, } from "./config.js";
|
|
1036
|
-
+import { APP_NAME, detectInstallMethod, getAgentDir, getPackageDir, getSelfUpdateCommand, getSelfUpdateUnavailableInstruction, PACKAGE_NAME, PROJECT_CONFIG_DIR_NAMES, VERSION, } from "./config.js";
|
|
1184
|
+
+import { APP_NAME, CONFIG_DIR_NAME, detectInstallMethod, getAgentDir, getPackageDir, getSelfUpdateCommand, getSelfUpdateUnavailableInstruction, PACKAGE_NAME, PROJECT_CONFIG_DIR_NAMES, VERSION, } from "./config.js";
|
|
1185
|
+
import { ModelRuntime } from "./core/model-runtime.js";
|
|
1037
1186
|
import { DefaultPackageManager } from "./core/package-manager.js";
|
|
1038
1187
|
import { resolveProjectTrusted } from "./core/project-trust.js";
|
|
1039
|
-
|
|
1040
|
-
|
|
1188
|
+
@@ -60,7 +60,7 @@ Without -l, starts in global settings (~/${CONFIG_DIR_NAME}/agent/settings.json)
|
|
1189
|
+
Press Tab in the TUI to switch between global and project-local modes.
|
|
1190
|
+
|
|
1191
|
+
Options:
|
|
1192
|
+
- -l, --local Edit project overrides (${CONFIG_DIR_NAME}/settings.json)
|
|
1193
|
+
+ -l, --local Edit project overrides (${PROJECT_CONFIG_DIR_NAMES[0]}/settings.json)
|
|
1194
|
+
-a, --approve Trust project-local files for this command with -l
|
|
1195
|
+
-na, --no-approve Ignore project-local files for this command with -l
|
|
1196
|
+
`);
|
|
1197
|
+
@@ -74,7 +74,7 @@ function printPackageCommandHelp(command) {
|
|
1041
1198
|
Install a package and add it to settings.
|
|
1042
1199
|
|
|
1043
1200
|
Options:
|
|
@@ -1046,7 +1203,7 @@ index f81b4b4..9712a37 100644
|
|
|
1046
1203
|
-a, --approve Trust project-local files for this command
|
|
1047
1204
|
-na, --no-approve Ignore project-local files for this command
|
|
1048
1205
|
|
|
1049
|
-
@@ -
|
|
1206
|
+
@@ -95,7 +95,7 @@ Remove a package and its source from settings.
|
|
1050
1207
|
Alias: ${APP_NAME} uninstall <source> [-l]
|
|
1051
1208
|
|
|
1052
1209
|
Options:
|
|
@@ -1055,71 +1212,3 @@ index f81b4b4..9712a37 100644
|
|
|
1055
1212
|
-a, --approve Trust project-local files for this command
|
|
1056
1213
|
-na, --no-approve Ignore project-local files for this command
|
|
1057
1214
|
|
|
1058
|
-
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js
|
|
1059
|
-
index 68d0308..f7208f1 100644
|
|
1060
|
-
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js
|
|
1061
|
-
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js
|
|
1062
|
-
@@ -1,5 +1,5 @@
|
|
1063
|
-
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
1064
|
-
-import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
1065
|
-
+import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
1066
|
-
import { areExperimentalFeaturesEnabled } from "../../../core/experimental.js";
|
|
1067
|
-
import { theme } from "../theme/theme.js";
|
|
1068
|
-
/**
|
|
1069
|
-
@@ -13,6 +13,43 @@ function sanitizeStatusText(text) {
|
|
1070
|
-
.replace(/ +/g, " ")
|
|
1071
|
-
.trim();
|
|
1072
|
-
}
|
|
1073
|
-
+/**
|
|
1074
|
-
+ * Lay extension statuses out over as many lines as the terminal needs, keeping
|
|
1075
|
-
+ * each status whole. Upstream joined them into ONE line and truncated it to the
|
|
1076
|
-
+ * width, which silently hid whatever didn't fit — and what didn't fit was often
|
|
1077
|
-
+ * the loudest indicator on screen (Privateer's "permission gate OFF" flag). A
|
|
1078
|
-
+ * status too wide to fit on a line of its own is wrapped, never clipped.
|
|
1079
|
-
+ */
|
|
1080
|
-
+function packStatusLines(statuses, width) {
|
|
1081
|
-
+ if (width <= 0)
|
|
1082
|
-
+ return [];
|
|
1083
|
-
+ const lines = [];
|
|
1084
|
-
+ let current = "";
|
|
1085
|
-
+ let currentWidth = 0;
|
|
1086
|
-
+ const flush = () => {
|
|
1087
|
-
+ if (current)
|
|
1088
|
-
+ lines.push(current);
|
|
1089
|
-
+ current = "";
|
|
1090
|
-
+ currentWidth = 0;
|
|
1091
|
-
+ };
|
|
1092
|
-
+ for (const status of statuses) {
|
|
1093
|
-
+ if (!status)
|
|
1094
|
-
+ continue;
|
|
1095
|
-
+ const statusWidth = visibleWidth(status);
|
|
1096
|
-
+ if (statusWidth > width) {
|
|
1097
|
-
+ flush();
|
|
1098
|
-
+ lines.push(...wrapTextWithAnsi(status, width));
|
|
1099
|
-
+ continue;
|
|
1100
|
-
+ }
|
|
1101
|
-
+ const separator = current ? 1 : 0;
|
|
1102
|
-
+ if (currentWidth + separator + statusWidth > width)
|
|
1103
|
-
+ flush();
|
|
1104
|
-
+ current = current ? `${current} ${status}` : status;
|
|
1105
|
-
+ currentWidth += separator + statusWidth;
|
|
1106
|
-
+ }
|
|
1107
|
-
+ flush();
|
|
1108
|
-
+ return lines;
|
|
1109
|
-
+}
|
|
1110
|
-
/**
|
|
1111
|
-
* Format token counts for compact footer display.
|
|
1112
|
-
*/
|
|
1113
|
-
@@ -211,9 +248,9 @@ export class FooterComponent {
|
|
1114
|
-
const sortedStatuses = Array.from(extensionStatuses.entries())
|
|
1115
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
1116
|
-
.map(([, text]) => sanitizeStatusText(text));
|
|
1117
|
-
- const statusLine = sortedStatuses.join(" ");
|
|
1118
|
-
- // Truncate to terminal width with dim ellipsis for consistency with footer style
|
|
1119
|
-
- lines.push(truncateToWidth(statusLine, width, theme.fg("dim", "...")));
|
|
1120
|
-
+ // Wrap onto extra lines instead of truncating: a status is there because
|
|
1121
|
-
+ // something wants to be seen, so none of them may be cut off.
|
|
1122
|
-
+ lines.push(...packStatusLines(sortedStatuses, width));
|
|
1123
|
-
}
|
|
1124
|
-
return lines;
|
|
1125
|
-
}
|