pi-code 1.0.59 → 1.0.60
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/extensions/status-line.ts +57 -15
- package/package.json +1 -1
|
@@ -36,6 +36,7 @@ import { claudeEffortLevel } from './internal/effort.js'
|
|
|
36
36
|
import { readManagedSettings } from './internal/managed-settings.js'
|
|
37
37
|
import { isPlanModeState, PLAN_MODE_CHANNEL } from './internal/plan-mode-state.js'
|
|
38
38
|
import { isProjectApprovedSilently } from './internal/project-approval.js'
|
|
39
|
+
import { repoRoot } from './internal/project-root.js'
|
|
39
40
|
import { readSettingsChain } from './internal/settings-chain.js'
|
|
40
41
|
import { watchSettingsFiles } from './internal/settings-watch.js'
|
|
41
42
|
import { readActiveStyleName, settingsFiles } from './output-styles.js'
|
|
@@ -43,6 +44,18 @@ import { readActiveStyleName, settingsFiles } from './output-styles.js'
|
|
|
43
44
|
const COMMAND_TIMEOUT_MS = 5_000
|
|
44
45
|
const DEBOUNCE_MS = 300
|
|
45
46
|
|
|
47
|
+
/** Whether cwd sits in a git worktree: `.git` is a file pointing at the main
|
|
48
|
+
* checkout there, and a directory in an ordinary clone. */
|
|
49
|
+
function isGitWorktree(cwd: string): boolean {
|
|
50
|
+
const root = repoRoot(cwd)
|
|
51
|
+
if (root === undefined) return false
|
|
52
|
+
try {
|
|
53
|
+
return fs.statSync(path.join(root, '.git')).isFile()
|
|
54
|
+
} catch {
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
46
59
|
/** Claude sends its CLI version; pi-code's own version is the honest analogue. */
|
|
47
60
|
const PACKAGE_VERSION = (() => {
|
|
48
61
|
try {
|
|
@@ -235,6 +248,16 @@ export default function statusLine(pi: ExtensionAPI) {
|
|
|
235
248
|
ctx.ui.setStatus('pi-code-status', commandLine ?? builtIn)
|
|
236
249
|
}
|
|
237
250
|
|
|
251
|
+
/** The --add-dir directories, the flag pi-code registers for Claude's additional
|
|
252
|
+
* working directories. Empty when none were given, which is the documented shape. */
|
|
253
|
+
function addedDirs(): string[] {
|
|
254
|
+
const raw = String(pi.getFlag?.('add-dir') ?? '')
|
|
255
|
+
return raw
|
|
256
|
+
.split(',')
|
|
257
|
+
.map((dir) => dir.trim())
|
|
258
|
+
.filter(Boolean)
|
|
259
|
+
}
|
|
260
|
+
|
|
238
261
|
/** The stdin payload per Claude's documented statusline contract. */
|
|
239
262
|
function buildPayload(ctx: ExtensionContext): Record<string, unknown> {
|
|
240
263
|
const usage = ctx.getContextUsage() ?? { tokens: null, contextWindow: 0, percent: null }
|
|
@@ -249,9 +272,16 @@ export default function statusLine(pi: ExtensionAPI) {
|
|
|
249
272
|
session_id: ctx.sessionManager.getSessionId(),
|
|
250
273
|
cwd: ctx.cwd,
|
|
251
274
|
version: PACKAGE_VERSION,
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
|
|
275
|
+
// project_dir is the repository, not the directory the session started in: a
|
|
276
|
+
// script labelling the project showed whichever subdirectory it was launched
|
|
277
|
+
// from. git_worktree reports the .git file a worktree carries in place of a
|
|
278
|
+
// directory. added_dirs comes from the --add-dir flag pi-code registers.
|
|
279
|
+
workspace: {
|
|
280
|
+
current_dir: ctx.cwd,
|
|
281
|
+
project_dir: repoRoot(ctx.cwd) ?? ctx.cwd,
|
|
282
|
+
git_worktree: isGitWorktree(ctx.cwd),
|
|
283
|
+
added_dirs: addedDirs(),
|
|
284
|
+
},
|
|
255
285
|
// Both fields, per Claude's documented contract: published statusline scripts
|
|
256
286
|
// read .model.display_name and render the literal "null" when it is missing.
|
|
257
287
|
model: { id: model?.id ?? '', display_name: model?.name ?? model?.id ?? '' },
|
|
@@ -269,17 +299,17 @@ export default function statusLine(pi: ExtensionAPI) {
|
|
|
269
299
|
total_input_tokens: usage.tokens,
|
|
270
300
|
// The per-component breakdown from the last message's usage, which
|
|
271
301
|
// ctx.getContextUsage() (input-side estimate only) cannot provide.
|
|
272
|
-
|
|
302
|
+
// Present before the first response too, as Claude sends them: a script
|
|
303
|
+
// reading current_usage gets null rather than undefined.
|
|
304
|
+
total_output_tokens: lastUsage?.output ?? 0,
|
|
305
|
+
current_usage: lastUsage
|
|
273
306
|
? {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
cache_read_input_tokens: lastUsage.cacheRead,
|
|
279
|
-
cache_creation_input_tokens: lastUsage.cacheWrite,
|
|
280
|
-
},
|
|
307
|
+
input_tokens: lastUsage.input,
|
|
308
|
+
output_tokens: lastUsage.output,
|
|
309
|
+
cache_read_input_tokens: lastUsage.cacheRead,
|
|
310
|
+
cache_creation_input_tokens: lastUsage.cacheWrite,
|
|
281
311
|
}
|
|
282
|
-
:
|
|
312
|
+
: null,
|
|
283
313
|
},
|
|
284
314
|
// The true combined total when a message usage is known, else the input-side estimate.
|
|
285
315
|
exceeds_200k_tokens: (lastUsage?.totalTokens ?? usage.tokens ?? 0) > 200_000,
|
|
@@ -323,9 +353,17 @@ export default function statusLine(pi: ExtensionAPI) {
|
|
|
323
353
|
const result = await runHookCommand(config.command, buildPayload(ctx), COMMAND_TIMEOUT_MS, undefined, undefined, (kill) => {
|
|
324
354
|
killInflight = kill
|
|
325
355
|
})
|
|
326
|
-
|
|
356
|
+
// Claude: "Your script can output multiple lines to create a richer display."
|
|
357
|
+
// pi has one row for every extension status and replaces newlines with spaces
|
|
358
|
+
// before rendering it (footer.js sanitizeStatusText), so the rows are joined
|
|
359
|
+
// here rather than dropped; taking only the first silently lost the rest.
|
|
360
|
+
const rows = result.stdout
|
|
361
|
+
.split('\n')
|
|
362
|
+
.map((line) => line.trim())
|
|
363
|
+
.filter(Boolean)
|
|
364
|
+
.join(' ')
|
|
327
365
|
const pad = ' '.repeat(config.padding)
|
|
328
|
-
commandLine =
|
|
366
|
+
commandLine = rows ? `${pad}${rows}${pad}` : undefined
|
|
329
367
|
show(ctx, segmentText(ctx, ctx.ui.theme.fg('dim', '○')))
|
|
330
368
|
} catch {
|
|
331
369
|
// A replaced or reloaded session invalidates ctx while the command is in
|
|
@@ -463,9 +501,13 @@ export default function statusLine(pi: ExtensionAPI) {
|
|
|
463
501
|
// command change re-resolves and re-runs.
|
|
464
502
|
disposeSettingsWatch()
|
|
465
503
|
disposeSettingsWatch = watchSettingsFiles(files, () => {
|
|
504
|
+
const previousCommand = config?.command
|
|
466
505
|
config = readDisableAllHooks(files) ? undefined : readStatusLineConfig(files)
|
|
467
506
|
armRefresh()
|
|
468
|
-
|
|
507
|
+
// The debounce batches rapid triggers, but a command the user just edited has
|
|
508
|
+
// nothing to batch with: run it now so the result of the edit is immediate.
|
|
509
|
+
if (config?.command !== previousCommand) void runCommand(ctx)
|
|
510
|
+
else scheduleRefresh()
|
|
469
511
|
})
|
|
470
512
|
show(ctx, segmentText(ctx, ctx.ui.theme.fg('dim', '○')))
|
|
471
513
|
scheduleRefresh()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.60",
|
|
4
4
|
"description": "Claude Code experience for the pi coding agent: reads your .claude config (rules, commands, skills, hooks, output styles, MCP servers, agents) and adds todo, checkpoints, memory, web, subagents, and goals",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi",
|