@rosetears/aili-pi 0.1.8 → 0.1.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 +7 -7
- package/THIRD_PARTY_NOTICES.md +12 -12
- package/docs/persistent-agents.md +114 -0
- package/extensions/matrix/index.ts +24 -8
- package/extensions/zentui/config.ts +13 -13
- package/extensions/zentui/format.ts +15 -1
- package/extensions/zentui/gradient.ts +22 -13
- package/extensions/zentui/tool-execution.ts +7 -4
- package/manifests/adapter-evidence.json +53 -20
- package/manifests/capabilities.json +3 -3
- package/manifests/live-verification.json +18 -19
- package/manifests/provenance.json +12 -12
- package/manifests/roles.json +270 -57
- package/manifests/sbom.json +1 -128
- package/manifests/skill-compatibility.json +57 -61
- package/manifests/subagent-provenance.json +8 -15
- package/package.json +3 -3
- package/roles/agent-evaluator.md +8 -3
- package/roles/ai-regression-scout.md +8 -3
- package/roles/browser-qa-runner.md +8 -3
- package/roles/code-reviewer.md +8 -3
- package/roles/code-scout.md +8 -3
- package/roles/convergence-reviewer.md +8 -3
- package/roles/doc-researcher.md +8 -3
- package/roles/e2e-artifact-runner.md +8 -3
- package/roles/general.md +49 -0
- package/roles/implementer.md +8 -3
- package/roles/opensource-sanitizer.md +8 -3
- package/roles/plan-auditor.md +8 -3
- package/roles/pr-test-analyzer.md +8 -3
- package/roles/security-auditor.md +8 -3
- package/roles/silent-failure-reviewer.md +8 -3
- package/roles/spec-miner.md +8 -3
- package/roles/test-coverage-reviewer.md +8 -3
- package/roles/test-engineer.md +8 -3
- package/roles/web-performance-auditor.md +8 -3
- package/roles/web-researcher.md +8 -3
- package/scripts/sync-roles.ts +186 -24
- package/src/runtime/doctor.ts +38 -10
- package/src/runtime/global-resources.ts +5 -1
- package/src/runtime/index.ts +2 -2
- package/src/runtime/persistent-agents/hub.ts +429 -0
- package/src/runtime/persistent-agents/model-selection.ts +363 -0
- package/src/runtime/persistent-agents/output-delivery.ts +356 -0
- package/src/runtime/persistent-agents/permission.ts +223 -0
- package/src/runtime/persistent-agents/policy.ts +311 -0
- package/src/runtime/persistent-agents/production.ts +569 -0
- package/src/runtime/persistent-agents/runtime.ts +164 -0
- package/src/runtime/persistent-agents/sandbox.ts +68 -0
- package/src/runtime/persistent-agents/scheduler.ts +190 -0
- package/src/runtime/persistent-agents/session-factory.ts +184 -0
- package/src/runtime/persistent-agents/storage.ts +775 -0
- package/src/runtime/persistent-agents/task-coordinator.ts +460 -0
- package/src/runtime/persistent-agents/task-schema.ts +141 -0
- package/src/runtime/persistent-agents/types.ts +134 -0
- package/src/runtime/persistent-agents/workspace.ts +335 -0
- package/src/runtime/registry.ts +28 -32
- package/src/runtime/roles.ts +211 -18
- package/src/runtime/rose-context.ts +1 -1
- package/templates/APPEND_SYSTEM.md +1 -1
- package/themes/rose-cyberdeck.json +5 -9
- package/upstream/opencode-global-agents.lock.json +1 -1
- package/src/runtime/subagents.ts +0 -249
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ That command creates or updates only the AILI marker block in `~/.pi/agent/APPEN
|
|
|
53
53
|
|
|
54
54
|
The package supplies the dark `rose-cyberdeck` theme plus three additional Pi Extensions: a Rose header, Rose Shimmer + four-row Rose Code Rain working surface, and Zentui footer/editor surface. Select it through Pi's `/settings` theme selector or set `"theme": "rose-cyberdeck"` in `~/.pi/agent/settings.json`. The visual extensions are adapted from `pi-sakura-cyberdeck` at revision `165a1f8011a12a58a6409b56b8a6c0416cd9b589` under MIT; see `THIRD_PARTY_NOTICES.md` and `notices/pi-sakura-cyberdeck-NOTICE.txt`.
|
|
55
55
|
|
|
56
|
-
Rose Code Rain
|
|
56
|
+
Rose Code Rain uses the original sparse, fixed-column waterfall geometry: `density` selects even-cell tracks, at most 96 tracks span ultra-wide terminals, and each track falls vertically with a randomized tail and gap. The default 12 FPS cadence and 8–16 rows/second fall speed sit between the released and dense-preview profiles. `/rose-matrix status`, `/rose-matrix fps <8-18>`, `/rose-matrix density <0.45-0.95>`, and `/rose-matrix appearance <auto|dark|light>` change active preferences. `/sakura-matrix` remains a deprecated compatibility alias. Header, rain, frames, footer, and editor use the Rose six-color system: Blue, Ice, Cyan, Violet, Rose, and Soft Rose.
|
|
57
57
|
|
|
58
58
|
### Migrating from Rem/Sakura names
|
|
59
59
|
|
|
@@ -77,7 +77,7 @@ The `pi-permission-modes@2.2.0` baseline owns mode persistence, prompts, and san
|
|
|
77
77
|
- `pi-web-access@0.13.0` provides its complete upstream web-search, content-fetch, curator, clone/PDF/video, and bundled-skill surface. Its provider fallback, network traffic, config/credential paths, clone cache, temporary curator service, downloads, and optional browser-cookie access are upstream behavior; inspect its tool requests and configuration before use.
|
|
78
78
|
- `pi-quota-status@0.3.0` is enabled by default. It may maintain `~/.pi/agent/pi-quota-status/state.json`; `/quota config` creates its configuration template. Zentui displays exactly one weekly value as `codex <percent> <reset>`, preferring explicit `Wk` data and treating the dependency's current `5h`-labeled primary value only as a compatibility fallback when weekly is absent.
|
|
79
79
|
- `pi-permission-modes@2.2.0` provides the permission UI and sandbox degradation behavior above through AILI's exact-source adaptation. The only semantic source change is line-terminator-safe shared glob matching; `upstream/pi-permission-modes.lock.json` records the baseline and adapted hashes. AILI does not retain `/aili-mode` or `Ctrl+Shift+Alt+A` as competing controls.
|
|
80
|
-
-
|
|
80
|
+
- AILI owns the public `task`/`hub` persistent Agent framework. `task` creates parent-scoped official Pi child sessions using 19 specialized `aili.*` selectors or `general`; top-level work is async by default, supports bounded batch scheduling, and returns stable Agent/job/turn IDs plus `agent://` and `history://` references. `hub` provides list/send/wait/inbox/output/history/jobs/cancel/model operations, park/revive, durable delivery, and owner/descendant scoping. No `subagent` compatibility alias or run/attempt backend selector remains. See [`docs/persistent-agents.md`](docs/persistent-agents.md).
|
|
81
81
|
- `pi-cache-optimizer@2.6.18` provides `/cache-optimizer`, provider cache diagnostics, cache statistics, and prompt-cache optimization. It may maintain `~/.pi/agent/pi-cache-optimizer-stats.json`; `/cache-optimizer fix` is interactive and is the only command that may propose editing `models.json`.
|
|
82
82
|
- `pi-markdown-preview@0.10.1` provides `/preview`, `/preview-browser`, `/preview-pdf`, `/preview-clear-cache`, and the `preview_export` tool. Terminal/browser previews require a Chromium executable; PDF export additionally requires Pandoc and a LaTeX engine.
|
|
83
83
|
- `@narumitw/pi-lsp@0.25.0` provides language-agnostic `lsp_diagnostics`, `lsp_fix`, and `/lsp`. It supports routes for C/C++, Python, CSS/SCSS, JavaScript/TypeScript, Go, Rust, Java, Kotlin, Bash, YAML, Terraform, and other languages. It does not download language servers; install the required commands separately and configure project routes in `.pi/pi-lsp.json` or user routes in `~/.pi/agent/pi-lsp.json`.
|
|
@@ -97,9 +97,9 @@ When unavailable, runtime and doctor output use explicit `SKIP`/`WARN` results a
|
|
|
97
97
|
|
|
98
98
|
## Security boundary
|
|
99
99
|
|
|
100
|
-
AILI
|
|
100
|
+
AILI applies a non-removable in-process child guard before tool approval. It denies credential, authentication, and private-key paths/material; intersects parent-active tools with role/call ceilings; and routes each `ask` decision back to the parent UI. In sandbox-required modes, child Bash reuses the initialized `pi-permission-modes` SandboxManager through a child-cwd-specific Bash definition; if that executor is unavailable or the child is in an incompatible Git worktree, Bash fails closed rather than running unsandboxed. Parent task acceptance is not blanket child authorization. The guard does not make arbitrary trusted extension code safe, and neither AILI nor Pi claims a universal OS sandbox. Inspect exact approval targets and do not put credentials in task text.
|
|
101
101
|
|
|
102
|
-
Use `
|
|
102
|
+
Use `hub jobs`, `hub wait`, `hub output`, and `hub history` to inspect durable asynchronous work. At most 32 top-level turns run concurrently; nested work is synchronous and depth-bounded. Persistent Agents are a benefit-based way to improve execution efficiency and preserve parent context, while the main agent retains decisions, integration, and final verification. Direct parent work remains valid when delegation has no clear net benefit; no Agent call is required to unlock mutation. Provider/model behavior still depends on the configured Pi environment.
|
|
103
103
|
|
|
104
104
|
## Provenance and reproducibility
|
|
105
105
|
|
|
@@ -107,7 +107,7 @@ Use `subagent` lifecycle actions (`status`, `logs`, `wait`, `interrupt`, `mark-b
|
|
|
107
107
|
- `upstream/opencode-global-agents.lock.json` pins the global AGENTS source revision/hash and documents its Pi-native derivation.
|
|
108
108
|
- `upstream/pi-permission-modes.lock.json` pins the exact upstream and adapted permission runtime files and semantic diff.
|
|
109
109
|
- `manifests/skill-compatibility.json` records one compatibility state per skill.
|
|
110
|
-
- `manifests/roles.json` records
|
|
110
|
+
- `manifests/roles.json` records 19 generated specialized profiles plus the AILI-owned `general` profile.
|
|
111
111
|
- `manifests/provenance.json`, `manifests/sbom.json`, and `THIRD_PARTY_NOTICES.md` record adapted/reference sources and the exact npm lock inventory.
|
|
112
112
|
|
|
113
113
|
Verify generated artifacts with:
|
|
@@ -125,8 +125,8 @@ npm run validate:release
|
|
|
125
125
|
- **Doctor is non-pass:** inspect the exact `ERROR`, `WARN`, `SKIP`, or `UNVERIFIED` component. Missing optional packs are not core execution success.
|
|
126
126
|
- **Permission shortcut does nothing:** use `/perm`; terminal multiplexers may consume `Alt+M`.
|
|
127
127
|
- **YOLO still asks for multiline Bash:** confirm the loaded Package contains the adapted permission runtime with `npm run verify:permission-modes`; do not work around it by granting every distinct script for the session.
|
|
128
|
-
- **
|
|
129
|
-
- **
|
|
128
|
+
- **Persistent task says the parent Session is not durable:** start/save a normal Pi session first; Agents require a parent JSONL so their sidecar can be scoped exactly.
|
|
129
|
+
- **Child Bash is denied in a sandbox-required mode:** inspect `/sandbox` for dependency/platform readiness. AILI deliberately denies instead of running unsandboxed when the parent SandboxManager is unavailable or when an isolated Git worktree uses a `.git` file that Bubblewrap cannot bind safely.
|
|
130
130
|
- **Global resources are non-pass:** run `/aili-install-global-resources` only after reviewing the exact `~/.pi/agent/` targets. A malformed marker or an unowned role collision intentionally leaves files unchanged.
|
|
131
131
|
- **Offline use:** the installed Package embeds the pinned skills and does not fetch `aili-workflows` at runtime. Its Pi-managed npm lifecycle synchronizes only pre-existing same-name global skills from that embedded fixed snapshot. First-time Pi/package installation still requires the relevant package sources.
|
|
132
132
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -13,17 +13,6 @@ This distribution is MIT-licensed. The following adapted sources and locked deve
|
|
|
13
13
|
- Reused symbols/patterns: 64 canonical skill bodies and owned assets, 19 child-role prompt bodies
|
|
14
14
|
- Local changes: skills/** is an exact byte-for-byte snapshot with no semantic overlay; role prompts are generated as Pi frontmatter with explicit tool/capability ceilings and structured output; templates/APPEND_SYSTEM.md is a Pi-native governance derivation of the pinned global AGENTS template, with OpenCode-only control planes excluded
|
|
15
15
|
|
|
16
|
-
## @agwab/pi-subagent
|
|
17
|
-
|
|
18
|
-
- Status: dependency
|
|
19
|
-
- Source: https://github.com/AgwaB/pi-subagent.git
|
|
20
|
-
- Revision: daa7b83819116a62008ad17aa65fcd50fefbafd0
|
|
21
|
-
- Version: 0.4.8
|
|
22
|
-
- License: MIT
|
|
23
|
-
- Source files: src/index.ts, src/api.ts, src/runners/headless-model.ts, src/artifacts/result.ts
|
|
24
|
-
- Reused symbols/patterns: subagent tool renderCall, runSubagent API, headless lifecycle, artifact envelope
|
|
25
|
-
- Local changes: AILI registers the full pinned upstream subagent tool schema, prepends a sanitized bounded requested-Agent heading, injects a non-removable credential guard, normalizes ordinary omitted/auto runs to headless for the Pi 0.81.1 compatibility window, and rejects explicit inline before model startup; no upstream source is copied
|
|
26
|
-
|
|
27
16
|
## pi-permission-modes
|
|
28
17
|
|
|
29
18
|
- Status: adapted
|
|
@@ -101,8 +90,19 @@ This distribution is MIT-licensed. The following adapted sources and locked deve
|
|
|
101
90
|
- Reused symbols/patterns: header, matrix animation, Zentui footer, fixed editor compositor
|
|
102
91
|
- Local changes: registered as three additional Pi Package Extensions; Rose header loads a package-owned renamed artwork asset without changing upstream identity; Rose Shimmer, Rose Code Rain, and Zentui use the Rose-owned palette and gradient; overflowing Matrix tracks remain deterministic across the complete terminal width with the 96-track budget, while each rain row receives a structural blank-row repair; relative import specifiers and session lifecycle event are adapted for this package's NodeNext TypeScript contract
|
|
103
92
|
|
|
93
|
+
## Oh My Pi reference
|
|
94
|
+
|
|
95
|
+
- Status: reference-only
|
|
96
|
+
- Source: https://github.com/can1357/oh-my-pi.git
|
|
97
|
+
- Revision: 59619623e1eeb7c290649eeaf3a269284ce8adef
|
|
98
|
+
- Version: 17.1.3
|
|
99
|
+
- License: MIT
|
|
100
|
+
- Source files: none copied
|
|
101
|
+
- Reused symbols/patterns: none
|
|
102
|
+
- Local changes: none
|
|
103
|
+
|
|
104
104
|
## npm dependency inventory
|
|
105
105
|
|
|
106
|
-
The exact
|
|
106
|
+
The exact 419-entry package-lock inventory, versions, integrity values, dependency scope, and declared licenses is recorded in `manifests/sbom.json`.
|
|
107
107
|
|
|
108
108
|
Runtime dependencies are initialized through the single AILI Extension entry. Package-owned third-party adaptations are copied only where their provenance sourceFiles explicitly name repository paths.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Persistent Agents (`task` and `hub`)
|
|
2
|
+
|
|
3
|
+
> **Availability:** The AILI-owned runtime is the public orchestration surface. The package registers `task` and `hub` and does not register a legacy `subagent` alias. Deterministic tests plus authorized real-provider, child-sandbox, and disposable external-workspace lifecycle probes are release-bound evidence.
|
|
4
|
+
|
|
5
|
+
## Agent selectors
|
|
6
|
+
|
|
7
|
+
The canonical catalog contains exactly 20 selectors:
|
|
8
|
+
|
|
9
|
+
- `general` (the default when `agent` is omitted)
|
|
10
|
+
- `aili.agent-evaluator`
|
|
11
|
+
- `aili.ai-regression-scout`
|
|
12
|
+
- `aili.browser-qa-runner`
|
|
13
|
+
- `aili.code-reviewer`
|
|
14
|
+
- `aili.code-scout`
|
|
15
|
+
- `aili.convergence-reviewer`
|
|
16
|
+
- `aili.doc-researcher`
|
|
17
|
+
- `aili.e2e-artifact-runner`
|
|
18
|
+
- `aili.implementer`
|
|
19
|
+
- `aili.opensource-sanitizer`
|
|
20
|
+
- `aili.plan-auditor`
|
|
21
|
+
- `aili.pr-test-analyzer`
|
|
22
|
+
- `aili.security-auditor`
|
|
23
|
+
- `aili.silent-failure-reviewer`
|
|
24
|
+
- `aili.spec-miner`
|
|
25
|
+
- `aili.test-coverage-reviewer`
|
|
26
|
+
- `aili.test-engineer`
|
|
27
|
+
- `aili.web-performance-auditor`
|
|
28
|
+
- `aili.web-researcher`
|
|
29
|
+
|
|
30
|
+
`aili.general`, `task` as a selector, and unknown selectors are invalid. The 19 specialized profiles keep their own complete role prompt and cannot spawn children. `general` may synchronously spawn an allowed non-self specialized Agent below the configured depth ceiling.
|
|
31
|
+
|
|
32
|
+
## Creating Agents with `task`
|
|
33
|
+
|
|
34
|
+
A flat request creates one new stable Agent:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"task": "Inspect the parser and report evidence",
|
|
39
|
+
"agent": "aili.code-scout",
|
|
40
|
+
"name": "ParserScout",
|
|
41
|
+
"async": false,
|
|
42
|
+
"tools": ["read", "grep"],
|
|
43
|
+
"workspace": "shared",
|
|
44
|
+
"writeScope": { "paths": [], "resources": [] }
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
A batch validates every item before creating any Agent:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"context": "Use the accepted plan at plan/accepted.md",
|
|
53
|
+
"tasks": [
|
|
54
|
+
{ "task": "Inspect storage", "agent": "aili.code-scout" },
|
|
55
|
+
{ "task": "Implement the accepted fix", "agent": "aili.implementer", "workspace": "auto", "writeScope": { "paths": ["src/storage"], "resources": [] } }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Per-item fields are `task`, `context`, `agent`, `name`, `model`, `async`, `tools`, `workspace`, `writeScope`, and `cwd`. Unknown fields fail validation. `blocking` is profile-only internal metadata, not a `task` field; callers must use `async:false` to wait synchronously.
|
|
61
|
+
|
|
62
|
+
Every item creates a new Agent. Reusing `name: "Scout"` allocates `Scout`, `Scout-2`, and so on; it never resumes the first Agent. Follow-up work uses `hub send` with the allocated Agent ID. Nested IDs are parent-prefixed, such as `general.code-scout`.
|
|
63
|
+
|
|
64
|
+
Top-level non-blocking roles default to async. `async:false`, an internally blocking role profile, and all child-to-grandchild calls are synchronous. One parent allows at most 32 active turns; excess jobs remain in durable FIFO order. AILI sets no Agent-turn wall-clock or assistant-request budget (`0`/unlimited), but provider watchdogs, tool timeouts, permissions, the 32-turn semaphore, process shutdown, and manual cancellation still apply. Background work does not survive the Pi process.
|
|
65
|
+
|
|
66
|
+
## Managing Agents with `hub`
|
|
67
|
+
|
|
68
|
+
`hub` actions are:
|
|
69
|
+
|
|
70
|
+
- `list` — active Agents (and optionally released disk-backed identities)
|
|
71
|
+
- `send` — running safe-boundary steer, idle new turn, or parked revive/new turn
|
|
72
|
+
- `wait` — bounded wait over owned job/message IDs
|
|
73
|
+
- `inbox` — peek or drain failed-live-handoff mail
|
|
74
|
+
- `output` / `history` — bounded disk reads
|
|
75
|
+
- `jobs` — owned job state
|
|
76
|
+
- `cancel` — hard-cancel a job or release an idle/parked identity without deleting history
|
|
77
|
+
- `model` — query or request model override operations
|
|
78
|
+
|
|
79
|
+
Only failed live handoff enters the durable mailbox. Each Agent keeps at most 100 messages; the 101st is rejected while the existing 100 remain. Successful messages have durable receipts for de-duplication.
|
|
80
|
+
|
|
81
|
+
Running, idle, parked, and aborted Agents never run two concurrent turns under one identity. An aborted Agent cannot revive. Process loss records a running turn as `interrupted`, a queued job as `unexecuted`, and never automatically replays either.
|
|
82
|
+
|
|
83
|
+
## Output, history, and retention
|
|
84
|
+
|
|
85
|
+
Complete raw output is stored at the parent-owned `<agent-id>.md`; the official Pi child conversation remains an independent Session JSONL. Tool results return at most 500,000 bytes and 5,000 lines, while parent completion previews are capped at 5,000 characters with explicit truncation metadata.
|
|
86
|
+
|
|
87
|
+
Use `agent://<agent-id>` and `history://<agent-id>` as stable references. `hub output/history` resolves them with `offset` and `limit`, including after an Agent is released.
|
|
88
|
+
|
|
89
|
+
Child history cannot be deleted independently. It follows the parent session. Forks start with an empty Agent registry and never copy/control old child artifacts. Confirmed AILI parent deletion can cascade its owned sidecar; official Pi 0.81.1 built-in Ctrl+D/archive has no sidecar hook, so doctor keeps that host gap visible and orphaned sidecars are preserved for reconciliation.
|
|
90
|
+
|
|
91
|
+
## Models
|
|
92
|
+
|
|
93
|
+
Each turn resolves in this order:
|
|
94
|
+
|
|
95
|
+
1. one-shot `task.model`
|
|
96
|
+
2. stable Agent instance override
|
|
97
|
+
3. trusted project role override
|
|
98
|
+
4. user-global role override
|
|
99
|
+
5. profile frontmatter model
|
|
100
|
+
6. official parent fallback
|
|
101
|
+
|
|
102
|
+
An explicit unknown, unavailable, unauthenticated, or incompatible model fails at its source layer and does not fall through. One-shot values never change configuration. Direct users can run `/aili-agent-model <global|project|instance> <selector|agent-id> <provider/model|clear> [thinking]`; model-facing persistent requests through `hub model` require a fresh interactive confirmation every time. Project model configuration is ignored and cannot be written before project trust is active.
|
|
103
|
+
|
|
104
|
+
## Workspaces and permissions
|
|
105
|
+
|
|
106
|
+
`workspace:auto` keeps disjoint known scopes shared and isolates known path overlap. Shared resources such as ports/databases cannot be isolated by a Git worktree and therefore conflict visibly. An undeclared scope defaults to shared with a best-effort diagnostic; observable second conflicting writes are blocked with isolated-retry guidance.
|
|
107
|
+
|
|
108
|
+
Isolation projects the current dirty tracked/untracked baseline into a disposable worktree, returns child-only patch/branch evidence, never auto-merges, and checks that the main workspace stayed unchanged. After cleanup, history/output remain readable but that Agent cannot revive.
|
|
109
|
+
|
|
110
|
+
Effective tools are always an intersection of parent-active tools, child-loadable definitions, role/capability ceilings, hard guards, and per-call narrowing. Child `task`/`hub` definitions are AILI-owned bridges, never reused parent coordinator definitions. In sandbox-required permission modes, child Bash reuses the parent-initialized `pi-permission-modes` SandboxManager with a child-cwd-specific filesystem profile; missing/degraded sandbox state and incompatible Git-worktree metadata deny Bash instead of falling back unsandboxed. Credential/auth/private-key material is denied before approval and excluded from messages/output/artifacts. Background asks suspend only that job and return to the parent UI; no UI, rejection, cancellation, shutdown, or bridge loss denies and settles the request.
|
|
111
|
+
|
|
112
|
+
## Legacy data
|
|
113
|
+
|
|
114
|
+
Legacy `.pi/agent/runs/`, existing Pi sessions, user configuration, and unrelated Agent sidecars are not migrated, reinterpreted, or deleted by the replacement runtime. Rollback preserves both legacy runs and new sidecars.
|
|
@@ -22,11 +22,12 @@ const SHIMMER_STEP_MS = 120;
|
|
|
22
22
|
const TOOL_GRADIENT: readonly RGB[] = [[188, 167, 255], [125, 228, 255]];
|
|
23
23
|
|
|
24
24
|
export const ROSE_MATRIX_GLYPHS = [..."0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモラリルレロワン"];
|
|
25
|
+
/** The six user-selected rain colors, assigned by the exact weights below. */
|
|
25
26
|
export const ROSE_RAIN_PALETTE: readonly RGB[] = [
|
|
26
|
-
[136, 184, 255], [
|
|
27
|
-
[
|
|
28
|
-
[214, 244, 255], [136, 184, 255], [199, 91, 122], [232, 167, 184],
|
|
27
|
+
[136, 184, 255], [214, 244, 255], [125, 228, 255],
|
|
28
|
+
[188, 167, 255], [199, 91, 122], [232, 167, 184],
|
|
29
29
|
];
|
|
30
|
+
export const ROSE_RAIN_WEIGHTS = { blue: 50, ice: 20, cyan: 15, violet: 8, rose: 4, roseSoft: 3 } as const;
|
|
30
31
|
export const ROSE_SHIMMER_INDICATOR = ["·", "✢", "✳", "✶", "✻", "✽", "✻", "✶", "✳", "✢"] as const;
|
|
31
32
|
|
|
32
33
|
type RGB = readonly [number, number, number];
|
|
@@ -45,6 +46,7 @@ export interface MatrixConfig {
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export interface Drop {
|
|
49
|
+
/** Fixed terminal-cell column; vertical motion never changes this value. */
|
|
48
50
|
x: number;
|
|
49
51
|
offset: number;
|
|
50
52
|
speed: number;
|
|
@@ -59,7 +61,7 @@ type ConfigLoadResult = { config: MatrixConfig; migrated: boolean; warning?: str
|
|
|
59
61
|
const DEFAULT_CONFIG: MatrixConfig = {
|
|
60
62
|
version: 2,
|
|
61
63
|
enabled: true,
|
|
62
|
-
fps:
|
|
64
|
+
fps: 12,
|
|
63
65
|
density: 0.65,
|
|
64
66
|
height: 4,
|
|
65
67
|
appearance: "auto",
|
|
@@ -204,6 +206,19 @@ function selectBoundedColumns(columns: readonly number[]): number[] {
|
|
|
204
206
|
return Array.from({ length: MAX_DROPS }, (_, index) => columns[Math.round((index * lastIndex) / (MAX_DROPS - 1))] ?? 0);
|
|
205
207
|
}
|
|
206
208
|
|
|
209
|
+
/** Exact 50/20/15/8/4/3 distribution over each deterministic 100-track cycle. */
|
|
210
|
+
export function roseRainColor(index: number): RGB {
|
|
211
|
+
// A coprime stride distributes all weights through the 96-track ceiling,
|
|
212
|
+
// instead of leaving the final Rose/Soft Rose buckets unreachable.
|
|
213
|
+
const bucket = (((index * 37) % 100) + 100) % 100;
|
|
214
|
+
if (bucket < 50) return ROSE_RAIN_PALETTE[0]!;
|
|
215
|
+
if (bucket < 70) return ROSE_RAIN_PALETTE[1]!;
|
|
216
|
+
if (bucket < 85) return ROSE_RAIN_PALETTE[2]!;
|
|
217
|
+
if (bucket < 93) return ROSE_RAIN_PALETTE[3]!;
|
|
218
|
+
if (bucket < 97) return ROSE_RAIN_PALETTE[4]!;
|
|
219
|
+
return ROSE_RAIN_PALETTE[5]!;
|
|
220
|
+
}
|
|
221
|
+
|
|
207
222
|
export function createDrops(width: number, density: number, height = 4): Drop[] {
|
|
208
223
|
const random = mulberry32((width * 2654435761) ^ 0x53414b55);
|
|
209
224
|
const columns = Array.from({ length: Math.ceil(width / 2) }, (_, index) => index * 2);
|
|
@@ -216,11 +231,12 @@ export function createDrops(width: number, density: number, height = 4): Drop[]
|
|
|
216
231
|
return {
|
|
217
232
|
x,
|
|
218
233
|
offset: random() * cycle,
|
|
219
|
-
|
|
234
|
+
// Between the released waterfall (5.5–13) and dense preview (18).
|
|
235
|
+
speed: 8 + random() * 8,
|
|
220
236
|
length,
|
|
221
237
|
gap,
|
|
222
238
|
seed: Math.floor(random() * 0x7fffffff) ^ (index * 7919),
|
|
223
|
-
color:
|
|
239
|
+
color: roseRainColor(index),
|
|
224
240
|
};
|
|
225
241
|
});
|
|
226
242
|
}
|
|
@@ -229,8 +245,8 @@ function appearanceColor(color: RGB, appearance: ResolvedAppearance): RGB {
|
|
|
229
245
|
if (appearance === "dark") return color;
|
|
230
246
|
if (color[0] === 199 && color[1] === 91) return LIGHT.indicator;
|
|
231
247
|
if (color[0] === 232 && color[1] === 167) return [168, 69, 95];
|
|
232
|
-
if (color[0] ===
|
|
233
|
-
if (color[1] === 228) return [78, 120, 129];
|
|
248
|
+
if (color[0] === 188 && color[1] === 167) return [119, 106, 151];
|
|
249
|
+
if (color[0] === 214 || color[1] === 228) return [78, 120, 129];
|
|
234
250
|
return LIGHT.base;
|
|
235
251
|
}
|
|
236
252
|
|
|
@@ -235,27 +235,27 @@ export const defaultConfig: PolishedTuiConfig = {
|
|
|
235
235
|
cwd: "bold #88B8FF",
|
|
236
236
|
gitBranch: "bold #BCA7FF",
|
|
237
237
|
gitStatus: "bold #D6F4FF",
|
|
238
|
-
contextNormal: "#
|
|
239
|
-
contextWarning: "bold #
|
|
240
|
-
contextError: "bold #
|
|
238
|
+
contextNormal: "#7DE4FF",
|
|
239
|
+
contextWarning: "bold #BCA7FF",
|
|
240
|
+
contextError: "bold #C75B7A",
|
|
241
241
|
tokens: "#9DA9C8",
|
|
242
|
-
cost: "bold #
|
|
242
|
+
cost: "bold #7DE4FF",
|
|
243
243
|
separator: "#64708F",
|
|
244
244
|
runtimePrefix: "#7DE4FF",
|
|
245
245
|
extensionStatus: "#BCA7FF",
|
|
246
|
-
sessionDuration: "#
|
|
246
|
+
sessionDuration: "#BCA7FF",
|
|
247
247
|
packageVersion: "#D6F4FF",
|
|
248
|
-
gitCommit: "#
|
|
249
|
-
gitMetricsAdded: "#
|
|
250
|
-
gitMetricsDeleted: "#
|
|
251
|
-
username: "#
|
|
252
|
-
time: "#
|
|
253
|
-
os: "#
|
|
248
|
+
gitCommit: "#7DE4FF",
|
|
249
|
+
gitMetricsAdded: "#7DE4FF",
|
|
250
|
+
gitMetricsDeleted: "#C75B7A",
|
|
251
|
+
username: "#BCA7FF",
|
|
252
|
+
time: "#BCA7FF",
|
|
253
|
+
os: "#D6F4FF",
|
|
254
254
|
editorAccent: "bold #88B8FF",
|
|
255
255
|
editorPrompt: "bold #88B8FF",
|
|
256
256
|
editorBorder: "rose-cyberdeck-gradient",
|
|
257
257
|
editorModel: "bold #88B8FF",
|
|
258
|
-
editorProvider: "#
|
|
258
|
+
editorProvider: "#D6F4FF",
|
|
259
259
|
editorThinking: "#BCA7FF",
|
|
260
260
|
editorThinkingMinimal: "#64708F",
|
|
261
261
|
editorThinkingLow: "#7DE4FF",
|
|
@@ -264,7 +264,7 @@ export const defaultConfig: PolishedTuiConfig = {
|
|
|
264
264
|
editorThinkingXhigh: "bold #BCA7FF",
|
|
265
265
|
},
|
|
266
266
|
colorSources: {
|
|
267
|
-
starship: "
|
|
267
|
+
starship: "theme",
|
|
268
268
|
editor: "terminal",
|
|
269
269
|
userMessages: "theme",
|
|
270
270
|
},
|
|
@@ -288,6 +288,20 @@ export function buildContextLabel(ctx: ExtensionContext): string {
|
|
|
288
288
|
return formatContextPercentLabel(usage?.percent, contextWindow);
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Normalize inherited Starship runtime hints into Rose-owned semantic colors.
|
|
293
|
+
* The source strings remain detection metadata; package rendering never emits
|
|
294
|
+
* their traffic-light or indexed terminal colors.
|
|
295
|
+
*/
|
|
296
|
+
export function roseRuntimeStyle(style: string): ColorSpec {
|
|
297
|
+
const normalized = style.toLowerCase();
|
|
298
|
+
if (/(?:red|202|208|orange)/.test(normalized)) return "rose";
|
|
299
|
+
if (/(?:yellow|purple|105|147)/.test(normalized)) return "violet";
|
|
300
|
+
if (/(?:white|149)/.test(normalized)) return "ice";
|
|
301
|
+
if (/(?:green|cyan|blue|0093a7)/.test(normalized)) return "cyan";
|
|
302
|
+
return "blue";
|
|
303
|
+
}
|
|
304
|
+
|
|
291
305
|
export function formatRuntimeSegment(
|
|
292
306
|
theme: Pick<Theme, "fg">,
|
|
293
307
|
runtime: RuntimeInfo | undefined,
|
|
@@ -298,7 +312,7 @@ export function formatRuntimeSegment(
|
|
|
298
312
|
if (!runtime) return "";
|
|
299
313
|
const symbol = resolveRuntimeSymbol(runtime.name, runtime.symbol, mode);
|
|
300
314
|
const label = runtime.version ? `${symbol} ${runtime.version}` : symbol;
|
|
301
|
-
return `${renderStyleForSource(theme, colorSource, prefixStyle, "via")} ${renderStyleForSource(theme, colorSource, runtime.style, label)}`;
|
|
315
|
+
return `${renderStyleForSource(theme, colorSource, prefixStyle, "via")} ${renderStyleForSource(theme, colorSource, roseRuntimeStyle(runtime.style), label)}`;
|
|
302
316
|
}
|
|
303
317
|
|
|
304
318
|
/**
|
|
@@ -11,6 +11,10 @@ export const ROSE_GRADIENT_STOPS: readonly RGB[] = [
|
|
|
11
11
|
[125, 228, 255], // cyan #7DE4FF
|
|
12
12
|
[214, 244, 255], // ice #D6F4FF
|
|
13
13
|
];
|
|
14
|
+
/** Completed tool frames use a cool, restrained completion gradient. */
|
|
15
|
+
export const ROSE_TOOL_COMPLETE_STOPS: readonly RGB[] = [
|
|
16
|
+
[136, 184, 255], [125, 228, 255], [214, 244, 255],
|
|
17
|
+
];
|
|
14
18
|
|
|
15
19
|
const RESET = "\x1b[0m";
|
|
16
20
|
const GRADIENT_CACHE_LIMIT = 128;
|
|
@@ -25,32 +29,37 @@ function mix(from: RGB, to: RGB, amount: number): RGB {
|
|
|
25
29
|
];
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
function sampleGradient(position: number): RGB {
|
|
29
|
-
const normalized = Math.max(0, Math.min(1, position));
|
|
30
|
-
const scaled = normalized * (ROSE_GRADIENT_STOPS.length - 1);
|
|
31
|
-
const index = Math.min(ROSE_GRADIENT_STOPS.length - 2, Math.floor(scaled));
|
|
32
|
-
const from = ROSE_GRADIENT_STOPS[index] ?? ROSE_GRADIENT_STOPS[0]!;
|
|
33
|
-
const to = ROSE_GRADIENT_STOPS[index + 1] ?? from;
|
|
34
|
-
return mix(from, to, scaled - index);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
32
|
function foreground(color: RGB, text: string): string {
|
|
38
33
|
return `\x1b[38;2;${color[0]};${color[1]};${color[2]}m${text}`;
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
/** Render the stable Rose-to-ice gradient for Zentui chrome and markers. */
|
|
42
|
-
|
|
43
|
-
const
|
|
37
|
+
function renderGradient(text: string, stops: readonly RGB[]): string {
|
|
38
|
+
const cacheKey = `${stops.flat().join(",")}:${text}`;
|
|
39
|
+
const cached = gradientCache.get(cacheKey);
|
|
44
40
|
if (cached !== undefined) return cached;
|
|
45
41
|
const chars = [...text];
|
|
46
42
|
if (chars.length === 0) return text;
|
|
47
43
|
const span = Math.max(1, chars.length - 1);
|
|
48
|
-
const rendered = `${chars.map((char, index) =>
|
|
44
|
+
const rendered = `${chars.map((char, index) => {
|
|
45
|
+
const position = Math.max(0, Math.min(1, index / span));
|
|
46
|
+
const scaled = position * (stops.length - 1);
|
|
47
|
+
const stop = Math.min(stops.length - 2, Math.floor(scaled));
|
|
48
|
+
return foreground(mix(stops[stop] ?? stops[0]!, stops[stop + 1] ?? stops[stop] ?? stops[0]!, scaled - stop), char);
|
|
49
|
+
}).join("")}${RESET}`;
|
|
49
50
|
if (gradientCache.size >= GRADIENT_CACHE_LIMIT) gradientCache.delete(gradientCache.keys().next().value ?? "");
|
|
50
|
-
gradientCache.set(
|
|
51
|
+
gradientCache.set(cacheKey, rendered);
|
|
51
52
|
return rendered;
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
export function renderRoseGradient(text: string): string {
|
|
56
|
+
return renderGradient(text, ROSE_GRADIENT_STOPS);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function renderRoseToolCompleteGradient(text: string): string {
|
|
60
|
+
return renderGradient(text, ROSE_TOOL_COMPLETE_STOPS);
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
/** Add symmetric colored side rails while preserving the terminal width contract. */
|
|
55
64
|
export function renderBoxedLine(line: string, width: number, leftRail: string, rightRail: string): string {
|
|
56
65
|
if (width <= 0) return "";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Theme, ToolExecutionComponent } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
-
import { renderBoxedLine, renderRoseGradient } from "./gradient.js";
|
|
3
|
+
import { renderBoxedLine, renderRoseGradient, renderRoseToolCompleteGradient } from "./gradient.js";
|
|
4
4
|
import { installPrototypePatch } from "./prototype-patch-registry.js";
|
|
5
5
|
|
|
6
6
|
const SETTLED_CACHE_MAX_LINES = 80;
|
|
@@ -141,7 +141,10 @@ export function installToolExecutionStyle(getTheme: () => Theme | undefined): Cl
|
|
|
141
141
|
if (blank !== undefined) prefix.push(blank);
|
|
142
142
|
}
|
|
143
143
|
const label = fitBorderLabel(statusLabel(runtime), width);
|
|
144
|
-
const
|
|
144
|
+
const completeGradient = !pending && !runtime.result?.isError
|
|
145
|
+
? renderRoseToolCompleteGradient
|
|
146
|
+
: renderRoseGradient;
|
|
147
|
+
const top = completeGradient(label);
|
|
145
148
|
// Keep only the status rail slightly heavier. State is expressed in the
|
|
146
149
|
// Rose palette rather than traffic-light red/green: violet while running,
|
|
147
150
|
// ice blue when complete, and Rose when failed.
|
|
@@ -150,8 +153,8 @@ export function installToolExecutionStyle(getTheme: () => Theme | undefined): Cl
|
|
|
150
153
|
: runtime.result?.isError
|
|
151
154
|
? theme.fg("accent", "┃ ")
|
|
152
155
|
: theme.fg("syntaxFunction", "┃ ");
|
|
153
|
-
const rightRail =
|
|
154
|
-
const bottom =
|
|
156
|
+
const rightRail = completeGradient(" │");
|
|
157
|
+
const bottom = completeGradient(bottomBorder(width));
|
|
155
158
|
|
|
156
159
|
const boxed = [
|
|
157
160
|
...prefix,
|
|
@@ -8,38 +8,71 @@
|
|
|
8
8
|
"sourceRevision": "7eb35f357ad489f5841ee10dac1e44549c1bdb76",
|
|
9
9
|
"verification": [
|
|
10
10
|
"vitest run tests/integration/extension-load.test.ts",
|
|
11
|
-
"vitest run tests/
|
|
11
|
+
"vitest run tests/integration/persistent-agent-host-seams.test.ts"
|
|
12
12
|
],
|
|
13
13
|
"artifacts": [
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
{
|
|
15
|
+
"path": "package-lock.json",
|
|
16
|
+
"sha256": "006a165d0b94cd75a0a8cfbcd54f588b5d87441699316fb128512748b5bfd857"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "tests/integration/extension-load.test.ts",
|
|
20
|
+
"sha256": "f2fdceb965f55bc481acc6457eee5cac9499dac08e8c3d17ca60efd07f13e96c"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"path": "tests/integration/persistent-agent-host-seams.test.ts",
|
|
24
|
+
"sha256": "562ca1ce07e9d57861b48c210a8d10b1d8cbe3ffad7db6ac20ecb178f3beda36"
|
|
25
|
+
}
|
|
17
26
|
]
|
|
18
27
|
},
|
|
19
28
|
{
|
|
20
29
|
"capability": "subagent.dispatch",
|
|
21
30
|
"status": "adapted",
|
|
22
|
-
"owner": "src/runtime/
|
|
31
|
+
"owner": "src/runtime/persistent-agents/production.ts",
|
|
23
32
|
"sourceRevision": "7eb35f357ad489f5841ee10dac1e44549c1bdb76",
|
|
24
33
|
"verification": [
|
|
25
34
|
"npm run verify:roles",
|
|
26
|
-
"vitest run tests/unit/
|
|
27
|
-
"vitest run tests/integration/
|
|
28
|
-
"
|
|
29
|
-
"AILI_LIVE_CREDENTIAL_GUARD_PROBE=1 npx vitest run tests/integration/live-subagent.test.ts"
|
|
35
|
+
"vitest run tests/unit/persistent-agent-task.test.ts tests/unit/persistent-agent-hub.test.ts tests/unit/persistent-agent-policy.test.ts",
|
|
36
|
+
"vitest run tests/integration/persistent-agent-runtime.test.ts tests/integration/package-runtime.test.ts",
|
|
37
|
+
"npm run test:doctor"
|
|
30
38
|
],
|
|
31
39
|
"artifacts": [
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
{
|
|
41
|
+
"path": "src/runtime/persistent-agents/production.ts",
|
|
42
|
+
"sha256": "312ac2a3cd32b298550caedc09d74d97d279ef9380a7e03ca32a424b70121ee1"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "src/runtime/persistent-agents/runtime.ts",
|
|
46
|
+
"sha256": "fbf90c6c4ba573b64bca98e775aeb036ba8f28788e3919d0beebe52c36ef58de"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"path": "src/runtime/persistent-agents/storage.ts",
|
|
50
|
+
"sha256": "cb33384792ca375fab62bf8529407c4e16e0e952fe7a28d0f1022f26ab7589d7"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"path": "src/runtime/persistent-agents/permission.ts",
|
|
54
|
+
"sha256": "48b30508491bca7fcd04d82b30d9dde1423499c2f02c014074c3f030c7ebd8ba"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"path": "tests/unit/persistent-agent-task.test.ts",
|
|
58
|
+
"sha256": "2562ff539e9f1cf756c2097beb9de09b0c28f33088c0f18fdbb91c978a898c3f"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"path": "tests/unit/persistent-agent-hub.test.ts",
|
|
62
|
+
"sha256": "8d90b71b4db40822b566d1807212ea20ed30d0a85706ee058d869736ccd0d306"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"path": "tests/unit/persistent-agent-policy.test.ts",
|
|
66
|
+
"sha256": "1a397beeef79d4553461314020fc91655ff1bbc88d1f23b76c1391ab1e78b8f8"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"path": "tests/integration/persistent-agent-runtime.test.ts",
|
|
70
|
+
"sha256": "50c930a4b72e5697f0931f0fcd9ff1a17a22b8dcd8f7e3ad51c255b6e454a2f9"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"path": "tests/integration/package-runtime.test.ts",
|
|
74
|
+
"sha256": "bc3659d12c416343b1c3bafffd3365a77fb342e6b5ac5e4d3abd8aaf9d608eea"
|
|
75
|
+
}
|
|
43
76
|
]
|
|
44
77
|
}
|
|
45
78
|
]
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"pi-web-access",
|
|
7
7
|
"pi-quota-status",
|
|
8
8
|
"pi-permission-modes",
|
|
9
|
-
"
|
|
9
|
+
"aili-persistent-agents",
|
|
10
10
|
"optional-pack:web-research",
|
|
11
11
|
"optional-pack:browser-qa",
|
|
12
12
|
"optional-pack:artifact-runtime"
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"id": "subagent.dispatch",
|
|
37
|
-
"provider": "
|
|
38
|
-
"adapterOwner": "
|
|
37
|
+
"provider": "aili-persistent-agents",
|
|
38
|
+
"adapterOwner": "src/runtime/persistent-agents/production.ts (AILI-owned task/hub with parent-scoped Pi sessions)",
|
|
39
39
|
"platforms": ["linux"],
|
|
40
40
|
"class": "required",
|
|
41
41
|
"risk": { "secret": "possible", "network": "provider-dependent", "sideEffect": "delegated" },
|