@iroaxel/arcena 4.3.157

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Axel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ ![arcena](screenshots/ggboss.png)
2
+
3
+ <p align="center">
4
+ <strong>One chat. Many arcicoder workers. The boss runs the room.</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@iroaxel/arcena"><img src="https://img.shields.io/npm/v/@iroaxel/arcena?style=for-the-badge" alt="npm version"></a>
9
+ <a href="../../LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge" alt="MIT License"></a>
10
+ </p>
11
+
12
+ You talk to the boss. The boss drives the workers β€” one per project β€” in parallel. Dispatch work, watch them finish, keep a backlog, swap models on the fly. All from one terminal.
13
+
14
+ Built on [`@iroaxel/arcicoder`](../ggcoder/README.md), [`@iroaxel/gg-agent`](../gg-agent/README.md) and [`@iroaxel/gg-ai`](../gg-ai/README.md). Part of the [GG Framework](../../README.md) monorepo.
15
+
16
+ ---
17
+
18
+ ## πŸš€ Run It
19
+
20
+ ```bash
21
+ # Sign in once with arcicoder β€” arcena reuses the same auth
22
+ npm i -g @iroaxel/arcicoder
23
+ arcicoder login
24
+
25
+ # Install the boss
26
+ npm i -g @iroaxel/arcena
27
+
28
+ # Pick which projects the boss should drive (interactive picker β€”
29
+ # scans your arcicoder, Claude Code, and Codex session history)
30
+ arcena link
31
+
32
+ # Start the orchestrator
33
+ arcena
34
+ ```
35
+
36
+ Already linked? `arcena continue` resumes the most recent session. `arcena --resume <id>` resumes a specific one.
37
+
38
+ ---
39
+
40
+ ## πŸͺ„ How it works
41
+
42
+ You type one prompt. The boss decides which workers to dispatch, in parallel or serial, with `prompt_worker` (fire-and-forget) or by adding to the task plan and calling `dispatch_pending`. Each worker is a full `arcicoder` agent β€” read, write, edit, bash, grep, find, ls, web fetch, sub-agents β€” running in its own project directory.
43
+
44
+ When a worker finishes, you get a tight summary back: **Changed**, **Skipped**, **Verified**, **Notes**, and a single-letter **Status** (`DONE` / `UNVERIFIED` / `PARTIAL` / `BLOCKED` / `INFO`). The boss reads that, cross-checks it against the worker's actual tool calls, and either reports back to you or re-prompts to verify, finish, or unblock.
45
+
46
+ A few things make it feel like one conversation instead of N:
47
+
48
+ - **Live worker state** is appended to every event the boss receives. It can never forget that "B is still working" while it's reading "A finished".
49
+ - **Auto-chain.** If the boss leaves a project parked while pending tasks remain, the orchestrator dispatches the next task itself and tells the boss it did so.
50
+ - **Auto-compact.** When the boss's context crosses 80%, it compacts and starts a fresh session file so `arcena continue` resumes the trimmed history.
51
+ - **Crash-resistant.** Six workers in one process can't take the boss down β€” uncaught throws and unhandled rejections are logged to `~/.gg/boss/debug.log` and the run loop keeps going.
52
+ - **Audio chimes.** A done sound on each worker finish, an all-clear chime when every worker is idle and the queue is empty.
53
+
54
+ ---
55
+
56
+ ## πŸŽ› Models
57
+
58
+ Boss and workers run on **different models, on purpose**. Use a strong reasoning model (Opus, GPT-5) up top and a fast cheap model (Sonnet, Haiku) for the workers β€” or whatever combination fits the work.
59
+
60
+ Defaults: `claude-opus-4-7` for the boss, `claude-sonnet-4-6` for the workers. Anthropic, OpenAI, GLM, and Moonshot are all supported (anything `arcicoder` supports). Swap mid-session with `/model-boss` and `/model-workers` β€” your choice persists across restarts.
61
+
62
+ ```bash
63
+ arcena --boss-model claude-opus-4-7 --worker-model claude-sonnet-4-6
64
+ arcena --project ../api --project ../web # explicit project list
65
+ ```
66
+
67
+ ---
68
+
69
+ ## ⌨️ Keybindings
70
+
71
+ | Key | What it does |
72
+ |---|---|
73
+ | <kbd>Tab</kbd> | Cycle the project scope pill (All / per-project) on your next message |
74
+ | <kbd>Shift+Tab</kbd> | Toggle the boss's extended thinking |
75
+ | <kbd>Esc</kbd> | Interrupt the boss mid-turn (workers keep running) |
76
+ | <kbd>Ctrl+T</kbd> | Open the Tasks pane |
77
+ | <kbd>Ctrl+C</kbd> Γ—2 | Exit arcena |
78
+ | <kbd>↑</kbd> / <kbd>↓</kbd> | Recall previous prompts (when input is empty) |
79
+ | <kbd>Enter</kbd> | Send Β· <kbd>Shift+Enter</kbd> newline Β· `/` opens the slash menu |
80
+
81
+ Inside the **Tasks pane** (<kbd>Ctrl+T</kbd>):
82
+
83
+ | Key | What it does |
84
+ |---|---|
85
+ | <kbd>↑</kbd> / <kbd>↓</kbd> (or <kbd>k</kbd> / <kbd>j</kbd>) | Navigate tasks |
86
+ | <kbd>Enter</kbd> | Dispatch the selected task to its worker |
87
+ | <kbd>r</kbd> | Run all pending and blocked tasks across idle workers |
88
+ | <kbd>d</kbd> | Delete the selected task |
89
+ | <kbd>Esc</kbd> | Close the pane |
90
+
91
+ ---
92
+
93
+ ## πŸ’¬ Slash commands
94
+
95
+ | Command | What it does |
96
+ |---|---|
97
+ | `/help` (`/?`) | Show all commands and keybindings |
98
+ | `/model-boss` | Switch the orchestrator's model |
99
+ | `/model-workers` | Switch every worker's model |
100
+ | `/compact` | Compact the boss's context now |
101
+ | `/clear` | Clear chat history and terminal |
102
+ | `/radio` | Stream a free internet radio station while you work |
103
+ | `/quit` (`/q`, `/exit`) | Exit arcena |
104
+
105
+ ---
106
+
107
+ ## πŸ“‹ The task plan
108
+
109
+ The boss isn't just a dispatcher β€” it keeps a persistent backlog. Use it for tracked, reviewable, resumable work.
110
+
111
+ - The boss adds tasks via `add_task(project, title, description, fresh?)`.
112
+ - Tasks live in `~/.gg/boss/tasks.json` and survive restarts.
113
+ - Press <kbd>Ctrl+T</kbd> any time to see the plan, dispatch an item, or delete it.
114
+ - Worker self-reported status (`DONE` / `UNVERIFIED` / `PARTIAL` / `BLOCKED` / `INFO`) auto-updates the task, with the boss free to override based on cross-check.
115
+ - When a project goes idle with pending work in the plan, **auto-chain** picks up the next task without the boss having to remember.
116
+
117
+ Direct dispatch (`prompt_worker`) is for one-shot work. The plan is for batches you want to curate, review, and resume.
118
+
119
+ ---
120
+
121
+ ## πŸ“» Radio
122
+
123
+ `/radio` streams long-running, royalty-free internet radio while you work β€” SomaFM Groove Salad, Drone Zone, Radio Paradise Mellow Mix, lofi beats. Pick a station or `Off`. Requires one of `mpv` (recommended), `ffplay`, `mpg123`, or `vlc/cvlc` on your `PATH`.
124
+
125
+ ---
126
+
127
+ ## πŸ—‚ Project discovery
128
+
129
+ `arcena link` is interactive. It scans:
130
+
131
+ - `~/.gg/sessions/` β€” your existing **arcicoder** projects
132
+ - `~/.claude/projects/` β€” your **Claude Code** projects (cwds extracted from the JSONL events themselves, not the lossy dir-name encoding)
133
+ - `~/.codex/sessions/` β€” your **Codex** projects (cwds pulled from session metadata)
134
+
135
+ Sorted most-recent first. Pick a few, save the list, and the boss starts a worker for each one.
136
+
137
+ ---
138
+
139
+ ## πŸ›Ÿ Auto-update
140
+
141
+ On every launch the boss installs any pending update from the prior run (effective next launch) and schedules a fresh registry check in the background. No prompts, no interruption β€” you just stay current.
142
+
143
+ ---
144
+
145
+ ## πŸ“„ License
146
+
147
+ MIT
148
+
149
+ ---
150
+
151
+ <p align="center">
152
+ <strong>Talk to the boss. The workers do the rest.</strong>
153
+ </p>
154
+
155
+ <p align="center">
156
+ <a href="https://www.npmjs.com/package/@iroaxel/arcena"><img src="https://img.shields.io/badge/Install-npm%20i%20--g%20%40iroaxel%2Farcena-blue?style=for-the-badge" alt="Install"></a>
157
+ </p>
@@ -0,0 +1,358 @@
1
+ import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+ import {
3
+ DEFAULT_INGEST_URL,
4
+ install,
5
+ isInstallProbeFingerprint,
6
+ source_default,
7
+ verifyInstall
8
+ } from "./chunk-YKKUCYNE.js";
9
+ import {
10
+ init_esm_shims
11
+ } from "./chunk-YNWFCUMR.js";
12
+
13
+ // ../ggcoder/dist/core/pixel.js
14
+ init_esm_shims();
15
+ import { readFileSync, existsSync } from "fs";
16
+ import { homedir } from "os";
17
+ import { join } from "path";
18
+ async function fetchPixelEntries(opts = {}) {
19
+ const home = opts.homeDir ?? homedir();
20
+ const path = join(home, ".gg", "projects.json");
21
+ const fetchFn = opts.fetchFn ?? fetch;
22
+ if (!existsSync(path))
23
+ return { entries: [], unreachable: [], unmanaged: [], hasProjects: false };
24
+ let map;
25
+ try {
26
+ map = JSON.parse(readFileSync(path, "utf8"));
27
+ } catch {
28
+ return { entries: [], unreachable: [], unmanaged: [], hasProjects: false };
29
+ }
30
+ const projectIds = Object.keys(map);
31
+ if (projectIds.length === 0)
32
+ return { entries: [], unreachable: [], unmanaged: [], hasProjects: false };
33
+ const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\/+$/, "");
34
+ const entries = [];
35
+ const unreachable = [];
36
+ const unmanaged = [];
37
+ for (const id of projectIds) {
38
+ const project = map[id];
39
+ if (!project)
40
+ continue;
41
+ if (!project.secret) {
42
+ unmanaged.push(project.name);
43
+ continue;
44
+ }
45
+ try {
46
+ const res = await fetchFn(`${ingestUrl}/api/projects/${id}/errors`, {
47
+ headers: { authorization: `Bearer ${project.secret}` }
48
+ });
49
+ if (!res.ok) {
50
+ unreachable.push(project.name);
51
+ continue;
52
+ }
53
+ const body = await res.json();
54
+ for (const err of body.errors) {
55
+ if (err.status === "merged")
56
+ continue;
57
+ if (isInstallProbeFingerprint(err.fingerprint))
58
+ continue;
59
+ entries.push({
60
+ errorId: err.id,
61
+ projectId: id,
62
+ projectName: project.name,
63
+ projectPath: project.path,
64
+ status: err.status,
65
+ type: err.type ?? "Error",
66
+ message: (err.message ?? "").trim(),
67
+ occurrences: err.occurrences,
68
+ recurrenceCount: err.recurrence_count,
69
+ location: deriveLocation(err.stack, project.path),
70
+ branch: err.branch,
71
+ lastSeenAt: err.last_seen_at
72
+ });
73
+ }
74
+ } catch {
75
+ unreachable.push(project.name);
76
+ }
77
+ }
78
+ const statusOrder = {
79
+ failed: 0,
80
+ open: 1,
81
+ in_progress: 2,
82
+ awaiting_review: 3
83
+ };
84
+ const grouped = /* @__PURE__ */ new Map();
85
+ for (const e of entries) {
86
+ if (!grouped.has(e.projectName))
87
+ grouped.set(e.projectName, []);
88
+ grouped.get(e.projectName).push(e);
89
+ }
90
+ const sorted = [];
91
+ const projectNames = [...grouped.keys()].sort();
92
+ for (const name of projectNames) {
93
+ const group = grouped.get(name);
94
+ group.sort((a, b) => {
95
+ const ord = (statusOrder[a.status] ?? 99) - (statusOrder[b.status] ?? 99);
96
+ if (ord !== 0)
97
+ return ord;
98
+ if (a.recurrenceCount !== b.recurrenceCount)
99
+ return b.recurrenceCount - a.recurrenceCount;
100
+ return b.occurrences - a.occurrences;
101
+ });
102
+ sorted.push(...group);
103
+ }
104
+ return { entries: sorted, unreachable, unmanaged, hasProjects: true };
105
+ }
106
+ function deriveLocation(stack, projectPath) {
107
+ if (!stack)
108
+ return "unknown";
109
+ try {
110
+ const parsed = JSON.parse(stack);
111
+ if (Array.isArray(parsed)) {
112
+ const top = parsed.find((f) => typeof f === "object" && f !== null && "file" in f && "line" in f && "in_app" in f && f.in_app === true) ?? parsed[0];
113
+ if (top && top.file) {
114
+ const rel = relativizeFile(top.file, projectPath);
115
+ return `${rel}:${top.line ?? "?"}`;
116
+ }
117
+ }
118
+ } catch {
119
+ }
120
+ return "unknown";
121
+ }
122
+ function relativizeFile(file, projectPath) {
123
+ let f = file;
124
+ if (f.startsWith("file://"))
125
+ f = f.slice("file://".length);
126
+ if (projectPath && f.startsWith(projectPath + "/"))
127
+ f = f.slice(projectPath.length + 1);
128
+ return f;
129
+ }
130
+ async function listAllErrors(opts = {}) {
131
+ const home = opts.homeDir ?? homedir();
132
+ const path = join(home, ".gg", "projects.json");
133
+ const fetchFn = opts.fetchFn ?? fetch;
134
+ if (!existsSync(path)) {
135
+ printNoProjects();
136
+ return;
137
+ }
138
+ let map;
139
+ try {
140
+ map = JSON.parse(readFileSync(path, "utf8"));
141
+ } catch {
142
+ console.error(source_default.red(`\u2717 ${path} is not valid JSON.`));
143
+ process.exitCode = 1;
144
+ return;
145
+ }
146
+ const projectIds = Object.keys(map);
147
+ if (projectIds.length === 0) {
148
+ printNoProjects();
149
+ return;
150
+ }
151
+ const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\/+$/, "");
152
+ let totalOpen = 0;
153
+ let totalAwaiting = 0;
154
+ let totalInProgress = 0;
155
+ let totalFailed = 0;
156
+ for (const id of projectIds) {
157
+ const project = map[id];
158
+ if (!project)
159
+ continue;
160
+ const url = `${ingestUrl}/api/projects/${id}/errors`;
161
+ if (!project.secret) {
162
+ console.log(source_default.hex("#fbbf24")(`\u26A0 ${project.name}: missing bearer secret \u2014 re-run \`arcicoder pixel install\` to refresh management access`));
163
+ continue;
164
+ }
165
+ let body;
166
+ try {
167
+ const res = await fetchFn(url, {
168
+ headers: { authorization: `Bearer ${project.secret}` }
169
+ });
170
+ if (!res.ok) {
171
+ console.log(source_default.red(`\u2717 ${project.name}: failed to fetch (${res.status})`) + source_default.dim(` ${url}`));
172
+ continue;
173
+ }
174
+ body = await res.json();
175
+ } catch (err) {
176
+ console.log(source_default.red(`\u2717 ${project.name}: ${err instanceof Error ? err.message : String(err)}`));
177
+ continue;
178
+ }
179
+ const errors = body.errors.filter((e) => e.status !== "merged" && !isInstallProbeFingerprint(e.fingerprint));
180
+ if (errors.length === 0) {
181
+ console.log(source_default.hex("#4ade80")(`\u2713 ${project.name}`) + source_default.dim(" no open errors"));
182
+ continue;
183
+ }
184
+ console.log("");
185
+ console.log(source_default.hex("#a78bfa").bold(`\u25BE ${project.name}`) + source_default.dim(` ${project.path}`));
186
+ for (const err of errors) {
187
+ switch (err.status) {
188
+ case "open":
189
+ totalOpen++;
190
+ break;
191
+ case "in_progress":
192
+ totalInProgress++;
193
+ break;
194
+ case "awaiting_review":
195
+ totalAwaiting++;
196
+ break;
197
+ case "failed":
198
+ totalFailed++;
199
+ break;
200
+ }
201
+ printError(err);
202
+ }
203
+ }
204
+ printSummary(totalOpen, totalInProgress, totalAwaiting, totalFailed, projectIds.length);
205
+ }
206
+ function printError(err) {
207
+ const stack = parseStack(err.stack);
208
+ const topInApp = stack.find((f) => f.in_app) ?? stack[0];
209
+ const loc = topInApp ? `${topInApp.file}:${topInApp.line}` : "unknown location";
210
+ const statusBadge = badgeFor(err.status);
211
+ const message = (err.message ?? "").trim().slice(0, 100);
212
+ const recurrence = err.recurrence_count > 0 ? source_default.hex("#fbbf24")(` \u21BB${err.recurrence_count}`) : "";
213
+ console.log(" " + statusBadge + " " + source_default.bold(err.type ?? "Error") + source_default.dim(` \xD7${err.occurrences}`) + recurrence);
214
+ if (message)
215
+ console.log(" " + source_default.hex("#cbd5e1")(message));
216
+ console.log(" " + source_default.dim(loc));
217
+ if (err.branch)
218
+ console.log(" " + source_default.dim(`branch: ${err.branch}`));
219
+ }
220
+ function badgeFor(status) {
221
+ const labels = {
222
+ open: source_default.bgHex("#dc2626").white(" OPEN "),
223
+ in_progress: source_default.bgHex("#2563eb").white(" WORKING "),
224
+ awaiting_review: source_default.bgHex("#eab308").black(" REVIEW "),
225
+ failed: source_default.bgHex("#7f1d1d").white(" FAILED ")
226
+ };
227
+ return labels[status] ?? source_default.bgHex("#374151").white(` ${status.toUpperCase()} `);
228
+ }
229
+ function parseStack(raw) {
230
+ if (!raw)
231
+ return [];
232
+ try {
233
+ const parsed = JSON.parse(raw);
234
+ if (Array.isArray(parsed)) {
235
+ return parsed.filter((f) => typeof f === "object" && f !== null && "file" in f && "line" in f && "in_app" in f);
236
+ }
237
+ } catch {
238
+ }
239
+ return [];
240
+ }
241
+ function printNoProjects() {
242
+ console.log("");
243
+ console.log(source_default.dim("No projects registered yet."));
244
+ console.log("");
245
+ console.log("Run " + source_default.hex("#60a5fa").bold("arcicoder pixel install") + " inside any project to wire it up.");
246
+ console.log("");
247
+ }
248
+ function printSummary(open, inProgress, awaiting, failed, projectCount) {
249
+ const total = open + inProgress + awaiting + failed;
250
+ console.log("");
251
+ if (total === 0) {
252
+ console.log(source_default.hex("#4ade80")(`All clean across ${plural(projectCount, "project")}.`));
253
+ console.log("");
254
+ return;
255
+ }
256
+ const parts = [];
257
+ if (open)
258
+ parts.push(source_default.hex("#ef4444")(`${open} open`));
259
+ if (inProgress)
260
+ parts.push(source_default.hex("#60a5fa")(`${inProgress} working`));
261
+ if (awaiting)
262
+ parts.push(source_default.hex("#eab308")(`${awaiting} awaiting review`));
263
+ if (failed)
264
+ parts.push(source_default.hex("#7f1d1d")(`${failed} failed`));
265
+ console.log(parts.join(source_default.dim(" \xB7 ")) + source_default.dim(` across ${plural(projectCount, "project")}`));
266
+ console.log("");
267
+ }
268
+ function plural(n, word) {
269
+ return `${n} ${word}${n === 1 ? "" : "s"}`;
270
+ }
271
+ async function runPixelInstall(opts) {
272
+ const result = await install({
273
+ ingestUrl: opts.ingestUrl,
274
+ projectName: opts.name,
275
+ skipPackageInstall: opts.skipPackageInstall
276
+ });
277
+ console.log("");
278
+ console.log(source_default.hex("#4ade80").bold(result.reused ? "Pixel re-wired (existing project)." : "Pixel installed."));
279
+ console.log(source_default.dim(` Project: `) + result.projectName + source_default.dim(` (${result.projectId})`));
280
+ console.log(source_default.dim(` Kind: `) + result.projectKind);
281
+ console.log(source_default.dim(` Init file: `) + result.initFilePath);
282
+ console.log(source_default.dim(` Env file: `) + result.envFilePath);
283
+ console.log(source_default.dim(` Mapping: `) + result.projectsJsonPath);
284
+ switch (result.entryWiring.kind) {
285
+ case "injected":
286
+ console.log(source_default.dim(` Wired: `) + result.entryWiring.entryPath);
287
+ break;
288
+ case "already_present":
289
+ console.log(source_default.dim(` Entry: `) + result.entryWiring.entryPath + source_default.dim(" (already wired)"));
290
+ break;
291
+ case "no_entry_found":
292
+ console.log(source_default.hex("#fbbf24")(` \u26A0 Could not auto-detect your entry file.`));
293
+ console.log(source_default.dim(` Add to the TOP of your entry: `));
294
+ console.log(" " + source_default.hex("#60a5fa")(`import "./gg-pixel.init.mjs";`));
295
+ break;
296
+ case "skipped":
297
+ console.log(source_default.hex("#fbbf24")(` \u26A0 Entry wiring skipped: ${result.entryWiring.reason}`));
298
+ break;
299
+ }
300
+ if (!result.packageInstalled && !opts.skipPackageInstall) {
301
+ console.log(source_default.hex("#fbbf24")(` \u26A0 Package install via ${result.packageManager} failed. Run it manually.`));
302
+ }
303
+ if (result.secondaryInit) {
304
+ console.log(source_default.dim(` Also wrote: `) + result.secondaryInit.path);
305
+ console.log(source_default.dim(` `) + source_default.dim(result.secondaryInit.description));
306
+ }
307
+ for (const w of result.warnings) {
308
+ console.log(source_default.hex("#fbbf24")(` \u26A0 ${w}`));
309
+ }
310
+ console.log("");
311
+ await runVerification(result, opts.ingestUrl);
312
+ console.log("");
313
+ }
314
+ async function runVerification(result, ingestUrl) {
315
+ if (!canVerify(result.projectKind)) {
316
+ console.log(source_default.dim(" Verification skipped \u2014 not implemented for ") + result.projectKind);
317
+ return;
318
+ }
319
+ console.log(source_default.dim(" Verifying install\u2026"));
320
+ const ingest = (ingestUrl ?? DEFAULT_INGEST_URL).replace(/\/+$/, "");
321
+ let outcome;
322
+ try {
323
+ outcome = await verifyInstall({
324
+ projectId: result.projectId,
325
+ projectKey: result.projectKey,
326
+ projectSecret: result.projectSecret,
327
+ ingestUrl: ingest,
328
+ projectRoot: result.projectRoot,
329
+ // React Native's runtime isn't Node, so don't try to spawn a Node child
330
+ // there β€” but still attempt direct ingest so we at least confirm the
331
+ // server side of the wiring.
332
+ skipChildProbe: result.projectKind === "react-native"
333
+ });
334
+ } catch (err) {
335
+ console.log(source_default.hex("#ef4444")(` \u2717 Verification crashed: ${err instanceof Error ? err.message : String(err)}`));
336
+ return;
337
+ }
338
+ if (outcome.kind === "ok") {
339
+ const via = outcome.method === "child_process" ? "via spawned probe" : "via direct ingest";
340
+ console.log(source_default.hex("#4ade80")(` \u2713 Pixel verified end-to-end`) + source_default.dim(` (${outcome.latencyMs}ms ${via})`));
341
+ } else {
342
+ console.log(source_default.hex("#ef4444")(` \u2717 Verification failed: ${outcome.reason}`));
343
+ if (outcome.hint) {
344
+ console.log(source_default.dim(` hint: ${outcome.hint}`));
345
+ }
346
+ console.log(source_default.dim(` The install files are written, but no event arrived at the backend. Inspect the project's runtime to see why.`));
347
+ }
348
+ }
349
+ function canVerify(kind) {
350
+ return kind !== "python" && kind !== "go" && kind !== "ruby";
351
+ }
352
+
353
+ export {
354
+ fetchPixelEntries,
355
+ listAllErrors,
356
+ runPixelInstall
357
+ };
358
+ //# sourceMappingURL=chunk-KZJPLEZU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../ggcoder/src/core/pixel.ts"],"sourcesContent":["import { readFileSync, existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n DEFAULT_INGEST_URL,\n install,\n isInstallProbeFingerprint,\n verifyInstall,\n type VerifyOutcome,\n} from \"@iroaxel/gg-pixel\";\n\ninterface ProjectMapping {\n name: string;\n path: string;\n /** Bearer secret for /api/* calls. Missing on legacy entries β€” those projects\n * can't be queried until they're re-installed. */\n secret?: string;\n}\n\ninterface ErrorRow {\n id: string;\n fingerprint: string;\n status: string;\n type: string | null;\n message: string | null;\n stack: string | null;\n occurrences: number;\n recurrence_count: number;\n last_seen_at: number;\n branch: string | null;\n}\n\ninterface ListOptions {\n ingestUrl?: string;\n homeDir?: string;\n fetchFn?: typeof fetch;\n}\n\nexport interface PixelEntry {\n errorId: string;\n projectId: string;\n projectName: string;\n projectPath: string;\n status: string;\n type: string;\n message: string;\n occurrences: number;\n recurrenceCount: number;\n location: string;\n branch: string | null;\n lastSeenAt?: number;\n}\n\nexport interface PixelFetchResult {\n entries: PixelEntry[];\n unreachable: string[];\n /** Project names that exist in projects.json but are missing the bearer\n * secret β€” they need to be re-installed before they can be managed. */\n unmanaged: string[];\n hasProjects: boolean;\n}\n\nexport async function fetchPixelEntries(opts: ListOptions = {}): Promise<PixelFetchResult> {\n const home = opts.homeDir ?? homedir();\n const path = join(home, \".gg\", \"projects.json\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n if (!existsSync(path)) return { entries: [], unreachable: [], unmanaged: [], hasProjects: false };\n\n let map: Record<string, ProjectMapping>;\n try {\n map = JSON.parse(readFileSync(path, \"utf8\")) as Record<string, ProjectMapping>;\n } catch {\n return { entries: [], unreachable: [], unmanaged: [], hasProjects: false };\n }\n\n const projectIds = Object.keys(map);\n if (projectIds.length === 0)\n return { entries: [], unreachable: [], unmanaged: [], hasProjects: false };\n\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n const entries: PixelEntry[] = [];\n const unreachable: string[] = [];\n const unmanaged: string[] = [];\n\n for (const id of projectIds) {\n const project = map[id];\n if (!project) continue;\n if (!project.secret) {\n unmanaged.push(project.name);\n continue;\n }\n try {\n const res = await fetchFn(`${ingestUrl}/api/projects/${id}/errors`, {\n headers: { authorization: `Bearer ${project.secret}` },\n });\n if (!res.ok) {\n unreachable.push(project.name);\n continue;\n }\n const body = (await res.json()) as { errors: ErrorRow[] };\n for (const err of body.errors) {\n if (err.status === \"merged\") continue;\n // Hide install-verification probes from the overlay even if the\n // probe-cleanup DELETE didn't land (network blip, etc.).\n if (isInstallProbeFingerprint(err.fingerprint)) continue;\n entries.push({\n errorId: err.id,\n projectId: id,\n projectName: project.name,\n projectPath: project.path,\n status: err.status,\n type: err.type ?? \"Error\",\n message: (err.message ?? \"\").trim(),\n occurrences: err.occurrences,\n recurrenceCount: err.recurrence_count,\n location: deriveLocation(err.stack, project.path),\n branch: err.branch,\n lastSeenAt: err.last_seen_at,\n });\n }\n } catch {\n unreachable.push(project.name);\n }\n }\n\n // Group by project name; within project, order by status priority then count.\n const statusOrder: Record<string, number> = {\n failed: 0,\n open: 1,\n in_progress: 2,\n awaiting_review: 3,\n };\n const grouped = new Map<string, PixelEntry[]>();\n for (const e of entries) {\n if (!grouped.has(e.projectName)) grouped.set(e.projectName, []);\n grouped.get(e.projectName)!.push(e);\n }\n const sorted: PixelEntry[] = [];\n const projectNames = [...grouped.keys()].sort();\n for (const name of projectNames) {\n const group = grouped.get(name)!;\n group.sort((a, b) => {\n const ord = (statusOrder[a.status] ?? 99) - (statusOrder[b.status] ?? 99);\n if (ord !== 0) return ord;\n if (a.recurrenceCount !== b.recurrenceCount) return b.recurrenceCount - a.recurrenceCount;\n return b.occurrences - a.occurrences;\n });\n sorted.push(...group);\n }\n\n return { entries: sorted, unreachable, unmanaged, hasProjects: true };\n}\n\nfunction deriveLocation(stack: string | null, projectPath?: string): string {\n if (!stack) return \"unknown\";\n try {\n const parsed = JSON.parse(stack) as unknown;\n if (Array.isArray(parsed)) {\n const top =\n parsed.find(\n (f): f is { file: string; line: number; in_app: boolean } =>\n typeof f === \"object\" &&\n f !== null &&\n \"file\" in f &&\n \"line\" in f &&\n \"in_app\" in f &&\n (f as { in_app: boolean }).in_app === true,\n ) ?? (parsed[0] as { file?: string; line?: number } | undefined);\n if (top && top.file) {\n const rel = relativizeFile(top.file, projectPath);\n return `${rel}:${top.line ?? \"?\"}`;\n }\n }\n } catch {\n // ignore\n }\n return \"unknown\";\n}\n\nfunction relativizeFile(file: string, projectPath?: string): string {\n let f = file;\n if (f.startsWith(\"file://\")) f = f.slice(\"file://\".length);\n if (projectPath && f.startsWith(projectPath + \"/\")) f = f.slice(projectPath.length + 1);\n return f;\n}\n\nexport async function listAllErrors(opts: ListOptions = {}): Promise<void> {\n const home = opts.homeDir ?? homedir();\n const path = join(home, \".gg\", \"projects.json\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n if (!existsSync(path)) {\n printNoProjects();\n return;\n }\n\n let map: Record<string, ProjectMapping>;\n try {\n map = JSON.parse(readFileSync(path, \"utf8\")) as Record<string, ProjectMapping>;\n } catch {\n console.error(chalk.red(`βœ— ${path} is not valid JSON.`));\n process.exitCode = 1;\n return;\n }\n\n const projectIds = Object.keys(map);\n if (projectIds.length === 0) {\n printNoProjects();\n return;\n }\n\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n\n let totalOpen = 0;\n let totalAwaiting = 0;\n let totalInProgress = 0;\n let totalFailed = 0;\n\n for (const id of projectIds) {\n const project = map[id];\n if (!project) continue;\n const url = `${ingestUrl}/api/projects/${id}/errors`;\n\n if (!project.secret) {\n console.log(\n chalk.hex(\"#fbbf24\")(\n `⚠ ${project.name}: missing bearer secret β€” re-run \\`arcicoder pixel install\\` to refresh management access`,\n ),\n );\n continue;\n }\n\n let body: { errors: ErrorRow[] };\n try {\n const res = await fetchFn(url, {\n headers: { authorization: `Bearer ${project.secret}` },\n });\n if (!res.ok) {\n console.log(\n chalk.red(`βœ— ${project.name}: failed to fetch (${res.status})`) + chalk.dim(` ${url}`),\n );\n continue;\n }\n body = (await res.json()) as { errors: ErrorRow[] };\n } catch (err) {\n console.log(\n chalk.red(`βœ— ${project.name}: ${err instanceof Error ? err.message : String(err)}`),\n );\n continue;\n }\n\n const errors = body.errors.filter(\n (e) => e.status !== \"merged\" && !isInstallProbeFingerprint(e.fingerprint),\n );\n if (errors.length === 0) {\n console.log(chalk.hex(\"#4ade80\")(`βœ“ ${project.name}`) + chalk.dim(\" no open errors\"));\n continue;\n }\n\n console.log(\"\");\n console.log(chalk.hex(\"#a78bfa\").bold(`β–Ύ ${project.name}`) + chalk.dim(` ${project.path}`));\n\n for (const err of errors) {\n switch (err.status) {\n case \"open\":\n totalOpen++;\n break;\n case \"in_progress\":\n totalInProgress++;\n break;\n case \"awaiting_review\":\n totalAwaiting++;\n break;\n case \"failed\":\n totalFailed++;\n break;\n }\n printError(err);\n }\n }\n\n printSummary(totalOpen, totalInProgress, totalAwaiting, totalFailed, projectIds.length);\n}\n\nfunction printError(err: ErrorRow): void {\n const stack = parseStack(err.stack);\n const topInApp = stack.find((f) => f.in_app) ?? stack[0];\n const loc = topInApp ? `${topInApp.file}:${topInApp.line}` : \"unknown location\";\n\n const statusBadge = badgeFor(err.status);\n const message = (err.message ?? \"\").trim().slice(0, 100);\n const recurrence =\n err.recurrence_count > 0 ? chalk.hex(\"#fbbf24\")(` ↻${err.recurrence_count}`) : \"\";\n\n console.log(\n \" \" +\n statusBadge +\n \" \" +\n chalk.bold(err.type ?? \"Error\") +\n chalk.dim(` Γ—${err.occurrences}`) +\n recurrence,\n );\n if (message) console.log(\" \" + chalk.hex(\"#cbd5e1\")(message));\n console.log(\" \" + chalk.dim(loc));\n if (err.branch) console.log(\" \" + chalk.dim(`branch: ${err.branch}`));\n}\n\nfunction badgeFor(status: string): string {\n const labels: Record<string, string> = {\n open: chalk.bgHex(\"#dc2626\").white(\" OPEN \"),\n in_progress: chalk.bgHex(\"#2563eb\").white(\" WORKING \"),\n awaiting_review: chalk.bgHex(\"#eab308\").black(\" REVIEW \"),\n failed: chalk.bgHex(\"#7f1d1d\").white(\" FAILED \"),\n };\n return labels[status] ?? chalk.bgHex(\"#374151\").white(` ${status.toUpperCase()} `);\n}\n\nfunction parseStack(raw: string | null): Array<{ file: string; line: number; in_app: boolean }> {\n if (!raw) return [];\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (Array.isArray(parsed)) {\n return parsed.filter(\n (f): f is { file: string; line: number; in_app: boolean } =>\n typeof f === \"object\" && f !== null && \"file\" in f && \"line\" in f && \"in_app\" in f,\n );\n }\n } catch {\n // ignore\n }\n return [];\n}\n\nfunction printNoProjects(): void {\n console.log(\"\");\n console.log(chalk.dim(\"No projects registered yet.\"));\n console.log(\"\");\n console.log(\n \"Run \" +\n chalk.hex(\"#60a5fa\").bold(\"arcicoder pixel install\") +\n \" inside any project to wire it up.\",\n );\n console.log(\"\");\n}\n\nfunction printSummary(\n open: number,\n inProgress: number,\n awaiting: number,\n failed: number,\n projectCount: number,\n): void {\n const total = open + inProgress + awaiting + failed;\n console.log(\"\");\n if (total === 0) {\n console.log(chalk.hex(\"#4ade80\")(`All clean across ${plural(projectCount, \"project\")}.`));\n console.log(\"\");\n return;\n }\n const parts: string[] = [];\n if (open) parts.push(chalk.hex(\"#ef4444\")(`${open} open`));\n if (inProgress) parts.push(chalk.hex(\"#60a5fa\")(`${inProgress} working`));\n if (awaiting) parts.push(chalk.hex(\"#eab308\")(`${awaiting} awaiting review`));\n if (failed) parts.push(chalk.hex(\"#7f1d1d\")(`${failed} failed`));\n console.log(\n parts.join(chalk.dim(\" Β· \")) + chalk.dim(` across ${plural(projectCount, \"project\")}`),\n );\n console.log(\"\");\n}\n\nfunction plural(n: number, word: string): string {\n return `${n} ${word}${n === 1 ? \"\" : \"s\"}`;\n}\n\ninterface InstallCliOptions {\n ingestUrl?: string;\n name?: string;\n skipPackageInstall: boolean;\n}\n\nexport async function runPixelInstall(opts: InstallCliOptions): Promise<void> {\n const result = await install({\n ingestUrl: opts.ingestUrl,\n projectName: opts.name,\n skipPackageInstall: opts.skipPackageInstall,\n });\n\n console.log(\"\");\n console.log(\n chalk\n .hex(\"#4ade80\")\n .bold(result.reused ? \"Pixel re-wired (existing project).\" : \"Pixel installed.\"),\n );\n console.log(\n chalk.dim(` Project: `) + result.projectName + chalk.dim(` (${result.projectId})`),\n );\n console.log(chalk.dim(` Kind: `) + result.projectKind);\n console.log(chalk.dim(` Init file: `) + result.initFilePath);\n console.log(chalk.dim(` Env file: `) + result.envFilePath);\n console.log(chalk.dim(` Mapping: `) + result.projectsJsonPath);\n switch (result.entryWiring.kind) {\n case \"injected\":\n console.log(chalk.dim(` Wired: `) + result.entryWiring.entryPath);\n break;\n case \"already_present\":\n console.log(\n chalk.dim(` Entry: `) + result.entryWiring.entryPath + chalk.dim(\" (already wired)\"),\n );\n break;\n case \"no_entry_found\":\n console.log(chalk.hex(\"#fbbf24\")(` ⚠ Could not auto-detect your entry file.`));\n console.log(chalk.dim(` Add to the TOP of your entry: `));\n console.log(\" \" + chalk.hex(\"#60a5fa\")(`import \"./gg-pixel.init.mjs\";`));\n break;\n case \"skipped\":\n console.log(chalk.hex(\"#fbbf24\")(` ⚠ Entry wiring skipped: ${result.entryWiring.reason}`));\n break;\n }\n if (!result.packageInstalled && !opts.skipPackageInstall) {\n console.log(\n chalk.hex(\"#fbbf24\")(\n ` ⚠ Package install via ${result.packageManager} failed. Run it manually.`,\n ),\n );\n }\n if (result.secondaryInit) {\n console.log(chalk.dim(` Also wrote: `) + result.secondaryInit.path);\n console.log(chalk.dim(` `) + chalk.dim(result.secondaryInit.description));\n }\n for (const w of result.warnings) {\n console.log(chalk.hex(\"#fbbf24\")(` ⚠ ${w}`));\n }\n console.log(\"\");\n\n await runVerification(result, opts.ingestUrl);\n console.log(\"\");\n}\n\n/**\n * Fires a synthetic event end-to-end and waits for it to round-trip through\n * D1. Catches the silent-failure modes that wiring alone can't (stale env,\n * sandboxed renderer, missing dotenv, broken `node_modules`, etc.).\n */\nasync function runVerification(\n result: {\n projectId: string;\n projectKey: string;\n projectSecret: string;\n projectKind: string;\n projectRoot: string;\n },\n ingestUrl: string | undefined,\n): Promise<void> {\n if (!canVerify(result.projectKind)) {\n // Non-JS kinds (python/go/ruby) have their own SDKs; verification path\n // doesn't apply yet. Print a one-line note instead of leaving silence.\n console.log(chalk.dim(\" Verification skipped β€” not implemented for \") + result.projectKind);\n return;\n }\n console.log(chalk.dim(\" Verifying install…\"));\n const ingest = (ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n let outcome: VerifyOutcome;\n try {\n outcome = await verifyInstall({\n projectId: result.projectId,\n projectKey: result.projectKey,\n projectSecret: result.projectSecret,\n ingestUrl: ingest,\n projectRoot: result.projectRoot,\n // React Native's runtime isn't Node, so don't try to spawn a Node child\n // there β€” but still attempt direct ingest so we at least confirm the\n // server side of the wiring.\n skipChildProbe: result.projectKind === \"react-native\",\n });\n } catch (err) {\n console.log(\n chalk.hex(\"#ef4444\")(\n ` βœ— Verification crashed: ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n return;\n }\n\n if (outcome.kind === \"ok\") {\n const via = outcome.method === \"child_process\" ? \"via spawned probe\" : \"via direct ingest\";\n console.log(\n chalk.hex(\"#4ade80\")(` βœ“ Pixel verified end-to-end`) +\n chalk.dim(` (${outcome.latencyMs}ms ${via})`),\n );\n } else {\n console.log(chalk.hex(\"#ef4444\")(` βœ— Verification failed: ${outcome.reason}`));\n if (outcome.hint) {\n console.log(chalk.dim(` hint: ${outcome.hint}`));\n }\n console.log(\n chalk.dim(\n ` The install files are written, but no event arrived at the backend. Inspect the project's runtime to see why.`,\n ),\n );\n }\n}\n\nfunction canVerify(kind: string): boolean {\n // Python/Go/Ruby SDKs have their own probe paths; not wiring them through\n // the JS verifier yet. Everything else (browser, node, hybrid frameworks,\n // electron, even react-native) gets the round-trip check.\n return kind !== \"python\" && kind !== \"go\" && kind !== \"ruby\";\n}\n"],"mappings":"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","names":[]}