pi-crew 0.10.5 → 0.11.0
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/CHANGELOG.md +292 -0
- package/agents/analyst.md +37 -2
- package/agents/cold-verifier.md +10 -1
- package/agents/councillor-critic.md +39 -0
- package/agents/councillor-pragmatist.md +39 -0
- package/agents/councillor-skeptic.md +41 -0
- package/agents/critic.md +40 -2
- package/agents/designer.md +58 -0
- package/agents/executor.md +39 -2
- package/agents/explorer.md +38 -2
- package/agents/librarian.md +49 -0
- package/agents/oracle.md +54 -0
- package/agents/orchestrator.md +48 -0
- package/agents/planner.md +41 -2
- package/agents/reviewer.md +39 -2
- package/agents/security-reviewer.md +43 -2
- package/agents/test-engineer.md +48 -2
- package/agents/verifier.md +14 -1
- package/agents/writer.md +32 -2
- package/dist/index.mjs +35196 -34789
- package/package.json +170 -169
- package/scripts/watch-agent-transcript.mjs +120 -0
- package/skills/async-worker-recovery/SKILL.md +4 -1
- package/skills/child-pi-spawning/SKILL.md +4 -1
- package/skills/context-artifact-hygiene/SKILL.md +4 -1
- package/skills/council/SKILL.md +24 -45
- package/skills/delegation-patterns/SKILL.md +18 -1
- package/skills/distill-persona/SKILL.md +4 -1
- package/skills/distill-software/SKILL.md +4 -1
- package/skills/event-log-tracing/SKILL.md +4 -1
- package/skills/git-master/SKILL.md +4 -1
- package/skills/iterative-audit/SKILL.md +4 -1
- package/skills/live-agent-lifecycle/SKILL.md +4 -1
- package/skills/mailbox-interactive/SKILL.md +4 -1
- package/skills/model-routing-context/SKILL.md +10 -1
- package/skills/multi-perspective-review/SKILL.md +18 -1
- package/skills/observability-reliability/SKILL.md +4 -1
- package/skills/orchestration/SKILL.md +18 -1
- package/skills/ownership-session-security/SKILL.md +4 -1
- package/skills/pi-extension-lifecycle/SKILL.md +4 -1
- package/skills/post-mortem/SKILL.md +4 -1
- package/skills/read-only-explorer/SKILL.md +4 -1
- package/skills/real-test-pi-crew/SKILL.md +165 -12
- package/skills/requirements-to-task-packet/SKILL.md +10 -1
- package/skills/research/SKILL.md +4 -1
- package/skills/resource-discovery-config/SKILL.md +10 -1
- package/skills/runtime-state-reader/SKILL.md +4 -1
- package/skills/safe-bash/SKILL.md +4 -1
- package/skills/scrutinize/SKILL.md +24 -1
- package/skills/secure-agent-orchestration-review/SKILL.md +4 -1
- package/skills/state-mutation-locking/SKILL.md +4 -1
- package/skills/systematic-debugging/SKILL.md +4 -1
- package/skills/verification-before-done/SKILL.md +18 -1
- package/skills/widget-rendering/SKILL.md +4 -1
- package/skills/workspace-isolation/SKILL.md +4 -1
- package/skills/worktree-isolation/SKILL.md +4 -1
- package/src/config/config-validation.ts +1 -0
- package/src/config/types.ts +8 -0
- package/src/errors.ts +1 -1
- package/src/extension/context-status-injection.ts +2 -2
- package/src/extension/crew-input-router.ts +2 -0
- package/src/extension/crew-vibes/config.ts +1 -56
- package/src/extension/crew-vibes/figures.ts +5 -84
- package/src/extension/crew-vibes/font-detect.ts +1 -1
- package/src/extension/crew-vibes/index.ts +36 -328
- package/src/extension/crew-vibes/render.ts +2 -58
- package/src/extension/help.ts +1 -0
- package/src/extension/knowledge-injection.ts +19 -7
- package/src/extension/post-init-skill-check.ts +32 -0
- package/src/extension/register.ts +9 -1
- package/src/extension/registration/command-registration.ts +5 -1
- package/src/extension/registration/commands/schedules.ts +212 -0
- package/src/extension/registration/commands/shared.ts +56 -1
- package/src/extension/registration/hook-registration.ts +20 -3
- package/src/extension/registration/lifecycle-handlers.ts +16 -2
- package/src/extension/registration/schedule-toast-bridge.ts +109 -0
- package/src/extension/registration/tool-loop-guard.ts +243 -0
- package/src/extension/registration/viewers.ts +66 -1
- package/src/extension/team-tool/handle-schedule.ts +120 -1
- package/src/extension/team-tool/handle-settings.ts +10 -0
- package/src/extension/team-tool/run.ts +42 -1
- package/src/extension/team-tool-types.ts +6 -0
- package/src/prompt/prompt-runtime.ts +25 -6
- package/src/runtime/async-runner.ts +75 -11
- package/src/runtime/background-runner.ts +41 -0
- package/src/runtime/broker/crew-broker-client.ts +45 -2
- package/src/runtime/broker/crew-broker.ts +22 -27
- package/src/runtime/broker/protocol/request-parsers.ts +10 -2
- package/src/runtime/broker/stdin-handshake.ts +87 -0
- package/src/runtime/broker/wait-push.ts +45 -0
- package/src/runtime/detached-run-results.ts +25 -1
- package/src/runtime/foreground-watchdog.ts +24 -5
- package/src/runtime/live-session/live-session-runtime.ts +1 -1
- package/src/runtime/model/model-scope.ts +2 -2
- package/src/runtime/run-tracker.ts +65 -11
- package/src/runtime/scheduling/scheduler.ts +120 -6
- package/src/runtime/settings-store.ts +28 -2
- package/src/runtime/skill-instructions.ts +20 -4
- package/src/runtime/task-runner/child-executor.ts +1 -1
- package/src/runtime/task-runner/prompt-builder.ts +22 -9
- package/src/schema/config-schema.ts +1 -0
- package/src/skills/discover-skills.ts +2 -2
- package/src/state/coordination/locks.ts +17 -2
- package/src/ui/agents-jobs-browser.ts +785 -0
- package/src/ui/dashboard-panes/agents-pane.ts +7 -4
- package/src/ui/dashboard-panes/schedules-pane.ts +154 -0
- package/src/ui/inline-panel/crew-editor.ts +19 -6
- package/src/ui/inline-panel/index.ts +6 -0
- package/src/ui/key-utils.ts +3 -0
- package/src/ui/keybinding-map.ts +56 -2
- package/src/ui/mascot.ts +2 -1
- package/src/ui/overlays/agent-picker-overlay.ts +3 -3
- package/src/ui/overlays/confirm-overlay.ts +3 -2
- package/src/ui/overlays/mailbox-compose-overlay.ts +4 -3
- package/src/ui/overlays/mailbox-detail-overlay.ts +3 -3
- package/src/ui/run-dashboard.ts +257 -6
- package/src/ui/settings-overlay.ts +43 -3
- package/src/ui/transcript-viewer.ts +3 -2
- package/src/ui/widget/index.ts +61 -88
- package/src/ui/widget/widget-formatters.ts +7 -4
- package/src/ui/widget/widget-renderer.ts +134 -174
- package/src/ui/widget/widget-types.ts +0 -7
- package/src/utils/frontmatter.ts +7 -1
- package/src/utils/ndjson.ts +9 -1
- package/src/utils/relative-time.ts +33 -0
- package/src/extension/crew-vibes/footer.ts +0 -313
- package/src/extension/crew-vibes/speed.ts +0 -286
- package/src/ui/dock-footer.ts +0 -49
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: resource-discovery-config
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
pi-crew resource and configuration discovery workflow.
|
|
5
|
+
When NOT to use: runtime state questions (use runtime-state-reader); model-specific config (use model-routing-context).
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "discover agents"
|
|
@@ -58,3 +61,9 @@ node --experimental-strip-types --test test/unit/config-schema-validation.test.t
|
|
|
58
61
|
npm test
|
|
59
62
|
npm pack --dry-run
|
|
60
63
|
```
|
|
64
|
+
|
|
65
|
+
## Self-restraint
|
|
66
|
+
|
|
67
|
+
"Creating nothing is a valid result." If the evidence does not support a meaningful change, say so explicitly rather than inventing one. The next attempt may find stronger evidence; an invented change now damages trust in every future report.
|
|
68
|
+
|
|
69
|
+
"Creating nothing" here means the current discovery already finds what consumers need. Registering resources nobody uses pollutes the discovery surface and slows every lookup.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: runtime-state-reader
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Safe read-only navigation of pi-crew run state.
|
|
5
|
+
When NOT to use: write actions or mutations (use state-mutation-locking); configuration changes (use resource-discovery-config).
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "inspect manifest"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: safe-bash
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Safe shell-command workflow.
|
|
5
|
+
When NOT to use: subprocess orchestration (use child-pi-spawning); destructive operations without sandbox (use ownership-session-security).
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "run this command"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scrutinize
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Outsider-perspective review questioning intent before tracing code.
|
|
5
|
+
When NOT to use: implementation work (use systematic-debugging); trivial one-line fixes that don't warrant outsider review.
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "scrutinize this"
|
|
@@ -84,3 +87,23 @@ If ANY answer is NO → Stop. Complete scrutiny requirements before reporting.
|
|
|
84
87
|
- **One simpler-alternative pass is MANDATORY.** Skip only if user says "don't question scope."
|
|
85
88
|
- **Distinguish claim from verification.** "The PR says X" and "I traced X and confirmed" are different.
|
|
86
89
|
- **No flattery, no hedging.** State the finding.
|
|
90
|
+
|
|
91
|
+
## Budget
|
|
92
|
+
|
|
93
|
+
This skill applies a 3-attempt budget: 1 initial + max 2 re-attempts.
|
|
94
|
+
|
|
95
|
+
Stamp every invocation:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
attempt X of 3 (Y attempts remaining)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
An attempt is one full outsider-perspective review pass. Re-attempt when the review uncovers intent-level questions that change the approach.
|
|
102
|
+
|
|
103
|
+
Re-attempts only when the previous attempt materially changes the decision or risk. Do NOT spend a re-attempt on mechanical changes or already-resolved findings. When exhausted, escalate to the user with options (accept risk / change scope / exceptional budget).
|
|
104
|
+
|
|
105
|
+
## Self-restraint
|
|
106
|
+
|
|
107
|
+
"Creating nothing is a valid result." If the evidence does not support a meaningful change, say so explicitly rather than inventing one. The next attempt may find stronger evidence; an invented change now damages trust in every future report.
|
|
108
|
+
|
|
109
|
+
"Creating nothing" here means concluding the intent was sound and the approach justified — no findings needed. An invented finding to justify the review round damages trust in every future review.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: secure-agent-orchestration-review
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Use when reviewing delegation, skill loading, tool access, worker prompts, artifacts, runtime config, state, ownership, or subprocess execution.
|
|
5
|
+
When NOT to use: pure code quality issues without security implications (use multi-perspective-review); single-file fixes (use scrutinize).
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "review delegation"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: state-mutation-locking
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Durable state mutation and locking workflow.
|
|
5
|
+
When NOT to use: read-only inspection (use runtime-state-reader); single-process non-concurrent edits.
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "modify manifest"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: systematic-debugging
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Four-phase debugging discipline with refuse gates.
|
|
5
|
+
When NOT to use: trivial fixes where root cause is obvious; production incidents needing immediate rollback (use post-mortem after).
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "debug this"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verification-before-done
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Evidence before claims.
|
|
5
|
+
When NOT to use: mid-task self-correction (use scrutinize); pure execution tasks where output IS evidence.
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "done"
|
|
@@ -80,3 +83,17 @@ Stop before saying done if you are using words like "should", "probably", "looks
|
|
|
80
83
|
- **Don't** use fuzzy language like "seems", "probably", "looks like"
|
|
81
84
|
- **Don't** skip providing verification commands for claims
|
|
82
85
|
- **Don't** claim done if you're still using hypotheses instead of evidence
|
|
86
|
+
|
|
87
|
+
## Budget
|
|
88
|
+
|
|
89
|
+
This skill applies a 3-attempt budget: 1 initial + max 2 re-attempts.
|
|
90
|
+
|
|
91
|
+
Stamp every invocation:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
attempt X of 3 (Y attempts remaining)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
An attempt is one fresh verification run (identify command → run → read output → compare to claim). Re-attempt when output contradicts the claim or reveals a new failure mode.
|
|
98
|
+
|
|
99
|
+
Re-attempts only when the previous attempt materially changes the decision or risk. Do NOT spend a re-attempt on mechanical changes or already-resolved findings. When exhausted, escalate to the user with options (accept risk / change scope / exceptional budget).
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: widget-rendering
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Pi TUI crew widget data sources, display priority, and rendering performance.
|
|
5
|
+
When NOT to use: non-TUI displays; backend data sources without widget context (use runtime-state-reader).
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "empty agent"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: workspace-isolation
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Workspace isolation boundaries.
|
|
5
|
+
When NOT to use: concurrent edits within same repo (use worktree-isolation); non-git projects.
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "workspace isolation"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: worktree-isolation
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Conflict-safe git worktree workflow.
|
|
5
|
+
When NOT to use: non-git changes (use direct edit); single-commit patches (use git-master).
|
|
6
|
+
|
|
4
7
|
origin: pi-crew
|
|
5
8
|
triggers:
|
|
6
9
|
- "create worktree"
|
|
@@ -640,6 +640,7 @@ function parseReliabilityConfig(value: unknown): CrewReliabilityConfig | undefin
|
|
|
640
640
|
forcePreflight: parseWithSchema(Type.Boolean(), obj.forcePreflight),
|
|
641
641
|
ambientStatusInjection: parseWithSchema(Type.Boolean(), obj.ambientStatusInjection),
|
|
642
642
|
perWriteValidation: parseWithSchema(Type.Boolean(), obj.perWriteValidation),
|
|
643
|
+
loopGuard: parseWithSchema(Type.Boolean(), obj.loopGuard),
|
|
643
644
|
scopeModels: parseWithSchema(Type.Boolean(), obj.scopeModels),
|
|
644
645
|
};
|
|
645
646
|
return Object.values(reliability).some((entry) => entry !== undefined) ? reliability : undefined;
|
package/src/config/types.ts
CHANGED
|
@@ -274,6 +274,14 @@ export interface CrewReliabilityConfig {
|
|
|
274
274
|
* Set to `false` to disable.
|
|
275
275
|
*/
|
|
276
276
|
perWriteValidation?: boolean;
|
|
277
|
+
/**
|
|
278
|
+
* Tool loop guard (ARCH-1). Warns at 3 consecutive identical tool results
|
|
279
|
+
* (identical args + byte-identical output) and hard-blocks read-only file
|
|
280
|
+
* tools (read/grep/glob/find/ls) at 5 — the model-side infinite-loop
|
|
281
|
+
* failure mode. `ask` repeats within a turn are warned at 2 and the 3rd
|
|
282
|
+
* call refused. Default: true (opt-out). Set to `false` to disable.
|
|
283
|
+
*/
|
|
284
|
+
loopGuard?: boolean;
|
|
277
285
|
/**
|
|
278
286
|
* Opt-in model scope enforcement (F7). When true, subagent model choices
|
|
279
287
|
* that fall outside the user's pi `enabledModels` allowlist are flagged:
|
package/src/errors.ts
CHANGED
|
@@ -64,7 +64,7 @@ const DEFAULT_HELP: Record<ErrorCode, string | undefined> = {
|
|
|
64
64
|
[ErrorCode.RunStale]:
|
|
65
65
|
"The worker stopped heartbeating and was treated as a zombie. Re-run the team (resume or fresh); if it recurs, check `runtime.executeWorkers` / system load.",
|
|
66
66
|
[ErrorCode.ModelOutOfScope]:
|
|
67
|
-
"The requested model is not in your pi `enabledModels` allowlist. Either pick a model listed in `enabledModels` (settings.json) or extend the allowlist. The scope gate is opt-in — disable `
|
|
67
|
+
"The requested model is not in your pi `enabledModels` allowlist. Either pick a model listed in `enabledModels` (settings.json) or extend the allowlist. The scope gate is opt-in — disable `reliability.scopeModels` to allow any model.",
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* - `emitContext` already wraps handlers in try/catch and emits errors instead
|
|
29
29
|
* of crashing the loop (Pi `runner.ts:933`), so a throw here can't break the
|
|
30
30
|
* agent — but we also guard defensively.
|
|
31
|
-
* - Opt-out: `
|
|
31
|
+
* - Opt-out: `reliability.ambientStatusInjection: false` in config.
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
@@ -163,7 +163,7 @@ export function handleContextEvent(event: ContextEvent, cwd: string, sessionId?:
|
|
|
163
163
|
* Register the ambient-status `context` event handler. Reads the project cwd
|
|
164
164
|
* from the session context on each call (crew state is per-project).
|
|
165
165
|
*
|
|
166
|
-
* Pass `enabled: false` (from `
|
|
166
|
+
* Pass `enabled: false` (from `reliability.ambientStatusInjection`) to
|
|
167
167
|
* disable the feature without unwiring the handler.
|
|
168
168
|
*/
|
|
169
169
|
export function registerContextStatusInjection(pi: ExtensionAPI, opts: { enabled?: boolean } = {}): void {
|
|
@@ -34,6 +34,8 @@ export const CREW_PHRASES: ReadonlyArray<{ phrase: string; command: string }> =
|
|
|
34
34
|
{ phrase: "crew commands", command: "/team-help" },
|
|
35
35
|
{ phrase: "crew doctor", command: "/team-doctor" },
|
|
36
36
|
{ phrase: "crew diagnose", command: "/team-doctor" },
|
|
37
|
+
{ phrase: "crew schedule", command: "/schedules" },
|
|
38
|
+
{ phrase: "scheduled jobs", command: "/schedules" },
|
|
37
39
|
{ phrase: "teams", command: "/teams" },
|
|
38
40
|
];
|
|
39
41
|
|
|
@@ -4,12 +4,11 @@ import { getCrewEnv } from "../../config/env-vars.ts";
|
|
|
4
4
|
import { hasCrewFontFile, isWebTerminal } from "./font-detect.ts";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Self-contained config for the crew-vibes module (
|
|
7
|
+
* Self-contained config for the crew-vibes module (provider quota).
|
|
8
8
|
* Stored in its own JSON file so it never touches the strict typebox schema
|
|
9
9
|
* used by the rest of pi-crew.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
export const SPEED_STATUS_ID = "pi-crew-speed";
|
|
13
12
|
export const CAPACITY_STATUS_ID = "pi-crew-bar";
|
|
14
13
|
export const PROVIDER_STATUS_ID = "pi-crew-bar";
|
|
15
14
|
|
|
@@ -23,21 +22,6 @@ export function configPath(): string {
|
|
|
23
22
|
|
|
24
23
|
export type TokenDisplay = "off" | "tokens" | "percentage";
|
|
25
24
|
|
|
26
|
-
export interface SpeedConfig {
|
|
27
|
-
enabled: boolean;
|
|
28
|
-
footer: boolean;
|
|
29
|
-
indicator: boolean;
|
|
30
|
-
label: string;
|
|
31
|
-
renderIntervalMs: number;
|
|
32
|
-
slidingWindowMs: number;
|
|
33
|
-
minReliableDurationMs: number;
|
|
34
|
-
maxDisplayTokS: number;
|
|
35
|
-
defaultIntervalMs: number;
|
|
36
|
-
minIntervalMs: number;
|
|
37
|
-
maxIntervalMs: number;
|
|
38
|
-
scale: number;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
25
|
export interface CapacityConfig {
|
|
42
26
|
enabled: boolean;
|
|
43
27
|
tokenDisplay: TokenDisplay;
|
|
@@ -51,26 +35,11 @@ export interface CapacityConfig {
|
|
|
51
35
|
|
|
52
36
|
export interface CrewVibesConfig {
|
|
53
37
|
enabled: boolean;
|
|
54
|
-
speed: SpeedConfig;
|
|
55
38
|
capacity: CapacityConfig;
|
|
56
39
|
}
|
|
57
40
|
|
|
58
41
|
export const DEFAULT_CONFIG: CrewVibesConfig = {
|
|
59
42
|
enabled: true,
|
|
60
|
-
speed: {
|
|
61
|
-
enabled: true,
|
|
62
|
-
footer: false,
|
|
63
|
-
indicator: true,
|
|
64
|
-
label: "tok/s",
|
|
65
|
-
renderIntervalMs: 250,
|
|
66
|
-
slidingWindowMs: 1000,
|
|
67
|
-
minReliableDurationMs: 1000,
|
|
68
|
-
maxDisplayTokS: 500,
|
|
69
|
-
defaultIntervalMs: 167,
|
|
70
|
-
minIntervalMs: 50,
|
|
71
|
-
maxIntervalMs: 250,
|
|
72
|
-
scale: 6000,
|
|
73
|
-
},
|
|
74
43
|
capacity: {
|
|
75
44
|
enabled: true,
|
|
76
45
|
tokenDisplay: "tokens",
|
|
@@ -133,29 +102,6 @@ function tokenDisplayFrom(raw: unknown, fallback: TokenDisplay): TokenDisplay {
|
|
|
133
102
|
return raw === "off" || raw === "tokens" || raw === "percentage" ? raw : fallback;
|
|
134
103
|
}
|
|
135
104
|
|
|
136
|
-
function normalizeSpeed(raw: unknown): SpeedConfig {
|
|
137
|
-
const input = asRecord(raw);
|
|
138
|
-
const speed: SpeedConfig = {
|
|
139
|
-
enabled: boolFrom(input.enabled, DEFAULT_CONFIG.speed.enabled),
|
|
140
|
-
footer: boolFrom(input.footer, DEFAULT_CONFIG.speed.footer),
|
|
141
|
-
indicator: boolFrom(input.indicator, DEFAULT_CONFIG.speed.indicator),
|
|
142
|
-
label: stringFrom(input.label, DEFAULT_CONFIG.speed.label),
|
|
143
|
-
renderIntervalMs: positiveFrom(input.renderIntervalMs, DEFAULT_CONFIG.speed.renderIntervalMs),
|
|
144
|
-
slidingWindowMs: positiveFrom(input.slidingWindowMs, DEFAULT_CONFIG.speed.slidingWindowMs),
|
|
145
|
-
minReliableDurationMs: positiveFrom(input.minReliableDurationMs, DEFAULT_CONFIG.speed.minReliableDurationMs),
|
|
146
|
-
maxDisplayTokS: positiveFrom(input.maxDisplayTokS, DEFAULT_CONFIG.speed.maxDisplayTokS),
|
|
147
|
-
defaultIntervalMs: positiveFrom(input.defaultIntervalMs, DEFAULT_CONFIG.speed.defaultIntervalMs),
|
|
148
|
-
minIntervalMs: positiveFrom(input.minIntervalMs, DEFAULT_CONFIG.speed.minIntervalMs),
|
|
149
|
-
maxIntervalMs: positiveFrom(input.maxIntervalMs, DEFAULT_CONFIG.speed.maxIntervalMs),
|
|
150
|
-
scale: positiveFrom(input.scale, DEFAULT_CONFIG.speed.scale),
|
|
151
|
-
};
|
|
152
|
-
if (speed.minIntervalMs > speed.maxIntervalMs) {
|
|
153
|
-
speed.minIntervalMs = DEFAULT_CONFIG.speed.minIntervalMs;
|
|
154
|
-
speed.maxIntervalMs = DEFAULT_CONFIG.speed.maxIntervalMs;
|
|
155
|
-
}
|
|
156
|
-
return speed;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
105
|
function normalizeCapacity(raw: unknown): CapacityConfig {
|
|
160
106
|
const input = asRecord(raw);
|
|
161
107
|
return {
|
|
@@ -174,7 +120,6 @@ export function normalizeConfig(raw: unknown): CrewVibesConfig {
|
|
|
174
120
|
const input = asRecord(raw);
|
|
175
121
|
return {
|
|
176
122
|
enabled: boolFrom(input.enabled, DEFAULT_CONFIG.enabled),
|
|
177
|
-
speed: normalizeSpeed(input.speed),
|
|
178
123
|
capacity: normalizeCapacity(input.capacity),
|
|
179
124
|
};
|
|
180
125
|
}
|
|
@@ -1,91 +1,12 @@
|
|
|
1
|
-
import type { SpeedConfig } from "./config.ts";
|
|
2
|
-
import { hasCrewFontFile, isWebTerminal } from "./font-detect.ts";
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The working indicator uses braille spinner characters by default — the
|
|
8
|
-
* same characters pi uses for its built-in loading animation (loaders.ts
|
|
9
|
-
* DEFAULT_FRAMES). These render on ANY terminal with basic Unicode support,
|
|
10
|
-
* no custom font required.
|
|
2
|
+
* Capacity-stage helpers (shared by renderCapacity, which remains exported
|
|
3
|
+
* for its unit tests after the footer retirement).
|
|
11
4
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* AND a terminal that renders Private Use Area codepoints.
|
|
5
|
+
* The speed-UI parts of this module (braille/PUA spinner frames,
|
|
6
|
+
* intervalForSpeed) were REMOVED with the tok/s speed UI (maintainer
|
|
7
|
+
* decision 2026-09-14) — pi's built-in working indicator is always used.
|
|
16
8
|
*/
|
|
17
9
|
|
|
18
|
-
// ── Braille spinner frames (web terminal fallback) ───────────────────
|
|
19
|
-
// Standard Unicode braille spinner — same characters pi uses for its
|
|
20
|
-
// built-in loading animation. Renders on ANY terminal.
|
|
21
|
-
const BRAILLE_FRAMES: readonly string[] = [
|
|
22
|
-
"\u280B ", // ⠋
|
|
23
|
-
"\u2819 ", // ⠙
|
|
24
|
-
"\u2839 ", // ⠹
|
|
25
|
-
"\u2838 ", // ⠸
|
|
26
|
-
"\u283C ", // ⠼
|
|
27
|
-
"\u2834 ", // ⠴
|
|
28
|
-
"\u2826 ", // ⠦
|
|
29
|
-
"\u2827 ", // ⠧
|
|
30
|
-
"\u2807 ", // ⠇
|
|
31
|
-
"\u280F ", // ⠏
|
|
32
|
-
] as const;
|
|
33
|
-
|
|
34
|
-
// ── PUA runner frames (opt-in) ────────────────────────────────────────
|
|
35
|
-
// 16 runner poses from the bundled crew-vibes.ttf font. Only usable when
|
|
36
|
-
// the font is installed AND the terminal renders PUA codepoints correctly.
|
|
37
|
-
// Each frame is one glyph + trailing space for constant 2-cell width.
|
|
38
|
-
const PUA_CREW_FRAMES: readonly string[] = [
|
|
39
|
-
"\uE700 ",
|
|
40
|
-
"\uE701 ",
|
|
41
|
-
"\uE702 ",
|
|
42
|
-
"\uE703 ",
|
|
43
|
-
"\uE704 ",
|
|
44
|
-
"\uE705 ",
|
|
45
|
-
"\uE706 ",
|
|
46
|
-
"\uE707 ",
|
|
47
|
-
"\uE708 ",
|
|
48
|
-
"\uE709 ",
|
|
49
|
-
"\uE70A ",
|
|
50
|
-
"\uE70B ",
|
|
51
|
-
"\uE70C ",
|
|
52
|
-
"\uE70D ",
|
|
53
|
-
"\uE70E ",
|
|
54
|
-
"\uE70F ",
|
|
55
|
-
] as const;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Return the indicator frames for the given style.
|
|
59
|
-
*
|
|
60
|
-
* Default is `"braille"` — standard Unicode braille spinner (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏)
|
|
61
|
-
* that renders correctly on every terminal, every platform, with zero
|
|
62
|
-
* font dependency. PUA runner-glyphs require crew-vibes.ttf installed AND
|
|
63
|
-
* a terminal that does font fallback for Private Use Area codepoints —
|
|
64
|
-
* Windows Terminal does NOT do this reliably, showing garbage chars even
|
|
65
|
-
* with the font installed.
|
|
66
|
-
*
|
|
67
|
-
* To opt into the PUA runner look, pass `style: "pua"` explicitly.
|
|
68
|
-
*/
|
|
69
|
-
export function crewFrames(style: "braille" | "pua" = "braille"): readonly string[] {
|
|
70
|
-
// Even when explicitly requested, fall back to braille if the font is
|
|
71
|
-
// missing or we're on a web terminal (which can't render PUA at all).
|
|
72
|
-
if (style === "pua" && (isWebTerminal() || !hasCrewFontFile())) return BRAILLE_FRAMES;
|
|
73
|
-
return style === "pua" ? PUA_CREW_FRAMES : BRAILLE_FRAMES;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Re-export PUA frames for backward compatibility and direct consumers.
|
|
77
|
-
export const RUN_CREW_FRAMES = PUA_CREW_FRAMES;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Map a tok/s reading to a working-indicator frame interval in ms.
|
|
81
|
-
* Ported from pi-speeed's runcatInterval: interval = scale / speed, clamped
|
|
82
|
-
* to [min, max]. A null/zero speed falls back to the default (idle) cadence.
|
|
83
|
-
*/
|
|
84
|
-
export function intervalForSpeed(config: SpeedConfig, speed: number | null): number {
|
|
85
|
-
if (speed === null || !Number.isFinite(speed) || speed <= 0) return config.defaultIntervalMs;
|
|
86
|
-
return Math.max(config.minIntervalMs, Math.min(config.maxIntervalMs, Math.round(config.scale / speed)));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
10
|
/**
|
|
90
11
|
* Pick the capacity stage index (0..levels-1) for a context-fill percent.
|
|
91
12
|
* Ported from pi-chonk's chonkIndex.
|
|
@@ -8,7 +8,7 @@ import { join } from "node:path";
|
|
|
8
8
|
* guarantee the terminal can render PUA glyphs (many terminals have their
|
|
9
9
|
* own font stacks). For reliable animation, braille fallback frames are
|
|
10
10
|
* used by default; PUA frames are only activated when the user explicitly
|
|
11
|
-
*
|
|
11
|
+
* (used by the capacity icons).
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
function fontPath(): string {
|