openwolf-enhanced 1.21.0 → 1.22.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 +116 -0
- package/README.md +96 -31
- package/dist/dashboard/assets/{AISuggestions-C9y4DXN7.js → AISuggestions-Cpup2r93.js} +1 -1
- package/dist/dashboard/assets/{ActivityLog-BwI3hu53.js → ActivityLog-vc08HmGa.js} +1 -1
- package/dist/dashboard/assets/{ActivityTimeline-CxfgPqU7.js → ActivityTimeline-fatU3zUR.js} +1 -1
- package/dist/dashboard/assets/{AnatomyBrowser-6xUbPIvg.js → AnatomyBrowser-CMsbTK8b.js} +1 -1
- package/dist/dashboard/assets/{BugLog-D-bqCcdb.js → BugLog-s5Pex7fA.js} +1 -1
- package/dist/dashboard/assets/{CerebrumViewer-Di01VvRz.js → CerebrumViewer-D5i0Yd88.js} +1 -1
- package/dist/dashboard/assets/{CronStatus-0LpbP4Gk.js → CronStatus-3S4D9sES.js} +1 -1
- package/dist/dashboard/assets/{DesignQC-x5mYKkE4.js → DesignQC-CeR_JqlS.js} +1 -1
- package/dist/dashboard/assets/LinkGraph-BTiwJzrc.js +1 -0
- package/dist/dashboard/assets/{MemoryViewer-Bc4Vw64G.js → MemoryViewer-QOXI9jv8.js} +1 -1
- package/dist/dashboard/assets/{NativeMemory-Dkk5zZei.js → NativeMemory-CoSRp5Q2.js} +1 -1
- package/dist/dashboard/assets/{ProjectOverview-C7G8tn04.js → ProjectOverview-G0xzHTJm.js} +1 -1
- package/dist/dashboard/assets/{ProjectsAggregate-Vu_cGEVx.js → ProjectsAggregate-BGn850vY.js} +1 -1
- package/dist/dashboard/assets/{StatusBadge-D6b5MXQJ.js → StatusBadge-DxWVdzKK.js} +1 -1
- package/dist/dashboard/assets/{TokenUsage-DFc8Ut2I.js → TokenUsage-BTTrcgDP.js} +1 -1
- package/dist/dashboard/assets/{index-BxheJgWu.js → index-CCxQQi4q.js} +3 -3
- package/dist/dashboard/assets/index-CVfvTpSA.css +2 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/hooks/shared.js +43 -2
- package/dist/src/cli/recall-cmd.js +18 -1
- package/dist/src/cli/recall-cmd.js.map +1 -1
- package/dist/src/daemon/cron-engine.js +9 -1
- package/dist/src/daemon/cron-engine.js.map +1 -1
- package/dist/src/daemon/wolf-daemon.js +53 -0
- package/dist/src/daemon/wolf-daemon.js.map +1 -1
- package/dist/src/hooks/shared.js +43 -2
- package/dist/src/hooks/shared.js.map +1 -1
- package/dist/src/utils/link-graph.js +183 -0
- package/dist/src/utils/link-graph.js.map +1 -0
- package/dist/src/utils/maintenance.js +20 -0
- package/dist/src/utils/maintenance.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/cron-manifest.json +32 -10
- package/dist/dashboard/assets/index-CbZ7BrXr.css +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,122 @@ This is a fork of [OpenWolf](https://github.com/cytostack/openwolf) by Cytostack
|
|
|
6
6
|
Pvt Ltd. Versions ≤ 1.0.4 refer to the upstream project; `1.1.0` is the first
|
|
7
7
|
release of this fork.
|
|
8
8
|
|
|
9
|
+
## [1.22.0] — 2026-08-20
|
|
10
|
+
|
|
11
|
+
**Contains a privacy fix. If you run the background daemon with an API key exported, read the
|
|
12
|
+
first entry.**
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- 🔒 **The scheduled AI tasks sent `<private>` content to an LLM API.** Two tasks ship in the
|
|
17
|
+
manifest — `cerebrum-reflection` (Sundays, reads `cerebrum.md`) and `project-suggestions`
|
|
18
|
+
(Mondays, reads `memory.md` and `anatomy.md`) — and until now the cron engine read those files
|
|
19
|
+
**raw**. Every other path that leaves the machine strips private regions first: `push`, `recall`
|
|
20
|
+
and `consolidate` all route through `blocksFor()`. This one did not, which made the README's
|
|
21
|
+
promise ("kept out of anything OpenWolf sends elsewhere") untrue once a week.
|
|
22
|
+
|
|
23
|
+
**Who was affected:** anyone whose daemon was running (`openwolf init` starts it automatically
|
|
24
|
+
when pm2 is installed), with the cron engine enabled, an API key exported in the daemon's
|
|
25
|
+
environment, and `<private>` blocks in `cerebrum.md`, `memory.md` or `anatomy.md`. If any of
|
|
26
|
+
those four is missing, nothing private was sent.
|
|
27
|
+
|
|
28
|
+
The fix strips at the read, and a regression test anchors on the read itself rather than on a
|
|
29
|
+
nearby symbol — so a second, unstripped context path fails the suite instead of shipping.
|
|
30
|
+
|
|
31
|
+
- 🔒 **A `<private>` written *about* disabled the knowledge base.** Matching is fail-closed by
|
|
32
|
+
design (1.20.5): an opening tag with no closing tag redacts to end of file, because a forgotten
|
|
33
|
+
tag must never mean "not private". But the match did not distinguish a marker from a mention.
|
|
34
|
+
This project's own `MEMORY.md` describes a bug using the words `` `<private>` `` in backticks —
|
|
35
|
+
and that one mention silently hid **104 of its 114 lines** from `recall`, from the resume digest,
|
|
36
|
+
from the semantic index. Code spans and fences are now masked before tags are located. The
|
|
37
|
+
security property is unchanged and covered by four tests, including that a fenced mention does
|
|
38
|
+
not disarm a real marker later in the same file.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- **The two AI cron tasks now ship disabled.** Something that sends project knowledge to a third
|
|
43
|
+
party should require a deliberate switch-on, not a deliberate switch-off. ⚠️ This only affects
|
|
44
|
+
**new** projects: `cron-manifest.json` is user data and `openwolf update` never rewrites it.
|
|
45
|
+
- **`openwolf doctor` now warns an existing install** when scheduled tasks would send files and an
|
|
46
|
+
API key is present, naming the tasks and the files. That is how projects created before this
|
|
47
|
+
release find out.
|
|
48
|
+
- **Corrected the upstream claims in the README.** It stated that `cytostack/openwolf` was
|
|
49
|
+
unmaintained and last released 1.0.4 in March 2026. That is false: upstream shipped a 2.x line
|
|
50
|
+
and is actively developed. The two are separate lineages — this package forked 1.x and never
|
|
51
|
+
adopted the 2.x rewrite — and the README now says so, in both languages.
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- **Backlinks and a link graph.** Citations were one-way: you could open an entry by id but not ask
|
|
56
|
+
who leans on it. `recall --id` now lists "Referenced by", and a new **Links** panel in the
|
|
57
|
+
dashboard draws the graph, ranks notes by how often they are referenced, and names dead
|
|
58
|
+
references instead of swallowing them. The graph shows the 90 best-connected notes on purpose —
|
|
59
|
+
drawing all 324 produced a hairball, and the caption says what is not drawn.
|
|
60
|
+
- The graph reads citation ids, `[[wikilinks]]` and markdown index links. Three calibration bugs
|
|
61
|
+
were found and fixed while building it: bracket patterns inside code were counted as links (10 of
|
|
62
|
+
17 reported dead links were Odoo array literals), the link-text bound was 160 characters against
|
|
63
|
+
a measured 473, and file keys collided between `.wolf/memory.md` and `native/MEMORY.md`.
|
|
64
|
+
|
|
65
|
+
## [1.21.0] — 2026-08-20
|
|
66
|
+
|
|
67
|
+
The honest-ledger release. Three additions, and one number that stops flattering itself.
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- **Injection accounting.** The savings figure counted only what OpenWolf avoided and never what
|
|
72
|
+
it costs. Every resume digest and every reminder block is context the model pays for, and none
|
|
73
|
+
of it appeared anywhere — a ledger with one side is how "898 million tokens saved" stayed
|
|
74
|
+
plausible for months (see 1.20.8). There are exactly two injection points, and both now book
|
|
75
|
+
into `lifetime.injection_tokens_estimated`. `report`, `status` and the dashboard show
|
|
76
|
+
reads-avoided, injected, and the net. **The net may go negative on purpose**: a metric that
|
|
77
|
+
cannot look bad measures nothing.
|
|
78
|
+
- **`openwolf find <query>`.** Locates a symbol or file without a repo-wide grep, ranked from the
|
|
79
|
+
index the scanner already writes — no second index that can go stale unnoticed. Symbol hits carry
|
|
80
|
+
exact line ranges, so the next step is a targeted `offset`/`limit` read instead of loading the
|
|
81
|
+
file. Also available as `--json` and as the MCP tool **`openwolf_find`**, which is the point: an
|
|
82
|
+
agent can ask where something lives instead of reading a file to find out.
|
|
83
|
+
- **Import-graph importance.** Ties in `find` break on PageRank over the project's own import graph.
|
|
84
|
+
Only project-internal relative imports count, and an unresolvable specifier creates no edge —
|
|
85
|
+
invented edges skew importance invisibly. Stored as a **rank percentile**, not the raw score:
|
|
86
|
+
measured on this repo the raw distribution was so skewed (median 0.058 against a maximum of 1.0)
|
|
87
|
+
that 118 of 158 files collapsed into the lowest bar.
|
|
88
|
+
- **tree-sitter symbol ranges (optional).** The regex extractor guesses a symbol's end as "the line
|
|
89
|
+
before the next one"; of 487 shared symbols, **472 (97 %) had an end line that was too far**, so
|
|
90
|
+
an `offset`/`limit` hint almost always pulled in something else. tree-sitter gives the real end
|
|
91
|
+
from the syntax tree and finds methods inside classes. It is an `optionalDependency` — 52 MB of
|
|
92
|
+
grammars is the wrong trade to force on everyone — falls back cleanly, and says why when it
|
|
93
|
+
cannot run. `web-tree-sitter` is pinned to `^0.24.7`: 0.26 is ABI-incompatible with the 0.1.13
|
|
94
|
+
grammars and fails with an *empty* error message.
|
|
95
|
+
- **`AGENTS.md` protocol block.** Codex and OpenCode read `AGENTS.md`, not `CLAUDE.md`, and this
|
|
96
|
+
fork never wrote it — their hooks fired while the protocol never reached the model. One delimited
|
|
97
|
+
block is now maintained there; everything outside it is left byte for byte alone, and broken
|
|
98
|
+
markers cause a refusal rather than a guessed repair.
|
|
99
|
+
|
|
100
|
+
### Fixed
|
|
101
|
+
|
|
102
|
+
- **Codex only ever got 4 of the 8 hooks.** `pre-read`, `pre-write`, `post-read` and `precompact`
|
|
103
|
+
were missing — exactly the ones carrying read avoidance, the do-not-repeat warning and the
|
|
104
|
+
compaction snapshot. OpenWolf ran there at half strength without anything ever failing.
|
|
105
|
+
- **The Codex tool matchers were too narrow.** `^apply_patch$` would never have seen a write
|
|
106
|
+
reported as `Write`, and a matcher that misses fails silently. They are a union of Claude and
|
|
107
|
+
Codex tool names now, and `SessionStart` deliberately carries no matcher so a compaction still
|
|
108
|
+
gets its digest.
|
|
109
|
+
- **Codex ignores hooks without `hooks = true` under `[features]`.** Without that switch a
|
|
110
|
+
perfectly fine-looking `hooks.json` sits there and none of it fires. `config.toml` is created
|
|
111
|
+
when missing and warned about otherwise — table-scoped, so the same key under another table does
|
|
112
|
+
not suppress the warning.
|
|
113
|
+
- **A partial `config.json` crashed `openwolf scan`.** `readJSON` returns the file's content when
|
|
114
|
+
the file exists, so the defaults never applied; a config holding only `openwolf.remote` died with
|
|
115
|
+
a raw `TypeError`.
|
|
116
|
+
- **`--limit` with a non-number reported "no match".** `parseInt("abc")` is `NaN` and
|
|
117
|
+
`slice(0, NaN)` is empty, so `find <symbol> --limit abc` claimed nothing was found for a symbol
|
|
118
|
+
that is indexed. A silent wrong answer is worse than a rejected flag.
|
|
119
|
+
- **`anatomy-symbols.json` was written non-atomically**, unlike every other `.wolf` file. A
|
|
120
|
+
`pre-read` hook firing mid-write read truncated JSON and lost all symbol hints for that turn.
|
|
121
|
+
|
|
122
|
+
Eight findings from the pre-release review are folded into these commits rather than left for a
|
|
123
|
+
follow-up; the review was run against the finished branch before anything was pushed.
|
|
124
|
+
|
|
9
125
|
## [1.20.9] — 2026-08-16
|
|
10
126
|
|
|
11
127
|
### Fixed
|
package/README.md
CHANGED
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
<h1 align="center">OpenWolf Enhanced</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<strong>A second brain for
|
|
9
|
-
|
|
8
|
+
<strong>A second brain for your coding agent.</strong><br />
|
|
9
|
+
A file index it consults before opening anything, a memory of your corrections that survives
|
|
10
|
+
<code>/clear</code>, and a token ledger that counts <em>both</em> sides. Through invisible hooks —
|
|
11
|
+
no workflow changes.
|
|
10
12
|
</p>
|
|
11
13
|
|
|
12
14
|
<p align="center">
|
|
@@ -14,6 +16,8 @@
|
|
|
14
16
|
</p>
|
|
15
17
|
|
|
16
18
|
<p align="center">
|
|
19
|
+
<a href="https://www.npmjs.com/package/openwolf-enhanced"><img src="https://img.shields.io/npm/v/openwolf-enhanced?color=CB3837&logo=npm&label=npm" alt="npm version" /></a>
|
|
20
|
+
<a href="https://www.npmjs.com/package/openwolf-enhanced"><img src="https://img.shields.io/npm/dm/openwolf-enhanced?color=CB3837&label=downloads" alt="npm downloads" /></a>
|
|
17
21
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-AGPL--3.0-blue.svg" alt="License: AGPL-3.0" /></a>
|
|
18
22
|
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-20%2B-green.svg" alt="Node.js" /></a>
|
|
19
23
|
<a href="https://github.com/cytostack/openwolf"><img src="https://img.shields.io/badge/fork%20of-cytostack%2Fopenwolf-lightgrey.svg" alt="Fork of cytostack/openwolf" /></a>
|
|
@@ -31,7 +35,36 @@
|
|
|
31
35
|
|
|
32
36
|
**Works with [Claude Code](https://claude.com/claude-code), [OpenAI Codex CLI](https://github.com/openai/codex), [Gemini CLI](https://github.com/google-gemini/gemini-cli) and [OpenCode](https://github.com/sst/opencode)** — plus Claude Desktop and any MCP client. Persistent project memory, searchable citations, and context injection through invisible hooks. Git-native, no database, no cloud.
|
|
33
37
|
|
|
34
|
-
**Contents:** [Why](#why-openwolf-exists) · [What's Enhanced](#whats-enhanced) · [Quick Start](#quick-start) · [How It Works](#how-it-works) · [Commands](#commands) · [Claude Desktop / MCP](#use-in-claude-desktop-mcp) · [FAQ](#faq)
|
|
38
|
+
**Contents:** [See it](#see-it) · [Why](#why-openwolf-exists) · [What's Enhanced](#whats-enhanced) · [Quick Start](#quick-start) · [How It Works](#how-it-works) · [Commands](#commands) · [Claude Desktop / MCP](#use-in-claude-desktop-mcp) · [FAQ](#faq)
|
|
39
|
+
|
|
40
|
+
## See it
|
|
41
|
+
|
|
42
|
+
Find where something lives, without a repo-wide grep — and read only that slice:
|
|
43
|
+
|
|
44
|
+
```console
|
|
45
|
+
$ openwolf find pageRank
|
|
46
|
+
|
|
47
|
+
1 hit(s) for "pageRank"
|
|
48
|
+
|
|
49
|
+
▆ src/scanner/import-graph.ts:106-147
|
|
50
|
+
fn pageRank · ~380 tok
|
|
51
|
+
|
|
52
|
+
▁…█ = importance in the import graph (how often, and from how central a file).
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Ask what it actually cost you — including what OpenWolf itself put into the context:
|
|
56
|
+
|
|
57
|
+
```console
|
|
58
|
+
$ openwolf report
|
|
59
|
+
|
|
60
|
+
Estimated (char-ratio heuristic)
|
|
61
|
+
Total tokens: 1,204,880
|
|
62
|
+
Reads avoided: 412,300
|
|
63
|
+
OpenWolf injected: 88,140 (resume digests, reminders)
|
|
64
|
+
Net savings: 324,160
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
That third line is the one most tools leave out. It can go negative, and it is meant to.
|
|
35
68
|
|
|
36
69
|
## Why OpenWolf Exists
|
|
37
70
|
|
|
@@ -41,27 +74,53 @@ OpenWolf gives Claude a second brain: a file index so it knows what files contai
|
|
|
41
74
|
|
|
42
75
|
## What's Enhanced
|
|
43
76
|
|
|
44
|
-
Everything upstream does, plus
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
|
50
|
-
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
| 🧠 **
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
77
|
+
Everything upstream does, plus the following. Details for each live in the
|
|
78
|
+
[docs](docs/index.md) and the [CHANGELOG](CHANGELOG.md).
|
|
79
|
+
|
|
80
|
+
**Finding things**
|
|
81
|
+
|
|
82
|
+
| | |
|
|
83
|
+
|---|---|
|
|
84
|
+
| 🔎 **`openwolf find`** | Symbol and file lookup from the existing index — with exact line ranges, so you read one function instead of the file. Also `--json` and the MCP tool `openwolf_find`. |
|
|
85
|
+
| 🧭 **Import-graph importance** | Ties break on PageRank over your own imports, stored as a rank percentile. The biggest file is rarely the most important one. |
|
|
86
|
+
| 🌳 **tree-sitter ranges** *(optional)* | Real symbol boundaries from the syntax tree instead of "the line before the next one" — which was wrong for 97 % of symbols. Optional dependency; falls back cleanly and says why. |
|
|
87
|
+
| 🧠 **Searchable memory** | `recall <query>` over STATUS / cerebrum / memory / buglog **and** Claude's native Auto Memory, BM25-ranked, each hit with a stable citation id. `--semantic` ranks by meaning via local embeddings; `--hybrid` fuses both. |
|
|
88
|
+
|
|
89
|
+
**Knowing what it costs**
|
|
90
|
+
|
|
91
|
+
| | |
|
|
92
|
+
|---|---|
|
|
93
|
+
| 📊 **Both sides of the ledger** | `report` shows reads avoided, **what OpenWolf itself injected**, and the net. The net may go negative — a metric that cannot look bad measures nothing. |
|
|
94
|
+
| 📦 **Bounded storage** | Ledger, bug log, cron queues and waste flags are all capped. No runaway multi-MB files. Every limit lives in `openwolf.retention` and survives updates. |
|
|
95
|
+
| 🩺 **Self-maintenance** | `doctor` reports the `.wolf/` footprint and compacts it, flags registry issues, suggests `.wolfignore` entries, and hints at near-duplicate cerebrum entries — `consolidate` LLM-merges them. |
|
|
96
|
+
| 📤 **Export** | `export <sessions\|bugs>` to JSON or CSV (RFC 4180). |
|
|
97
|
+
|
|
98
|
+
**Working across agents**
|
|
99
|
+
|
|
100
|
+
| | |
|
|
101
|
+
|---|---|
|
|
102
|
+
| 🐝 **Codex, Gemini, OpenCode** | `init`/`update` detect them and register the hooks there too, including the `AGENTS.md` protocol block they actually read — one delimited block, everything outside it untouched. |
|
|
103
|
+
| 🔌 **Claude Desktop / MCP** | `openwolf mcp` exposes recall, resume, find and memory-health to any MCP client. |
|
|
104
|
+
| 🔌 **Model-agnostic AI tasks** | The cron engine's AI tasks point at any OpenAI-compatible endpoint — OpenAI, Groq, Cerebras, Mistral, a local server. No code change. |
|
|
105
|
+
|
|
106
|
+
**Session hygiene**
|
|
107
|
+
|
|
108
|
+
| | |
|
|
109
|
+
|---|---|
|
|
110
|
+
| 🧭 **Smart resume** | A token-bounded digest on session start: STATUS and Do-Not-Repeat inline, the rest as an *"available on demand"* index — so the model continues without re-reading. |
|
|
111
|
+
| 📓 **Activity capture** *(opt-in)* | Notable shell commands **and failures** appended to a capped log that feeds the next resume. Secrets redacted, trivial reads dropped. Off by default. |
|
|
112
|
+
| 🗒 **Structured summaries** | Each session gets a `Did / Learned / Next / Files` scaffold, so memory stays greppable. |
|
|
113
|
+
| 🎯 **`.wolfignore`** | gitignore-style scoping for both anatomy scanning and hook tracking. |
|
|
114
|
+
| 🌍 **Localized digest** | The resume digest can render in German via `openwolf.lang`. |
|
|
115
|
+
|
|
116
|
+
**Trust**
|
|
117
|
+
|
|
118
|
+
| | |
|
|
119
|
+
|---|---|
|
|
120
|
+
| 🔒 **Privacy** | `<private>…</private>` in any `.wolf` file stays out of the injected context, out of search, and out of anything sent elsewhere. |
|
|
121
|
+
| 🛡 **Security & correctness** | Dashboard on loopback and token-gated, no command injection or path traversal, secret-file exclusion — plus ~15 security fixes from upstream pull requests that were never merged into the 1.x line this fork is based on. |
|
|
122
|
+
| 🚀 **Trusted releases** | Published to npm via GitHub OIDC — no long-lived token — with SLSA provenance. CI builds and tests on every push. |
|
|
123
|
+
| 📈 **Dashboard** | Deep-linkable panels, a cross-project view, a command log, Design QC grid, and a daemon-down banner. |
|
|
65
124
|
|
|
66
125
|
Every change is versioned in the [CHANGELOG](CHANGELOG.md); attribution is in the [NOTICE](NOTICE).
|
|
67
126
|
|
|
@@ -71,10 +130,13 @@ Every change is versioned in the [CHANGELOG](CHANGELOG.md); attribution is in th
|
|
|
71
130
|
npm install -g openwolf-enhanced
|
|
72
131
|
```
|
|
73
132
|
|
|
74
|
-
> **Note
|
|
75
|
-
>
|
|
76
|
-
>
|
|
77
|
-
>
|
|
133
|
+
> **Note — two different packages.** `npm install -g openwolf` installs
|
|
134
|
+
> [cytostack/openwolf](https://github.com/cytostack/openwolf), which is **actively developed**
|
|
135
|
+
> (2.x line, current as of August 2026). This package is a **separate lineage**: it forked the
|
|
136
|
+
> 1.x codebase in 2026 and never adopted the 2.x rewrite, so the two have diverged in
|
|
137
|
+
> architecture as well as features. Both still provide the same `openwolf` command, which means
|
|
138
|
+
> they cannot be installed side by side. Pick this one for the bounded-storage, self-maintenance
|
|
139
|
+
> and security work described above; pick upstream for the 2.x feature line.
|
|
78
140
|
|
|
79
141
|
<details>
|
|
80
142
|
<summary>Install from source instead</summary>
|
|
@@ -127,7 +189,9 @@ Two things to know before you re-run `pnpm build` on a copy you have already ins
|
|
|
127
189
|
| `memory.md` | Chronological action log with token estimates |
|
|
128
190
|
| `buglog.json` | Bug fix memory, searchable, prevents re-discovery |
|
|
129
191
|
| `token-ledger.json` | Lifetime token tracking and session history |
|
|
130
|
-
| `hooks/` |
|
|
192
|
+
| `hooks/` | 8 lifecycle hooks (pure Node.js), deployed to every detected agent |
|
|
193
|
+
| `anatomy-symbols.json` | Symbol line ranges for larger files — what `find` returns and what turns a read into a slice |
|
|
194
|
+
| `anatomy-graph.json` | Import-graph importance per file, used to order otherwise equal hits |
|
|
131
195
|
| `config.json` | Configuration with sensible defaults (incl. `retention`) |
|
|
132
196
|
| `identity.md` | Agent persona for this project |
|
|
133
197
|
| `OPENWOLF.md` | Instructions Claude follows every session |
|
|
@@ -205,10 +269,11 @@ openwolf consolidate LLM-merge near-duplicate cerebrum entries [--dry-r
|
|
|
205
269
|
openwolf recall <query> Keyword-search .wolf + native memory; ids per hit [--limit N] [--full] [--all] [--json]
|
|
206
270
|
[--semantic] rank by meaning (local embeddings) · [--hybrid] fuse keyword + semantic
|
|
207
271
|
openwolf recall --id <id> Expand a citation id to its full entry (second disclosure layer)
|
|
272
|
+
openwolf find <query> Locate a symbol or file — ranked, with exact line ranges [--limit N] [--json]
|
|
208
273
|
openwolf link Link to a remote workspace [--url URL --token TOKEN] [--status] [--unlink]
|
|
209
274
|
openwolf push Offer learnings, decisions and bugs to the linked workspace [--dry-run]
|
|
210
275
|
openwolf export <what> Export sessions|bugs as JSON or CSV [--format csv] [--out FILE]
|
|
211
|
-
openwolf mcp Run an MCP server (recall/resume/memory-health) [--project DIR]
|
|
276
|
+
openwolf mcp Run an MCP server (recall/resume/find/memory-health) [--project DIR]
|
|
212
277
|
openwolf scan Refresh the project structure map [--check]
|
|
213
278
|
openwolf dashboard Open the real-time web dashboard
|
|
214
279
|
openwolf daemon <cmd> start | stop | restart | logs — background task scheduler
|
|
@@ -297,7 +362,7 @@ explicitly. OpenWolf never writes to Claude's native memory — it reads and sur
|
|
|
297
362
|
No. Everything lives in a local `.wolf/` directory in your project — plain Markdown and JSON, git-native, no database and no cloud. Nothing leaves your machine. (The only outbound calls are optional: the background cron AI tasks and `openwolf consolidate`, which you point at a provider of your choice.)
|
|
298
363
|
|
|
299
364
|
**How is this different from the original `openwolf`?**
|
|
300
|
-
|
|
365
|
+
They are separate lineages now, not a maintained fork of an abandoned project. This package forked upstream's **1.x** code in 2026; upstream has since shipped a **2.x rewrite** and is actively developed. Neither tracks the other. What this fork adds on top of the 1.x base: bounded/self-maintaining storage, BM25 memory search with citations, an MCP server, model-agnostic AI tasks, multi-agent support, and ~15 security fixes — while staying a drop-in replacement for the same `openwolf` command. If you want upstream's 2.x work, install `openwolf`.
|
|
301
366
|
|
|
302
367
|
**Does it work with anything other than Claude Code?**
|
|
303
368
|
Yes. `init`/`update` auto-detect **Codex CLI**, **Gemini CLI** and **OpenCode** and register the same hooks there. The `openwolf mcp` server also exposes recall/resume to **Claude Desktop** and any MCP client.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as e,c as t,r as n}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n}from"./index-CCxQQi4q.js";import{i as r}from"./utils-BqE_aDxV.js";var i=t(e(),1),a=n(),o=new Set(`ts.tsx.js.jsx.mjs.cjs.py.rs.go.java.rb.php.cs.cpp.cc.c.h.hpp.swift.kt.vue.svelte.json.md.mdx.yml.yaml.toml.css.scss.html.sh.sql.prisma.graphql`.split(`.`)),s=/([A-Za-z0-9_.\-/]+\.[A-Za-z][A-Za-z0-9]{0,7})/g;function c(e,t){if(!t)return e;let n=[],r=0,i;for(s.lastIndex=0;(i=s.exec(e))!==null;){let s=i[1],c=s.slice(s.lastIndexOf(`.`)+1).toLowerCase();(s.includes(`/`)||o.has(c))&&(i.index>r&&n.push(e.slice(r,i.index)),n.push((0,a.jsx)(`button`,{onClick:()=>t(s),className:`font-mono underline decoration-dotted underline-offset-2`,style:{color:`var(--accent)`},title:`Jump to ${s} in Anatomy`,children:s},`${i.index}-${s}`)),r=i.index+s.length)}return r<e.length&&n.push(e.slice(r)),n.length?n:e}var l=[{key:`achievements`,title:`Achievements`,icon:`🏆`,color:`#059669`},{key:`improvements`,title:`Improvements`,icon:`✨`,color:`#3b82f6`},{key:`next_tasks`,title:`Next Tasks`,icon:`📋`,color:`#d97706`},{key:`risks`,title:`Risks & Tech Debt`,icon:`🛡`,color:`#dc2626`}],u=`Analyze this project and write a JSON file to .wolf/suggestions.json with this exact structure:
|
|
2
2
|
{
|
|
3
3
|
"generated_at": "<ISO timestamp>",
|
|
4
4
|
"achievements": ["..."],
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t,r as n}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n}from"./index-CCxQQi4q.js";var r=t(e(),1),i=n();function a(e){return e.split(`
|
|
2
2
|
`).filter(e=>e.trim().length>0).map(e=>{let t=/ → error$/.test(e),n=e.replace(/ → error$/,``),r=n.match(/^(\d{1,2}:\d{2})\s+(.*)$/);return r?{time:r[1],cmd:r[2],failed:t}:{time:``,cmd:n,failed:t}}).reverse()}function o({label:e,value:t,accent:n}){return(0,i.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:e}),(0,i.jsx)(`p`,{className:`text-2xl font-bold mt-1`,style:{color:n?`var(--danger)`:`var(--text-primary)`},children:t})]})}function s({data:e}){let[t,n]=(0,r.useState)(``),[s,c]=(0,r.useState)(!1),l=(0,r.useMemo)(()=>a(e.activityLog||``),[e.activityLog]),u=l.filter(e=>e.failed).length,d=l.filter(e=>(!s||e.failed)&&(!t||e.cmd.toLowerCase().includes(t.toLowerCase())));if(l.length===0)return(0,i.jsxs)(`div`,{className:`rounded-xl p-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsx)(`h3`,{className:`font-medium mb-2`,style:{color:`var(--text-secondary)`},children:`No shell activity captured`}),(0,i.jsxs)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:[`Passive Bash capture is `,(0,i.jsx)(`strong`,{children:`opt-in`}),`. Enable it in `,(0,i.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:`.wolf/config.json`}),` — set `,(0,i.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:`openwolf.capture.enabled = true`}),` — and notable commands (commits, installs, tests, builds) plus any failures land in `,(0,i.jsx)(`code`,{children:`.wolf/activity.log`}),`, redacted, and feed the next session's resume digest.`]})]});let f={color:`var(--text-secondary)`,padding:`0.5rem 0.75rem`,borderTop:`1px solid var(--border)`},p={color:`var(--text-muted)`,fontWeight:500,textAlign:`left`,padding:`0.5rem 0.75rem`};return(0,i.jsxs)(`div`,{children:[(0,i.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-3 gap-4 mb-4`,children:[(0,i.jsx)(o,{label:`Captured commands`,value:String(l.length)}),(0,i.jsx)(o,{label:`Failures`,value:String(u),accent:u>0}),(0,i.jsx)(o,{label:`Showing`,value:String(d.length)})]}),(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 mb-3`,children:[(0,i.jsx)(`input`,{type:`text`,placeholder:`Filter commands…`,value:t,onChange:e=>n(e.target.value),className:`rounded-lg px-3 py-2 text-sm flex-1 min-w-[200px] focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,i.jsx)(`button`,{onClick:()=>c(e=>!e),className:`px-3 py-2 text-xs rounded-lg transition-colors`,style:{background:s?`var(--danger-subtle)`:`var(--bg-surface)`,border:`1px solid var(--border)`,color:s?`var(--danger)`:`var(--text-muted)`},children:s?`Showing failures only`:`Failures only`})]}),(0,i.jsx)(`div`,{className:`rounded-xl overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:(0,i.jsx)(`div`,{className:`overflow-x-auto`,style:{maxHeight:520},children:(0,i.jsxs)(`table`,{className:`w-full text-sm`,style:{borderCollapse:`collapse`},children:[(0,i.jsx)(`thead`,{children:(0,i.jsxs)(`tr`,{children:[(0,i.jsx)(`th`,{style:{...p,width:64},children:`Time`}),(0,i.jsxs)(`th`,{style:p,children:[`Command (`,d.length,`)`]})]})}),(0,i.jsx)(`tbody`,{children:d.map((e,t)=>(0,i.jsxs)(`tr`,{style:{background:e.failed?`var(--danger-subtle)`:`transparent`},children:[(0,i.jsx)(`td`,{style:{...f,color:`var(--text-faint)`,whiteSpace:`nowrap`},children:e.time||`—`}),(0,i.jsxs)(`td`,{style:{...f,color:e.failed?`var(--danger)`:`var(--text-primary)`},className:`font-mono`,children:[e.cmd,e.failed&&(0,i.jsx)(`span`,{className:`text-xs ml-2`,style:{color:`var(--danger)`},children:`error`})]})]},t))})]})})}),(0,i.jsxs)(`p`,{className:`text-xs mt-3`,style:{color:`var(--text-faint)`},children:[`Secrets are redacted before capture; the newest commands feed the resume digest. Read-only view of `,(0,i.jsx)(`code`,{children:`.wolf/activity.log`}),`.`]})]})}export{s as ActivityLog};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,r as n}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n}from"./index-CCxQQi4q.js";var r=t(e(),1),i=n();function a({data:e}){let{memory:t}=e,[n,a]=(0,r.useState)(`all`),[o,s]=(0,r.useState)(``),[c,l]=(0,r.useState)(!0),u=(0,r.useMemo)(()=>{let e=t;if(n===`today`){let t=new Date().toISOString().slice(0,10);e=e.filter(e=>e.date===t)}else if(n===`week`){let t=new Date(Date.now()-7*864e5).toISOString().slice(0,10);e=e.filter(e=>e.date>=t)}if(o){let t=o.toLowerCase();e=e.map(e=>({...e,entries:e.entries.filter(e=>e.action.toLowerCase().includes(t)||e.files.toLowerCase().includes(t))})).filter(e=>e.entries.length>0)}return e},[t,n,o]);return(0,i.jsxs)(`div`,{children:[(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 mb-4`,children:[(0,i.jsx)(`div`,{className:`flex gap-1 rounded-lg p-1`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[`all`,`today`,`week`].map(e=>(0,i.jsx)(`button`,{onClick:()=>a(e),className:`px-3 py-1 text-xs rounded-md transition-colors`,style:{background:n===e?`var(--bg-surface-hover)`:`transparent`,color:n===e?`var(--text-primary)`:`var(--text-muted)`},children:e===`all`?`All`:e===`today`?`Today`:`This Week`},e))}),(0,i.jsx)(`input`,{type:`text`,placeholder:`Search actions...`,value:o,onChange:e=>s(e.target.value),className:`rounded-lg px-3 py-1.5 text-sm flex-1 min-w-[200px] focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,i.jsx)(`button`,{onClick:()=>l(!c),className:`px-3 py-1.5 text-xs rounded-lg`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-muted)`},children:c?`Flat view`:`Group by session`})]}),u.length===0?(0,i.jsx)(`div`,{className:`text-center py-12`,style:{color:`var(--text-muted)`},children:`No activity found.`}):c?u.map((e,t)=>(0,i.jsxs)(`div`,{className:`mb-4`,children:[(0,i.jsxs)(`div`,{className:`text-sm font-medium mb-2`,style:{color:`var(--text-muted)`},children:[e.date,` `,e.time,` — `,e.entries.length,` actions`]}),(0,i.jsx)(`div`,{className:`rounded-xl`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:e.entries.map((t,n)=>(0,i.jsxs)(`div`,{className:`flex items-center gap-4 px-4 py-3`,style:{borderBottom:n<e.entries.length-1?`1px solid var(--border)`:`none`},children:[(0,i.jsx)(`span`,{className:`text-xs font-mono w-12 shrink-0`,style:{color:`var(--text-faint)`},children:t.time}),(0,i.jsx)(`span`,{className:`w-2 h-2 rounded-full shrink-0 ${t.action.includes(`Created`)?`bg-emerald-500`:t.action.includes(`Edited`)?`bg-blue-500`:``}`,style:{background:!t.action.includes(`Created`)&&!t.action.includes(`Edited`)?`var(--text-faint)`:void 0}}),(0,i.jsx)(`span`,{className:`text-sm flex-1`,style:{color:`var(--text-secondary)`},children:t.action}),(0,i.jsx)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:t.tokens})]},n))})]},t)):(0,i.jsx)(`div`,{className:`rounded-xl`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:u.flatMap(e=>e.entries.map((t,n)=>(0,i.jsxs)(`div`,{className:`flex items-center gap-4 px-4 py-3`,style:{borderBottom:`1px solid var(--border)`},children:[(0,i.jsx)(`span`,{className:`text-xs font-mono w-20 shrink-0`,style:{color:`var(--text-faint)`},children:e.date}),(0,i.jsx)(`span`,{className:`text-xs font-mono w-12 shrink-0`,style:{color:`var(--text-faint)`},children:t.time}),(0,i.jsx)(`span`,{className:`text-sm flex-1`,style:{color:`var(--text-secondary)`},children:t.action}),(0,i.jsx)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:t.tokens})]},`${e.date}-${n}`)))})]})}export{a as ActivityTimeline};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,r as n}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n}from"./index-CCxQQi4q.js";import{r,t as i}from"./utils-BqE_aDxV.js";var a=t(e(),1),o=n();function s({tokens:e,className:t}){return(0,o.jsxs)(`span`,{className:i(`font-mono text-xs`,e<200?`text-emerald-400`:e<1e3?`text-amber-400`:`text-red-400`,t),children:[`~`,r(e),` tok`]})}function c(e){let t={name:`.`,path:`.`,children:[],files:[]},n=new Map;n.set(`./`,t);for(let r of e){let e=r.section;if(!n.has(e)){let r=e.replace(/\/$/,``).split(`/`),i=t,a=``;for(let e of r){a=a?`${a}/${e}`:e;let t=`${a}/`;if(!n.has(t)){let r={name:e,path:t,children:[],files:[]};i.children.push(r),n.set(t,r)}i=n.get(t)}}n.get(e).files.push({file:r.file,description:r.description,tokens:r.tokens})}return t}function l({node:e,search:t,depth:n=0}){let[r,i]=(0,a.useState)(n<2),c=t.toLowerCase(),f=e.files.filter(e=>!t||e.file.toLowerCase().includes(c)||e.description.toLowerCase().includes(c)),p=e.children.some(e=>d(e,c));return t&&f.length===0&&!p?null:(0,o.jsxs)(`div`,{className:`ml-3`,children:[e.name!==`.`&&(0,o.jsxs)(`button`,{onClick:()=>i(!r),className:`flex items-center gap-1.5 py-1 text-sm transition-colors`,style:{color:`var(--text-secondary)`},children:[(0,o.jsx)(`span`,{className:`w-4 text-center`,style:{color:`var(--text-faint)`},children:r?`▼`:`▶`}),(0,o.jsx)(`span`,{className:`text-amber-400`,children:`📁`}),(0,o.jsxs)(`span`,{children:[e.name,`/`]}),(0,o.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[u(e),` files`]})]}),(r||e.name===`.`)&&(0,o.jsxs)(`div`,{className:e.name===`.`?``:`ml-4`,children:[f.sort((e,t)=>e.file.localeCompare(t.file)).map(e=>(0,o.jsxs)(`div`,{className:`flex items-center gap-2 py-1 pl-5`,children:[(0,o.jsx)(`span`,{style:{color:`var(--text-faint)`},children:`📄`}),(0,o.jsx)(`span`,{className:`text-sm font-mono`,style:{color:`var(--text-primary)`},children:e.file}),e.description&&(0,o.jsxs)(`span`,{className:`text-xs truncate max-w-xs`,style:{color:`var(--text-faint)`},children:[`— `,e.description]}),(0,o.jsx)(s,{tokens:e.tokens,className:`ml-auto shrink-0`})]},e.file)),e.children.sort((e,t)=>e.name.localeCompare(t.name)).map(e=>(0,o.jsx)(l,{node:e,search:t,depth:n+1},e.path))]})]})}function u(e){return e.files.length+e.children.reduce((e,t)=>e+u(t),0)}function d(e,t){return e.files.some(e=>e.file.toLowerCase().includes(t)||e.description.toLowerCase().includes(t))?!0:e.children.some(e=>d(e,t))}function f({data:e,initialFile:t}){let{anatomy:n}=e,[r,i]=(0,a.useState)(t??``),[s,u]=(0,a.useState)(!1);(0,a.useEffect)(()=>{t&&i(t)},[t]);let d=(0,a.useMemo)(()=>c(n.entries),[n.entries]),f=(0,a.useMemo)(()=>{let e=n.entries.map(e=>e.tokens);return{total:n.entries.length,avg:e.length>0?Math.round(e.reduce((e,t)=>e+t,0)/e.length):0,largest:e.length>0?Math.max(...e):0}},[n.entries]);return(0,o.jsxs)(`div`,{children:[(0,o.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 mb-4`,children:[(0,o.jsx)(`input`,{type:`text`,placeholder:`Search files...`,value:r,onChange:e=>i(e.target.value),className:`flex-1 min-w-[200px] rounded-lg px-3 py-2 text-sm focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,o.jsx)(`button`,{onClick:()=>u(!s),className:`px-3 py-2 text-xs rounded-lg`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-muted)`},children:s?`Sort: Size`:`Sort: A-Z`})]}),(0,o.jsxs)(`div`,{className:`flex gap-4 mb-4 text-sm`,style:{color:`var(--text-muted)`},children:[(0,o.jsxs)(`span`,{children:[f.total,` files tracked`]}),(0,o.jsxs)(`span`,{children:[`Avg: `,f.avg,` tok/file`]}),(0,o.jsxs)(`span`,{children:[`Largest: `,f.largest,` tok`]})]}),(0,o.jsx)(`div`,{className:`rounded-xl p-4`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:n.entries.length===0?(0,o.jsxs)(`div`,{className:`text-center py-12`,style:{color:`var(--text-muted)`},children:[(0,o.jsx)(`p`,{className:`text-2xl mb-2`,children:`📂`}),(0,o.jsxs)(`p`,{children:[`No anatomy data. Run `,(0,o.jsx)(`code`,{style:{color:`var(--text-secondary)`},children:`openwolf scan`}),` to index your project.`]})]}):(0,o.jsx)(l,{node:d,search:r})})]})}export{f as AnatomyBrowser};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,r as n}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n}from"./index-CCxQQi4q.js";var r=t(e(),1),i=n();function a({data:e}){let{buglog:t}=e,[n,a]=(0,r.useState)(``),[o,s]=(0,r.useState)(null),c=n?t.bugs.filter(e=>e.error_message.toLowerCase().includes(n.toLowerCase())||e.root_cause.toLowerCase().includes(n.toLowerCase())||e.fix.toLowerCase().includes(n.toLowerCase())||e.tags.some(e=>e.toLowerCase().includes(n.toLowerCase()))):t.bugs;if(t.bugs.length===0)return(0,i.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-16 text-center`,children:[(0,i.jsx)(`div`,{className:`text-4xl mb-3`,children:`🐛`}),(0,i.jsx)(`h3`,{className:`font-medium mb-1`,style:{color:`var(--text-secondary)`},children:`No bugs logged yet`}),(0,i.jsx)(`p`,{className:`text-sm max-w-sm`,style:{color:`var(--text-muted)`},children:`When you encounter and fix bugs, they'll appear here for future reference.`})]});let l=t.bugs.flatMap(e=>e.tags),u=new Map;for(let e of l)u.set(e,(u.get(e)||0)+1);let d=[...u.entries()].sort((e,t)=>t[1]-e[1]).slice(0,5);return(0,i.jsxs)(`div`,{children:[(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4 mb-4`,children:[(0,i.jsx)(`input`,{type:`text`,placeholder:`Search bugs...`,value:n,onChange:e=>a(e.target.value),className:`flex-1 min-w-[200px] rounded-lg px-3 py-2 text-sm focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,i.jsxs)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:[t.bugs.length,` bugs logged`]})]}),d.length>0&&(0,i.jsx)(`div`,{className:`flex flex-wrap gap-2 mb-4`,children:d.map(([e,t])=>(0,i.jsxs)(`button`,{onClick:()=>a(e),className:`px-2 py-1 text-xs rounded-full`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:`var(--text-muted)`},children:[e,` (`,t,`)`]},e))}),(0,i.jsx)(`div`,{className:`space-y-3`,children:c.map(e=>{let t=o===e.id;return(0,i.jsxs)(`div`,{className:`rounded-xl overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>s(t?null:e.id),className:`w-full flex items-start gap-3 px-5 py-3 transition-colors text-left`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsx)(`span`,{className:`text-sm mt-0.5`,style:{color:`var(--text-faint)`},children:t?`▼`:`▶`}),(0,i.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,i.jsx)(`p`,{className:`text-sm truncate`,style:{color:`var(--text-primary)`},children:e.error_message}),(0,i.jsxs)(`div`,{className:`flex items-center gap-3 mt-1`,children:[(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:e.file}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:e.timestamp?.slice(0,10)})]})]}),e.occurrences>1&&(0,i.jsxs)(`span`,{className:`shrink-0 px-2 py-0.5 rounded-full text-xs`,style:{background:`var(--warning-subtle)`,color:`var(--warning)`},children:[`Seen `,e.occurrences,`x`]})]}),t&&(0,i.jsxs)(`div`,{className:`px-5 py-4 space-y-3`,style:{borderTop:`1px solid var(--border)`},children:[(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`p`,{className:`text-xs uppercase mb-1`,style:{color:`var(--text-faint)`},children:`Error Message`}),(0,i.jsx)(`pre`,{className:`text-sm rounded-lg p-3 overflow-x-auto font-mono`,style:{color:`var(--danger)`,background:`var(--danger-subtle)`},children:e.error_message})]}),(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`p`,{className:`text-xs uppercase mb-1`,style:{color:`var(--text-faint)`},children:`Root Cause`}),(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-secondary)`},children:e.root_cause})]}),(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`p`,{className:`text-xs uppercase mb-1`,style:{color:`var(--text-faint)`},children:`Fix`}),(0,i.jsx)(`pre`,{className:`text-sm rounded-lg p-3 overflow-x-auto font-mono`,style:{color:`var(--accent)`,background:`var(--accent-subtle)`},children:e.fix})]}),(0,i.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:e.tags.map(e=>(0,i.jsx)(`span`,{className:`px-2 py-0.5 text-xs rounded-full`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:`var(--text-muted)`},children:e},e))})]})]},e.id)})})]})}export{a as BugLog};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,r as n}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n}from"./index-CCxQQi4q.js";var r=t(e(),1),i=n();function a({data:e}){let{cerebrum:t}=e,[n,a]=(0,r.useState)(``),[o,s]=(0,r.useState)({preferences:!0,learnings:!0,doNotRepeat:!0,decisions:!1}),c=e=>s(t=>({...t,[e]:!t[e]})),l=e=>!n||e.toLowerCase().includes(n.toLowerCase());return(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`div`,{className:`flex items-center justify-between mb-4`,children:(0,i.jsxs)(`div`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:[`Last updated: `,t.lastUpdated||`—`,` ·`,t.preferences.length+t.learnings.length+t.doNotRepeat.length+t.decisions.length,` entries`]})}),(0,i.jsx)(`input`,{type:`text`,placeholder:`Search cerebrum...`,value:n,onChange:e=>a(e.target.value),className:`w-full rounded-lg px-3 py-2 text-sm mb-4 focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,i.jsxs)(`div`,{className:`rounded-xl mb-4 overflow-hidden`,style:{background:`var(--danger-subtle)`,border:`1px solid rgba(220, 38, 38, 0.2)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`doNotRepeat`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`rgba(220, 38, 38, 0.08)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{style:{color:`var(--danger)`},children:`⊘`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--danger)`},children:`Do-Not-Repeat`}),(0,i.jsx)(`span`,{className:`text-xs px-2 py-0.5 rounded-full`,style:{background:`rgba(220, 38, 38, 0.1)`,color:`var(--danger)`},children:t.doNotRepeat.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.doNotRepeat?`▼`:`▶`})]}),o.doNotRepeat&&(0,i.jsxs)(`div`,{className:`px-5 pb-4 space-y-2`,children:[t.doNotRepeat.filter(e=>l(e.text)).map((e,t)=>(0,i.jsxs)(`div`,{className:`rounded-lg p-3`,style:{background:`rgba(220, 38, 38, 0.05)`,border:`1px solid rgba(220, 38, 38, 0.1)`},children:[e.date&&(0,i.jsxs)(`span`,{className:`text-xs font-mono mr-2`,style:{color:`rgba(220, 38, 38, 0.6)`},children:[`[`,e.date,`]`]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-secondary)`},children:e.text})]},t)),t.doNotRepeat.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No entries yet.`})]})]}),(0,i.jsxs)(`div`,{className:`rounded-xl mb-4 overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`preferences`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{className:`text-blue-400`,children:`◈`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`User Preferences`}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:t.preferences.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.preferences?`▼`:`▶`})]}),o.preferences&&(0,i.jsxs)(`div`,{className:`px-5 pb-4`,children:[t.preferences.filter(l).map((e,t)=>(0,i.jsxs)(`div`,{className:`flex items-start gap-2 py-1.5`,children:[(0,i.jsx)(`span`,{className:`mt-1`,style:{color:`var(--text-faint)`},children:`•`}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-secondary)`},children:e})]},t)),t.preferences.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No preferences recorded yet.`})]})]}),(0,i.jsxs)(`div`,{className:`rounded-xl mb-4 overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`learnings`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{style:{color:`var(--accent)`},children:`◎`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Key Learnings`}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:t.learnings.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.learnings?`▼`:`▶`})]}),o.learnings&&(0,i.jsxs)(`div`,{className:`px-5 pb-4 space-y-2`,children:[t.learnings.filter(l).map((e,t)=>(0,i.jsx)(`div`,{className:`rounded-lg p-3 text-sm`,style:{background:`var(--bg-surface-hover)`,color:`var(--text-secondary)`},children:e},t)),t.learnings.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No learnings recorded yet.`})]})]}),(0,i.jsxs)(`div`,{className:`rounded-xl overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`decisions`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{className:`text-amber-400`,children:`⚖`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Decision Log`}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:t.decisions.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.decisions?`▼`:`▶`})]}),o.decisions&&(0,i.jsxs)(`div`,{className:`px-5 pb-4 space-y-2`,children:[t.decisions.filter(l).map((e,t)=>(0,i.jsx)(`div`,{className:`rounded-lg p-3 text-sm`,style:{background:`var(--bg-surface-hover)`,color:`var(--text-secondary)`},children:e},t)),t.decisions.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No decisions logged yet.`})]})]})]})}export{a as CerebrumViewer};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,r as n,t as r}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n,t as r}from"./index-CCxQQi4q.js";import{i,n as a}from"./utils-BqE_aDxV.js";import{t as o}from"./StatusBadge-DxWVdzKK.js";var s=t(e(),1),c=n();function l({data:e}){let{cronManifest:t,cronState:n,client:l}=e,[u,d]=(0,s.useState)(!0),[f,p]=(0,s.useState)(!1),[m,h]=(0,s.useState)({}),g=e=>n.dead_letter_queue.some(t=>t.task_id===e)?`failed`:n.execution_log.filter(t=>t.task_id===e).sort((e,t)=>t.timestamp.localeCompare(e.timestamp))[0]?.status||`ok`,_=e=>{let t=n.execution_log.filter(t=>t.task_id===e).sort((e,t)=>t.timestamp.localeCompare(e.timestamp))[0];return t?i(t.timestamp):`never`},v=e=>{h(t=>({...t,[e]:`running`})),r(`/api/cron/run/${encodeURIComponent(e)}`,{method:`POST`}).then(t=>{h(n=>({...n,[e]:t.ok?`ok`:`error`})),setTimeout(()=>h(t=>{let n={...t};return delete n[e],n}),3e3)}).catch(()=>{h(t=>({...t,[e]:`error`})),setTimeout(()=>h(t=>{let n={...t};return delete n[e],n}),3e3)})},y=e=>{l?.send({type:`retry_dead_letter`,task_id:e})};return(0,c.jsxs)(`div`,{children:[(0,c.jsx)(`div`,{className:`rounded-xl overflow-hidden mb-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:(0,c.jsxs)(`table`,{className:`w-full`,children:[(0,c.jsx)(`thead`,{children:(0,c.jsxs)(`tr`,{style:{borderBottom:`1px solid var(--border)`},children:[(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase`,style:{color:`var(--text-faint)`},children:`Status`}),(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase`,style:{color:`var(--text-faint)`},children:`Task`}),(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase hidden md:table-cell`,style:{color:`var(--text-faint)`},children:`Schedule`}),(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase hidden md:table-cell`,style:{color:`var(--text-faint)`},children:`Last Run`}),(0,c.jsx)(`th`,{className:`text-right px-4 py-3 text-xs font-medium uppercase`,style:{color:`var(--text-faint)`},children:`Actions`})]})}),(0,c.jsx)(`tbody`,{children:t.tasks.map(e=>(0,c.jsxs)(`tr`,{className:`transition-colors`,style:{borderBottom:`1px solid var(--border)`},onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,c.jsx)(`td`,{className:`px-4 py-3`,children:(0,c.jsx)(o,{status:e.enabled?g(e.id):`disabled`})}),(0,c.jsxs)(`td`,{className:`px-4 py-3`,children:[(0,c.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-primary)`},children:e.name}),(0,c.jsx)(`p`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:e.description})]}),(0,c.jsx)(`td`,{className:`px-4 py-3 hidden md:table-cell text-sm`,style:{color:`var(--text-muted)`},children:a(e.schedule)}),(0,c.jsx)(`td`,{className:`px-4 py-3 hidden md:table-cell text-sm`,style:{color:`var(--text-faint)`},children:_(e.id)}),(0,c.jsx)(`td`,{className:`px-4 py-3 text-right`,children:(()=>{let t=m[e.id];return(0,c.jsx)(`button`,{onClick:()=>v(e.id),disabled:t===`running`,className:`px-3 py-1 text-xs rounded-md transition-colors`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:t===`ok`?`var(--accent)`:t===`error`?`var(--danger)`:`var(--text-secondary)`,opacity:t===`running`?.6:1},children:t===`running`?`Running…`:t===`ok`?`Triggered ✓`:t===`error`?`Failed ✗`:`Run Now`})})()})]},e.id))})]})}),(0,c.jsxs)(`div`,{className:`rounded-xl p-5 mb-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,c.jsxs)(`button`,{onClick:()=>d(!u),className:`flex items-center gap-2 w-full text-left`,children:[(0,c.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:u?`▼`:`▶`}),(0,c.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Dead Letter Queue`}),(0,c.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[`(`,n.dead_letter_queue.length,`)`]})]}),u&&(n.dead_letter_queue.length===0?(0,c.jsx)(`div`,{className:`text-center py-6 text-sm mt-2`,style:{color:`var(--text-muted)`},children:`No dead letters — all systems healthy`}):(0,c.jsx)(`div`,{className:`space-y-3 mt-3`,children:n.dead_letter_queue.map((e,t)=>(0,c.jsx)(`div`,{className:`rounded-lg p-4`,style:{background:`var(--danger-subtle)`,border:`1px solid rgba(220, 38, 38, 0.2)`},children:(0,c.jsxs)(`div`,{className:`flex items-start justify-between`,children:[(0,c.jsxs)(`div`,{children:[(0,c.jsx)(`p`,{className:`text-sm font-medium`,style:{color:`var(--danger)`},children:e.task_id}),(0,c.jsx)(`p`,{className:`text-xs mt-1`,style:{color:`var(--text-muted)`},children:e.error}),(0,c.jsxs)(`p`,{className:`text-xs mt-1`,style:{color:`var(--text-faint)`},children:[i(e.timestamp),` · `,e.attempts,` attempts`]})]}),(0,c.jsx)(`button`,{onClick:()=>y(e.task_id),className:`px-3 py-1 text-xs rounded-md`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:`var(--text-secondary)`},children:`Retry`})]})},t))}))]}),(0,c.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,c.jsxs)(`button`,{onClick:()=>p(!f),className:`flex items-center gap-2 w-full text-left`,children:[(0,c.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:f?`▼`:`▶`}),(0,c.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Execution History`})]}),f&&(0,c.jsxs)(`div`,{className:`mt-3`,children:[n.execution_log.slice(-30).reverse().map((e,t)=>(0,c.jsxs)(`div`,{className:`flex items-center gap-4 py-2`,style:{borderBottom:`1px solid var(--border)`},children:[(0,c.jsx)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:e.timestamp?.slice(11,16)}),(0,c.jsx)(`span`,{className:`text-sm flex-1`,style:{color:`var(--text-secondary)`},children:e.task_id}),(0,c.jsxs)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:[e.duration_ms,`ms`]}),(0,c.jsx)(o,{status:e.status})]},t)),n.execution_log.length===0&&(0,c.jsx)(`p`,{className:`text-sm py-4 text-center`,style:{color:`var(--text-muted)`},children:`No executions yet.`})]})]})]})}export{l as CronStatus};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,n,r,t as i}from"./index-
|
|
1
|
+
import{a as e,c as t,n,r,t as i}from"./index-CCxQQi4q.js";var a=t(e(),1),o=r(),s=e=>n(`/api/designqc/capture/${encodeURIComponent(e)}`);function c({data:e}){let{designqcReport:t,project:n}=e,[r,c]=(0,a.useState)(`idle`),[l,u]=(0,a.useState)(null),[d,f]=(0,a.useState)(null),p=t&&t.captures&&t.captures.length>0;return(0,o.jsxs)(`div`,{children:[(0,o.jsxs)(`div`,{className:`rounded-xl px-4 py-3 mb-6 flex items-start gap-3`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,o.jsx)(`span`,{style:{color:`var(--text-faint)`,marginTop:1},children:`ℹ`}),(0,o.jsxs)(`div`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:[`Works with `,(0,o.jsx)(`span`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`any accessible URL`}),` — local or deployed. The URL is auto-detected from `,(0,o.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:`package.json`}),` homepage, env files, or a running dev server.`,n?.root&&(0,o.jsxs)(`span`,{children:[` Scanning `,(0,o.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:n.root}),`.`]})]})]}),(0,o.jsxs)(`div`,{className:`rounded-xl p-5 mb-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,o.jsxs)(`div`,{className:`flex items-center justify-between mb-3`,children:[(0,o.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Capture Screenshots`}),(0,o.jsx)(`button`,{onClick:()=>{c(`running`),u(null),i(`/api/designqc/run`,{method:`POST`,headers:{"Content-Type":`application/json`},body:`{}`}).then(async e=>{if(!e.ok){let t=await e.json().catch(()=>({error:e.statusText}));throw Error(t.error||e.statusText)}c(`idle`)}).catch(e=>{c(`error`),u(e.message)})},disabled:r===`running`,className:`px-4 py-1.5 text-sm rounded-lg transition-colors`,style:{background:r===`error`?`var(--danger-subtle)`:`var(--accent-subtle)`,border:`1px solid ${r===`error`?`rgba(220,38,38,0.3)`:`var(--accent)`}`,color:r===`error`?`var(--danger)`:`var(--accent)`,opacity:r===`running`?.6:1},children:r===`running`?`Capturing…`:r===`error`?`Retry Capture`:`Run Capture`})]}),r===`running`&&(0,o.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`Auto-detecting URL, launching browser, capturing screenshots… this takes ~15–30s.`}),r===`error`&&l&&(0,o.jsx)(`p`,{className:`text-sm`,style:{color:`var(--danger)`},children:l}),r===`idle`&&(0,o.jsxs)(`div`,{className:`space-y-1.5 text-sm`,style:{color:`var(--text-muted)`},children:[(0,o.jsxs)(`p`,{children:[`Detects your URL automatically from `,(0,o.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:`package.json`}),`, env files, or a running dev server.`]}),(0,o.jsxs)(`p`,{children:[`After capture, ask Claude: `,(0,o.jsx)(`span`,{className:`italic`,children:`"Read .wolf/designqc-captures/ and evaluate the design"`})]})]})]}),(0,o.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,o.jsx)(`h3`,{className:`font-medium mb-3`,style:{color:`var(--text-secondary)`},children:`Last Capture`}),p?(0,o.jsxs)(`div`,{children:[(0,o.jsxs)(`div`,{className:`flex gap-4 text-sm mb-4`,children:[(0,o.jsxs)(`span`,{style:{color:`var(--text-faint)`},children:[`Captured: `,t.captured_at||`—`]}),(0,o.jsxs)(`span`,{style:{color:`var(--text-faint)`},children:[`Size: `,t.total_size_kb||0,`KB`]}),(0,o.jsxs)(`span`,{style:{color:`var(--text-faint)`},children:[`Est. tokens: ~`,t.estimated_tokens||0]})]}),(0,o.jsx)(`div`,{className:`grid grid-cols-2 md:grid-cols-3 gap-4`,children:t.captures.map((e,t)=>(0,o.jsxs)(`button`,{onClick:()=>f(e.file),className:`text-left rounded-lg overflow-hidden transition-transform hover:-translate-y-0.5`,style:{background:`var(--bg-base)`,border:`1px solid var(--border)`},title:`Klicken zum Vergrößern`,children:[(0,o.jsx)(`img`,{src:s(e.file),alt:`${e.viewport} · ${e.route}`,loading:`lazy`,className:`w-full block`,style:{maxHeight:200,objectFit:`cover`,objectPosition:`top`,background:`var(--bg-surface)`}}),(0,o.jsxs)(`div`,{className:`px-3 py-2`,children:[(0,o.jsx)(`div`,{className:`text-sm truncate`,style:{color:`var(--text-primary)`},children:e.file}),(0,o.jsxs)(`div`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[e.viewport,` · `,e.route]})]})]},t))})]}):(0,o.jsx)(`div`,{className:`text-center py-8`,children:(0,o.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No screenshots captured yet.`})})]}),d&&(0,o.jsxs)(`div`,{onClick:()=>f(null),className:`fixed inset-0 z-50 flex items-center justify-center p-6`,style:{background:`rgba(0,0,0,0.8)`},children:[(0,o.jsx)(`div`,{className:`relative max-w-6xl max-h-[90vh] overflow-auto rounded-lg`,onClick:e=>e.stopPropagation(),children:(0,o.jsx)(`img`,{src:s(d),alt:d,className:`block`,style:{maxWidth:`100%`}})}),(0,o.jsx)(`button`,{onClick:()=>f(null),className:`absolute top-4 right-4 w-9 h-9 rounded-full flex items-center justify-center text-lg`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`},"aria-label":`Schließen`,children:`✕`})]})]})}export{c as DesignQC};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,c as t,r as n,t as r}from"./index-CCxQQi4q.js";var i=t(e(),1),a=n();function o(e,t,n,r){let i=new Map(e.map((e,t)=>[e.key,t])),a=e.length,o=new Float64Array(a),s=new Float64Array(a);for(let e=0;e<a;e++){let t=e*2.399963%(Math.PI*2),i=Math.sqrt((e+.5)/a)*Math.min(n,r)*.42;o[e]=n/2+Math.cos(t)*i,s[e]=r/2+Math.sin(t)*i}let c=t.map(e=>[i.get(e.from),i.get(e.to)]).filter(e=>e[0]!==void 0&&e[1]!==void 0);for(let e=0;e<220;e++){let t=1-e/220;for(let e=0;e<a;e++)for(let n=e+1;n<a;n++){let r=o[e]-o[n],i=s[e]-s[n],a=r*r+i*i;if(a<1&&(a=1,r=e-n||1,i=1),a>9e4)continue;let c=420/a*t,l=Math.sqrt(a);o[e]+=r/l*c,s[e]+=i/l*c,o[n]-=r/l*c,s[n]-=i/l*c}for(let[e,n]of c){let r=o[n]-o[e],i=s[n]-s[e],a=Math.max(1,Math.hypot(r,i)),c=(a-72)*.02*t;o[e]+=r/a*c,s[e]+=i/a*c,o[n]-=r/a*c,s[n]-=i/a*c}for(let e=0;e<a;e++)o[e]=Math.max(14,Math.min(n-14,o[e])),s[e]=Math.max(14,Math.min(r-14,s[e]))}return{x:o,y:s,idx:i}}function s(){let[e,t]=(0,i.useState)(null),[n,s]=(0,i.useState)(null),c=(0,i.useRef)(null);(0,i.useEffect)(()=>{r(`/api/link-graph`).then(e=>e.json()).then(t).catch(()=>t({available:!1,error:`not reachable`}))},[]);let l=(0,i.useMemo)(()=>(e?.nodes??[]).filter(e=>e.in+e.out>0),[e]),u=(0,i.useMemo)(()=>[...l].sort((e,t)=>t.in+t.out-(e.in+e.out)).slice(0,90),[l]),d=(0,i.useMemo)(()=>new Set(u.map(e=>e.key)),[u]),f=(0,i.useMemo)(()=>(e?.edges??[]).filter(e=>d.has(e.from)&&d.has(e.to)),[e,d]),p=(e?.nodes?.length??0)-l.length;if((0,i.useEffect)(()=>{let t=c.current;if(!t||!e?.available||u.length===0)return;let r=t.width,i=t.height,{x:a,y:s,idx:l}=o(u,f,r,i),d=t.getContext(`2d`);if(!d)return;d.clearRect(0,0,r,i),d.strokeStyle=`rgba(148,163,184,0.22)`,d.lineWidth=1;for(let e of f){let t=l.get(e.from),n=l.get(e.to);t===void 0||n===void 0||(d.beginPath(),d.moveTo(a[t],s[t]),d.lineTo(a[n],s[n]),d.stroke())}let p=Math.max(1,...u.map(e=>e.in));u.forEach((e,t)=>{let r=3+Math.sqrt(e.in/p)*9;d.beginPath(),d.arc(a[t],s[t],r,0,Math.PI*2),d.fillStyle=e.key===n?`#fbbf24`:e.in>0?`#34d399`:`#64748b`,d.fill()}),d.fillStyle=`rgba(226,232,240,0.85)`,d.font=`11px ui-monospace, monospace`,[...u].sort((e,t)=>t.in-e.in).slice(0,8).forEach(e=>{let t=l.get(e.key);d.fillText(e.title.replace(/\.md$/,``).slice(0,26),a[t]+10,s[t]+4)})},[e,u,f,n]),!e)return(0,a.jsx)(`div`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`Loading…`});if(!e.available)return(0,a.jsxs)(`div`,{className:`rounded-xl p-5 text-sm`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-muted)`},children:[`No link graph available`,e.error?` — ${e.error}`:``,`.`]});let m=[...e.nodes??[]].sort((e,t)=>t.in-e.in).filter(e=>e.in>0).slice(0,12);return(0,a.jsxs)(`div`,{className:`grid gap-6 lg:grid-cols-[1.4fr_1fr]`,children:[(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsxs)(`div`,{className:`mb-3 flex items-baseline justify-between`,children:[(0,a.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Link graph`}),(0,a.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[u.length,` of `,l.length,` linked shown · `,p,` isolated · `,e.edges?.length??0,` links`]})]}),(0,a.jsx)(`canvas`,{ref:c,width:760,height:460,className:`w-full rounded-lg`,style:{background:`var(--bg-base)`,border:`1px solid var(--border)`}}),(0,a.jsxs)(`p`,{className:`mt-3 text-xs`,style:{color:`var(--text-faint)`},children:[`The `,90,` best-connected notes; dot size follows how often a note is referenced. Drawing all `,l.length,` produced a hairball, so the rest is counted rather than drawn —`,e.stats?.blocks.toLocaleString(`en-US`),` blocks sit behind these `,e.stats?.files,` files.`]})]}),(0,a.jsxs)(`div`,{className:`flex flex-col gap-6`,children:[(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsx)(`h3`,{className:`mb-3 font-medium`,style:{color:`var(--text-secondary)`},children:`Most referenced`}),m.length===0?(0,a.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`Nothing links to anything yet.`}):(0,a.jsx)(`ul`,{className:`flex flex-col gap-1.5 text-sm`,children:m.map(e=>(0,a.jsx)(`li`,{children:(0,a.jsxs)(`button`,{onClick:()=>s(e.key===n?null:e.key),className:`flex w-full items-center gap-2 rounded px-1.5 py-1 text-left hover:bg-white/5`,style:{color:e.key===n?`var(--accent)`:`var(--text-primary)`},children:[(0,a.jsx)(`span`,{className:`font-mono text-xs tabular-nums`,style:{color:`var(--text-faint)`},children:String(e.in).padStart(2,` `)}),(0,a.jsx)(`span`,{className:`truncate`,children:e.title.replace(/\.md$/,``)})]})},e.key))})]}),(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsxs)(`h3`,{className:`mb-1 font-medium`,style:{color:`var(--text-secondary)`},children:[`Dead references `,e.dangling?.length?`(${e.dangling.length})`:``]}),(0,a.jsx)(`p`,{className:`mb-3 text-xs`,style:{color:`var(--text-faint)`},children:`A link whose target does not exist. Named rather than swallowed — each one is a note that was meant to be written, or a link that was mistyped.`}),(e.dangling?.length??0)===0?(0,a.jsx)(`p`,{className:`text-sm`,style:{color:`var(--accent)`},children:`None. Every reference resolves.`}):(0,a.jsx)(`ul`,{className:`flex flex-col gap-2 text-sm`,children:e.dangling.slice(0,12).map((e,t)=>(0,a.jsxs)(`li`,{className:`leading-snug`,children:[(0,a.jsx)(`code`,{className:`text-xs`,style:{color:`#f87171`},children:e.target}),(0,a.jsxs)(`div`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[`from `,e.fromSrc.replace(/^native\//,``)]})]},t))})]})]})]})}export{s as LinkGraph};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,r as n}from"./index-
|
|
1
|
+
import{a as e,c as t,r as n}from"./index-CCxQQi4q.js";var r=t(e(),1),i=n();function a({data:e}){let{memory:t}=e,[n,a]=(0,r.useState)(0),[o,s]=(0,r.useState)(``),c=o?t.filter(e=>e.entries.some(e=>e.action.toLowerCase().includes(o.toLowerCase())||e.files.toLowerCase().includes(o.toLowerCase()))):t;return(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`div`,{className:`flex items-center gap-3 mb-4`,children:(0,i.jsx)(`input`,{type:`text`,placeholder:`Search memory...`,value:o,onChange:e=>s(e.target.value),className:`flex-1 rounded-lg px-3 py-2 text-sm focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}})}),c.length===0?(0,i.jsx)(`div`,{className:`text-center py-12`,style:{color:`var(--text-muted)`},children:`No sessions found.`}):(0,i.jsx)(`div`,{className:`space-y-3`,children:c.map((e,t)=>{let r=n===t,o=e.entries.reduce((e,t)=>e+(parseInt(t.tokens.replace(/[^0-9]/g,``))||0),0);return(0,i.jsxs)(`div`,{className:`rounded-xl overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>a(r?-1:t),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:r?`▼`:`▶`}),(0,i.jsxs)(`span`,{className:`text-sm font-medium`,style:{color:`var(--text-primary)`},children:[e.date,` `,e.time]}),(0,i.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[e.entries.length,` actions`]})]}),o>0&&(0,i.jsxs)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:[`~`,o,` tok`]})]}),r&&e.entries.length>0&&(0,i.jsx)(`div`,{style:{borderTop:`1px solid var(--border)`},children:(0,i.jsxs)(`table`,{className:`w-full`,children:[(0,i.jsx)(`thead`,{children:(0,i.jsxs)(`tr`,{className:`text-xs uppercase`,style:{color:`var(--text-faint)`},children:[(0,i.jsx)(`th`,{className:`text-left px-4 py-2 w-16`,children:`Time`}),(0,i.jsx)(`th`,{className:`text-left px-4 py-2`,children:`Action`}),(0,i.jsx)(`th`,{className:`text-left px-4 py-2 hidden md:table-cell`,children:`Files`}),(0,i.jsx)(`th`,{className:`text-left px-4 py-2 hidden md:table-cell`,children:`Outcome`}),(0,i.jsx)(`th`,{className:`text-right px-4 py-2 w-20`,children:`Tokens`})]})}),(0,i.jsx)(`tbody`,{children:e.entries.map((e,t)=>(0,i.jsxs)(`tr`,{style:{borderBottom:`1px solid var(--border)`},onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsx)(`td`,{className:`px-4 py-2 text-xs font-mono`,style:{color:`var(--text-faint)`},children:e.time}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-sm`,style:{color:`var(--text-secondary)`},children:e.action}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-sm hidden md:table-cell`,style:{color:`var(--text-muted)`},children:e.files}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-sm hidden md:table-cell`,style:{color:`var(--text-muted)`},children:e.outcome}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-xs font-mono text-right`,style:{color:`var(--text-faint)`},children:e.tokens})]},t))})]})})]},t)})})]})}export{a as MemoryViewer};
|