pi-weave 0.1.4 → 0.1.6
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 +31 -47
- package/package.json +3 -1
- package/skills/weave-explore/SKILL.md +18 -30
- package/skills/weave-notepad/SKILL.md +39 -36
- package/src/pi/index.ts +56 -13
- package/src/pi/viewer/tui/run.ts +8 -1
package/README.md
CHANGED
|
@@ -13,21 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
**An agent-native knowledge workspace for your life and your code.**
|
|
15
15
|
|
|
16
|
-
pi-weave is a [pi](https://github.com/earendil-works/pi)
|
|
17
|
-
extension with two faces that are secretly one:
|
|
16
|
+
pi-weave is a [pi](https://github.com/earendil-works/pi) extension with two faces that are secretly one:
|
|
18
17
|
|
|
19
|
-
1. **A smart notepad with AI skills.** A persistent vault of knowledge —
|
|
20
|
-
|
|
21
|
-
front matter under `~/.okf/notes/`. Your agent reads and writes it *with*
|
|
22
|
-
you; everything is editable by hand in any editor.
|
|
18
|
+
1. **A smart notepad with AI skills.** A persistent vault of knowledge — decisions, ideas, people, meetings — stored as plain Markdown notes
|
|
19
|
+
with front matter under `~/.okf/notes/`. Your agent reads and writes it *with* you; everything is editable by hand in any editor.
|
|
23
20
|
|
|
24
|
-
2. **A repository exploration engine.** A derived, git-aware knowledge index
|
|
25
|
-
|
|
26
|
-
packages, modules, entry points, and staleness state. Rebuildable,
|
|
27
|
-
disposable, never the source of truth.
|
|
21
|
+
2. **A repository exploration engine.** A derived, git-aware knowledge index of the repo you're in, living at `<repo>/.okf/` — structure,
|
|
22
|
+
languages, packages, modules, entry points, and staleness state. Rebuildable, disposable, never the source of truth.
|
|
28
23
|
|
|
29
|
-
And one rule across both: **everything is equally usable by humans and
|
|
30
|
-
agents.** No opaque databases. No lock-in formats.
|
|
24
|
+
And one rule across both: **everything is equally usable by humans and agents.** No opaque databases. No lock-in formats.
|
|
31
25
|
|
|
32
26
|
```
|
|
33
27
|
🧵 vault:12 · my-project:ok ← pi's status line when weave is active
|
|
@@ -43,47 +37,40 @@ pi install /path/to/pi-weave # local path
|
|
|
43
37
|
|
|
44
38
|
Or for development: `pi -e ./src/pi/index.ts`.
|
|
45
39
|
|
|
46
|
-
The package is [published on npm](https://www.npmjs.com/package/pi-weave);
|
|
47
|
-
|
|
48
|
-
([Publish workflow](.github/workflows/publish.yml)).
|
|
40
|
+
The package is [published on npm](https://www.npmjs.com/package/pi-weave); releases are cut from `main` and auto-published with provenance
|
|
41
|
+
attestation ([Publish workflow](.github/workflows/publish.yml)).
|
|
49
42
|
|
|
50
43
|
## What you get
|
|
51
44
|
|
|
52
45
|
| Surface | Name | Purpose |
|
|
53
46
|
|---|---|---|
|
|
54
|
-
| Tool | `weave_note` | list / get / add / append / search vault notes |
|
|
47
|
+
| Tool | `weave_note` | list / get / add / append / finalize / search vault notes |
|
|
55
48
|
| Tool | `weave_repo` | status / scan / overview of the `.okf` repo index |
|
|
56
49
|
| Command | `/weave` | workspace dashboard (vault + repository) |
|
|
57
50
|
| Command | `/weave-scan` | build/refresh the repository index (light) |
|
|
58
51
|
| Command | `/weave-scan deep` | light index + model-summarized sidecars (opt-in, incremental) |
|
|
52
|
+
| Command | `/weave-scan-cancel` | stop an in-flight `/weave-scan deep` run |
|
|
59
53
|
| Command | `/weave-view` | open the local graph viewer in your browser |
|
|
60
54
|
| Command | `/weave-view tui` | explore the same graph in-terminal (keyboard) |
|
|
61
55
|
| Skill | `weave-notepad` | how the agent should take good notes |
|
|
62
56
|
| Skill | `weave-explore` | how the agent should explore repositories |
|
|
63
57
|
|
|
64
|
-
**`/weave-view`** starts a loopback-only server (`127.0.0.1`, random port)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
On session start, pi-weave detects the repository you're in, checks whether
|
|
81
|
-
`.okf` exists and is fresh, and says so in the status line.
|
|
82
|
-
|
|
83
|
-
**`/weave-scan deep`** is the opt-in, incremental deep pass: it refreshes the
|
|
84
|
-
light index and then writes a short model summary per file to
|
|
85
|
-
`.okf/repository/summaries/`, skipping files whose content hash is unchanged
|
|
86
|
-
since their last summary. It costs tokens, so it never runs implicitly.
|
|
58
|
+
**`/weave-view`** starts a loopback-only server (`127.0.0.1`, random port) and opens an interactive graph of your knowledge space: vault
|
|
59
|
+
notes with trust provenance (solid = human, dashed = agent, dimmed = generated), wiki-link edges between notes, and the repository's
|
|
60
|
+
structure anchored to git state. It reads disk live on every refresh — never a stale cache. Zoom/scroll, drag to pan, click nodes to expand;
|
|
61
|
+
notes open in a rendered markdown side panel.
|
|
62
|
+
|
|
63
|
+
**`/weave-view tui`** explores the same knowledge graph in the terminal: an expandable containment tree (Explore), a 1-hop neighborhood
|
|
64
|
+
(Focus), a selected-node detail view with note/`.okf` bodies, and a staleness + link health surface — all keyboard-driven and read-only.
|
|
65
|
+
Same data as the browser viewer (the `GraphModel` assembled from vault + repo index); a pure, harness-free view-model
|
|
66
|
+
(`src/pi/viewer/tui/model.ts`) backs the `WeaveExplorer` component. See `docs/weave-view-tui-design.md`.
|
|
67
|
+
|
|
68
|
+
On session start, pi-weave detects the repository you're in, checks whether `.okf` exists and is fresh, and says so in the status footer — a
|
|
69
|
+
filled `●` marks weave as active (a deep scan spins it while running).
|
|
70
|
+
|
|
71
|
+
**`/weave-scan deep`** is the opt-in, incremental deep pass: it refreshes the light index and then writes a short model summary per file to
|
|
72
|
+
`.okf/repository/summaries/`, skipping files whose content hash is unchanged since their last summary. It costs tokens, so it never runs
|
|
73
|
+
implicitly — and it runs in the background, so `/weave-scan-cancel` can stop it mid-flight.
|
|
87
74
|
|
|
88
75
|
## The formats (why everything is portable)
|
|
89
76
|
|
|
@@ -112,15 +99,13 @@ Repository index (`<repo>/.okf/`):
|
|
|
112
99
|
└── structure.json # languages, packages, modules, entry points
|
|
113
100
|
```
|
|
114
101
|
|
|
115
|
-
The `.okf` index is **derived**: delete it, rescan, lose nothing. By default
|
|
116
|
-
it
|
|
117
|
-
sharing is a deliberate opt-in.
|
|
102
|
+
The `.okf` index is **derived**: delete it, rescan, lose nothing. By default it's excluded from git locally (`.git/info/exclude`);
|
|
103
|
+
committing it for team sharing is a deliberate opt-in.
|
|
118
104
|
|
|
119
105
|
## For other agent harnesses
|
|
120
106
|
|
|
121
|
-
The on-disk artifacts and `src/core` are harness-agnostic by design — Claude
|
|
122
|
-
|
|
123
|
-
skills follow the [Agent Skills standard](https://agentskills.io/specification).
|
|
107
|
+
The on-disk artifacts and `src/core` are harness-agnostic by design — Claude Code and opencode adapters are on the roadmap (docs/design.md
|
|
108
|
+
§21), and the skills follow the [Agent Skills standard](https://agentskills.io/specification).
|
|
124
109
|
|
|
125
110
|
## Development
|
|
126
111
|
|
|
@@ -129,5 +114,4 @@ npm install
|
|
|
129
114
|
npm run check # typecheck + tests with coverage gate (≥95%)
|
|
130
115
|
```
|
|
131
116
|
|
|
132
|
-
See [AGENTS.md](AGENTS.md) for contributor/agent rules and
|
|
133
|
-
[docs/design.md](docs/design.md) for the full design.
|
|
117
|
+
See [AGENTS.md](AGENTS.md) for contributor/agent rules and [docs/design.md](docs/design.md) for the full design.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-weave",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "An agent-native knowledge workspace for your life and your code. Smart notepad + repository exploration, readable by humans and agents alike.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
"coverage": "vitest run --coverage",
|
|
49
49
|
"typecheck": "tsc --noEmit",
|
|
50
50
|
"check": "npm run typecheck && npm run coverage",
|
|
51
|
+
"rewrap:md": "node scripts/rewrap-md.mjs",
|
|
52
|
+
"rewrap:md:check": "node scripts/rewrap-md.mjs --check",
|
|
51
53
|
"prepublishOnly": "npm run check"
|
|
52
54
|
},
|
|
53
55
|
"peerDependencies": {
|
|
@@ -5,45 +5,34 @@ description: Explore a git repository through its pi-weave knowledge index (.okf
|
|
|
5
5
|
|
|
6
6
|
# Weave Explore
|
|
7
7
|
|
|
8
|
-
pi-weave keeps a **derived** knowledge index of the repository at
|
|
9
|
-
|
|
10
|
-
Deleting `.okf` loses nothing — rescan to regenerate it.
|
|
8
|
+
pi-weave keeps a **derived** knowledge index of the repository at `<repo>/.okf/`. Source code is the truth; the index is a rebuildable
|
|
9
|
+
cache. Deleting `.okf` loses nothing — rescan to regenerate it.
|
|
11
10
|
|
|
12
11
|
## Tools
|
|
13
12
|
|
|
14
|
-
In pi, use the `weave_repo` tool (or the `/weave-scan` command). To see
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
In other harnesses, read the JSON documents under `.okf/` directly.
|
|
13
|
+
In pi, use the `weave_repo` tool (or the `/weave-scan` command). To see the assembled graph in the terminal, run `/weave-view tui` (Explore
|
|
14
|
+
tree, Focus neighborhood, Health surface); `/weave-view` opens the browser viewer. In other harnesses, read the JSON documents under `.okf/`
|
|
15
|
+
directly.
|
|
18
16
|
|
|
19
17
|
## Workflow
|
|
20
18
|
|
|
21
19
|
1. **Check for an index**: `weave_repo` action=status.
|
|
22
|
-
- `missing` → offer to scan (`weave_repo` action=scan), or scan directly
|
|
23
|
-
when the user asked to explore.
|
|
20
|
+
- `missing` → offer to scan (`weave_repo` action=scan), or scan directly when the user asked to explore.
|
|
24
21
|
- `stale` → scan again; the repository moved on.
|
|
25
22
|
- `fresh` → read it: action=overview.
|
|
26
|
-
2. **Start from the overview**: file counts, languages, packages, module
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
the
|
|
32
|
-
|
|
33
|
-
(`.okf/repository/summaries/` exists), read the relevant sidecars first —
|
|
34
|
-
they tell you what a file does and its outward surface in 1–3 sentences,
|
|
35
|
-
so you can decide whether to open the full file at all.
|
|
36
|
-
5. **Answer with structure**: name modules and packages by their indexed
|
|
37
|
-
paths so the user can jump straight to them.
|
|
23
|
+
2. **Start from the overview**: file counts, languages, packages, module groupings, and likely entry points. This replaces dozens of
|
|
24
|
+
`ls`/`find` calls.
|
|
25
|
+
3. **Descend progressively** (design §9): only open files in modules relevant to the user's question. The index gives you the map; the code
|
|
26
|
+
gives you the terrain.
|
|
27
|
+
4. **Read summaries before full files**: if the repo has been deep-scanned (`.okf/repository/summaries/` exists), read the relevant sidecars
|
|
28
|
+
first — they tell you what a file does and its outward surface in 1–3 sentences, so you can decide whether to open the full file at all.
|
|
29
|
+
5. **Answer with structure**: name modules and packages by their indexed paths so the user can jump straight to them.
|
|
38
30
|
|
|
39
31
|
## Deep summaries
|
|
40
32
|
|
|
41
|
-
`/weave-scan deep` creates or refreshes `.okf/repository/summaries/` — one
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
whose content hash changed since their last summary. If summaries are
|
|
45
|
-
missing or stale, offer `/weave-scan deep` to create or refresh them before
|
|
46
|
-
diving into full files.
|
|
33
|
+
`/weave-scan deep` creates or refreshes `.okf/repository/summaries/` — one sidecar per file, written by the session model. It is **opt-in
|
|
34
|
+
and incremental**: it never runs implicitly, and it only re-summarizes files whose content hash changed since their last summary. If
|
|
35
|
+
summaries are missing or stale, offer `/weave-scan deep` to create or refresh them before diving into full files.
|
|
47
36
|
|
|
48
37
|
## On-disk layout
|
|
49
38
|
|
|
@@ -59,6 +48,5 @@ diving into full files.
|
|
|
59
48
|
|
|
60
49
|
## Trust model
|
|
61
50
|
|
|
62
|
-
Everything in `.okf` is machine-generated (`source: generated`). If the user
|
|
63
|
-
|
|
64
|
-
`weave-notepad` skill) as human knowledge, not in the derived index.
|
|
51
|
+
Everything in `.okf` is machine-generated (`source: generated`). If the user corrects an interpretation, that correction belongs in the
|
|
52
|
+
vault (see the `weave-notepad` skill) as human knowledge, not in the derived index.
|
|
@@ -5,21 +5,17 @@ description: "Take and retrieve durable notes in the pi-weave vault. Use when th
|
|
|
5
5
|
|
|
6
6
|
# Weave Notepad
|
|
7
7
|
|
|
8
|
-
The pi-weave vault is the user's long-term memory: plain Markdown notes with
|
|
9
|
-
|
|
10
|
-
you write here, they can read and edit, and vice versa.
|
|
8
|
+
The pi-weave vault is the user's long-term memory: plain Markdown notes with front matter under `~/.okf/notes/`. It is shared with the human
|
|
9
|
+
— anything you write here, they can read and edit, and vice versa.
|
|
11
10
|
|
|
12
11
|
## Tools
|
|
13
12
|
|
|
14
|
-
In pi, use the `weave_note` tool. In other harnesses (or when the tool is not
|
|
15
|
-
available), operate on the files directly:
|
|
13
|
+
In pi, use the `weave_note` tool. In other harnesses (or when the tool is not available), operate on the files directly:
|
|
16
14
|
|
|
17
15
|
- **Notes** live at `~/.okf/notes/<slug>.md` (vault root overridable via `PI_WEAVE_VAULT`).
|
|
18
|
-
- Each note has YAML front matter: `title`, `created`, `updated` (ISO-8601),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
`finalize` restructures the body *above* the `## Raw` tail and preserves
|
|
22
|
-
the tail verbatim.
|
|
16
|
+
- Each note has YAML front matter: `title`, `created`, `updated` (ISO-8601), `tags: [..]`, and `source: human | agent | generated`.
|
|
17
|
+
- `weave_note` actions: `list`, `get`, `add`, `append`, `finalize`, `search`. `finalize` restructures the body *above* the `## Raw` tail and
|
|
18
|
+
preserves the tail verbatim.
|
|
23
19
|
|
|
24
20
|
## Raw Tail Format
|
|
25
21
|
|
|
@@ -41,49 +37,56 @@ Every note maintains a verbatim, append-only raw section at the bottom separated
|
|
|
41
37
|
|
|
42
38
|
### How to capture and append raw input
|
|
43
39
|
|
|
44
|
-
1. **Divider and Heading**: The raw section starts with `---` followed by `## Raw` and the notice comment: `<!-- NEVER edit below this line.
|
|
40
|
+
1. **Divider and Heading**: The raw section starts with `---` followed by `## Raw` and the notice comment: `<!-- NEVER edit below this line.
|
|
41
|
+
Verbatim user input preserved here. -->`.
|
|
45
42
|
2. **Code Blocks for Verbatim Input**: Always wrap verbatim user lines inside code blocks (triple backticks).
|
|
46
43
|
3. **Date and Time on Appends**: When appending subsequent snippets, prepend each snippet with: `<!-- appended YYYY-MM-DD HH:MM -->`.
|
|
47
44
|
4. **Finalization (`finalize`)**:
|
|
48
45
|
- `finalize` replaces or structures content only above the `---` and `## Raw` section.
|
|
49
46
|
- The `## Raw` block and all verbatim code blocks are never modified or removed.
|
|
50
47
|
|
|
48
|
+
## Dictation mode (continuous compile)
|
|
49
|
+
|
|
50
|
+
During live dictation / interview note-taking (see the skill description), Pi does **not** wait until the end to organize the note. Every
|
|
51
|
+
interactive append is immediately compiled into the body:
|
|
52
|
+
|
|
53
|
+
1. **Append the raw words verbatim** to the `## Raw` tail as usual (a dated `<!-- appended YYYY-MM-DD HH:MM -->` code block).
|
|
54
|
+
2. **Then immediately finalize** (`weave_note` action=finalize): rewrite the body *above* the `## Raw` tail — front-loaded summary,
|
|
55
|
+
sections, decisions, questions, tasks, entities, links — so the compiled document reflects everything said so far.
|
|
56
|
+
3. **Never rewrite or remove the `## Raw` tail.** It stays append-only and verbatim; only the body above it changes.
|
|
57
|
+
|
|
58
|
+
The result is a continuously-updated compiled document that stays current throughout the session — not just a raw tail that gets organized
|
|
59
|
+
once at the end.
|
|
60
|
+
|
|
51
61
|
## When to take a note
|
|
52
62
|
|
|
53
|
-
Create a note **only when the user explicitly asks** for one to exist:
|
|
54
|
-
"
|
|
55
|
-
Never promote conversation into a note on your own initiative — capture is
|
|
56
|
-
explicit by design.
|
|
63
|
+
Create a note **only when the user explicitly asks** for one to exist: "start a note on X", "add to the X note", "remember this", "jot that
|
|
64
|
+
down". Never promote conversation into a note on your own initiative — capture is explicit by design.
|
|
57
65
|
|
|
58
66
|
## When NOT to take a note
|
|
59
67
|
|
|
60
|
-
- Anything derivable from the repository itself (that knowledge belongs to
|
|
61
|
-
the `.okf` index, not the vault).
|
|
68
|
+
- Anything derivable from the repository itself (that knowledge belongs to the `.okf` index, not the vault).
|
|
62
69
|
- Session-scratch information (in-progress task state).
|
|
63
70
|
- Secrets, credentials, or anything the user hasn't confirmed is safe to persist.
|
|
64
71
|
|
|
65
72
|
## How to write a good note
|
|
66
73
|
|
|
67
|
-
1. **Search first** (`weave_note` action=search): if a note exists, `append`
|
|
68
|
-
to it rather than creating a duplicate.
|
|
74
|
+
1. **Search first** (`weave_note` action=search): if a note exists, `append` to it rather than creating a duplicate.
|
|
69
75
|
2. Title: short noun phrase ("Auth boundary decision", not "Notes").
|
|
70
|
-
3. **Scribble in, verbatim.** When the user is dictating, append their words
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
file directly in other harnesses). Move nothing out of
|
|
77
|
-
is append-only and never rewritten.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
(the default). Never overwrite a `source: human` note's meaning; append
|
|
83
|
-
with a dated "Agent addendum" section instead.
|
|
76
|
+
3. **Scribble in, verbatim.** When the user is dictating, append their words to the note as rough, verbatim scribbles — no silent rewording.
|
|
77
|
+
Keep them under the `## Raw` tail format at the end of the note.
|
|
78
|
+
4. **Compile continuously during dictation.** After *every* interactive append in dictation mode, immediately finalize the body *above* the
|
|
79
|
+
raw tail so the compiled doc stays current (see [Dictation mode](#dictation-mode-continuous-compile)). Outside dictation mode,
|
|
80
|
+
compilation stays on request.
|
|
81
|
+
5. **Finalize on request.** When the user says "finalize this" / "clean this up", restructure the body *above* the raw tail: front-loaded
|
|
82
|
+
summary, sections, entities, links. Use `weave_note` action=finalize (or edit the file directly in other harnesses). Move nothing out of
|
|
83
|
+
`## Raw` — it is append-only and never rewritten.
|
|
84
|
+
6. Tags: 1–4 lowercase tags; reuse existing tags when possible.
|
|
85
|
+
7. Provenance: notes the user scribbled stay `source: human` (finalization is editorial, not authorship) — pass `source: "human"` to `add`
|
|
86
|
+
for user-scribbled notes. Notes you draft from scratch are `source: agent` (the default). Never overwrite a `source: human` note's
|
|
87
|
+
meaning; append with a dated "Agent addendum" section instead.
|
|
84
88
|
|
|
85
89
|
## Retrieving knowledge
|
|
86
90
|
|
|
87
|
-
Use `weave_note` action=search with the user's key terms, then `get` the best
|
|
88
|
-
|
|
89
|
-
facts about code and flag the discrepancy — the note may be stale intent.
|
|
91
|
+
Use `weave_note` action=search with the user's key terms, then `get` the best hits. When a note and the repository index disagree, trust the
|
|
92
|
+
repository for facts about code and flag the discrepancy — the note may be stale intent.
|
package/src/pi/index.ts
CHANGED
|
@@ -32,6 +32,32 @@ export default function piWeave(pi: ExtensionAPI): void {
|
|
|
32
32
|
// Session-scoped viewer: lazy start on first /weave-view, never from the
|
|
33
33
|
// factory (extension rules); idempotent stop on session_shutdown.
|
|
34
34
|
let viewer: ViewerServer | null = null;
|
|
35
|
+
let lastCtx: ExtensionContext | ExtensionCommandContext | null = null;
|
|
36
|
+
let lastStatusText: string | undefined = undefined;
|
|
37
|
+
let isActive = false;
|
|
38
|
+
|
|
39
|
+
function updateStatus(ctx?: ExtensionContext | ExtensionCommandContext, text?: string): void {
|
|
40
|
+
if (ctx) lastCtx = ctx;
|
|
41
|
+
const c = ctx || lastCtx;
|
|
42
|
+
if (!c?.ui?.setStatus) return;
|
|
43
|
+
if (text !== undefined) {
|
|
44
|
+
lastStatusText = text;
|
|
45
|
+
}
|
|
46
|
+
if (!lastStatusText) {
|
|
47
|
+
c.ui.setStatus("weave", undefined);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let theme: { fg?: (slot: string, text: string) => string } | undefined;
|
|
51
|
+
try {
|
|
52
|
+
theme = (c.ui as unknown as { theme?: { fg?: (slot: string, text: string) => string } })?.theme;
|
|
53
|
+
} catch {
|
|
54
|
+
// ignore
|
|
55
|
+
}
|
|
56
|
+
const indicator = (isActive || inFlightDeepScans.size > 0)
|
|
57
|
+
? (theme?.fg ? theme.fg("accent", "●") : "●")
|
|
58
|
+
: (theme?.fg ? theme.fg("dim", "○") : "○");
|
|
59
|
+
c.ui.setStatus("weave", `${indicator} ${lastStatusText}`);
|
|
60
|
+
}
|
|
35
61
|
|
|
36
62
|
pi.on("session_shutdown", async () => {
|
|
37
63
|
const server = viewer;
|
|
@@ -39,9 +65,19 @@ export default function piWeave(pi: ExtensionAPI): void {
|
|
|
39
65
|
await server?.stop();
|
|
40
66
|
});
|
|
41
67
|
|
|
68
|
+
pi.on("agent_start", async (_event, ctx) => {
|
|
69
|
+
isActive = true;
|
|
70
|
+
updateStatus(ctx);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
pi.on("agent_end", async (_event, ctx) => {
|
|
74
|
+
isActive = false;
|
|
75
|
+
updateStatus(ctx);
|
|
76
|
+
});
|
|
77
|
+
|
|
42
78
|
pi.on("session_start", async (_event, ctx) => {
|
|
43
79
|
const status = await getWorkspaceStatus(ctx.cwd);
|
|
44
|
-
|
|
80
|
+
updateStatus(ctx, formatStatusLine(status));
|
|
45
81
|
|
|
46
82
|
if (!ctx.hasUI) return;
|
|
47
83
|
const repo = status.repository;
|
|
@@ -105,13 +141,13 @@ export default function piWeave(pi: ExtensionAPI): void {
|
|
|
105
141
|
// Compute the settled status here (no git-lock contention) and let
|
|
106
142
|
// the background scan restore it when it finishes.
|
|
107
143
|
const status = await getWorkspaceStatus(ctx.cwd);
|
|
108
|
-
startDeepScan(root, ctx, status);
|
|
144
|
+
startDeepScan(root, ctx, status, updateStatus);
|
|
109
145
|
}
|
|
110
146
|
return; // the background scan owns the status line until it settles
|
|
111
147
|
}
|
|
112
148
|
|
|
113
149
|
const status = await getWorkspaceStatus(ctx.cwd);
|
|
114
|
-
|
|
150
|
+
updateStatus(ctx, formatStatusLine(status));
|
|
115
151
|
},
|
|
116
152
|
});
|
|
117
153
|
|
|
@@ -156,15 +192,26 @@ export async function deepScanDone(root: string): Promise<void | undefined> {
|
|
|
156
192
|
* cancellation is reported via a notification. `baseStatus` is the workspace
|
|
157
193
|
* status captured before the scan and restored when it settles.
|
|
158
194
|
*/
|
|
159
|
-
function startDeepScan(
|
|
195
|
+
function startDeepScan(
|
|
196
|
+
root: string,
|
|
197
|
+
ctx: ExtensionCommandContext,
|
|
198
|
+
baseStatus: WorkspaceStatus,
|
|
199
|
+
updateStatus: (ctx?: ExtensionContext | ExtensionCommandContext, text?: string) => void,
|
|
200
|
+
): void {
|
|
160
201
|
const controller = new AbortController();
|
|
161
|
-
|
|
202
|
+
let doneResolve: () => void;
|
|
203
|
+
const done = new Promise<void>((resolve) => {
|
|
204
|
+
doneResolve = resolve;
|
|
205
|
+
});
|
|
206
|
+
inFlightDeepScans.set(root, { controller, done });
|
|
207
|
+
|
|
208
|
+
void (async () => {
|
|
162
209
|
try {
|
|
163
|
-
|
|
210
|
+
updateStatus(ctx, "🧵 deep scan: starting…");
|
|
164
211
|
const outcome = await deepScanRepository(root, ctx, {
|
|
165
212
|
onProgress: ({ current, total, path }) => {
|
|
166
213
|
const pct = total > 0 ? Math.round((current / total) * 100) : 100;
|
|
167
|
-
|
|
214
|
+
updateStatus(ctx, `🧵 deep scan: ${current}/${total} (${pct}%) — ${path}`);
|
|
168
215
|
},
|
|
169
216
|
signal: controller.signal,
|
|
170
217
|
});
|
|
@@ -183,13 +230,9 @@ function startDeepScan(root: string, ctx: ExtensionCommandContext, baseStatus: W
|
|
|
183
230
|
} finally {
|
|
184
231
|
// Restore the settled status before removing the map entry, so a caller
|
|
185
232
|
// awaiting deepScanDone() observes the settled status line.
|
|
186
|
-
updateStatusWidget(ctx, formatStatusLine(baseStatus));
|
|
187
233
|
inFlightDeepScans.delete(root);
|
|
234
|
+
updateStatus(ctx, formatStatusLine(baseStatus));
|
|
235
|
+
doneResolve!();
|
|
188
236
|
}
|
|
189
237
|
})();
|
|
190
|
-
inFlightDeepScans.set(root, { controller, done });
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function updateStatusWidget(ctx: ExtensionContext | ExtensionCommandContext, text: string | undefined): void {
|
|
194
|
-
ctx.ui.setWidget("weave", text ? [text] : undefined, { placement: "belowEditor" });
|
|
195
238
|
}
|
package/src/pi/viewer/tui/run.ts
CHANGED
|
@@ -60,7 +60,14 @@ export async function runWeaveViewTui(ctx: ExtensionCommandContext): Promise<voi
|
|
|
60
60
|
|
|
61
61
|
// Refresh the status line after close (a /weave-scan may have landed meanwhile).
|
|
62
62
|
const status = await getWorkspaceStatus(ctx.cwd);
|
|
63
|
-
|
|
63
|
+
let theme: { fg?: (slot: string, text: string) => string } | undefined;
|
|
64
|
+
try {
|
|
65
|
+
theme = (ctx.ui as unknown as { theme?: { fg?: (slot: string, text: string) => string } })?.theme;
|
|
66
|
+
} catch {
|
|
67
|
+
// ignore
|
|
68
|
+
}
|
|
69
|
+
const indicator = theme?.fg ? theme.fg("dim", "○") : "○";
|
|
70
|
+
ctx.ui.setStatus("weave", `${indicator} ${formatStatusLine(status)}`);
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
/** Test seam: build the model the explorer opens with, without a terminal. */
|