auriga-cli 1.18.4 → 1.18.5
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/dist/api-types.d.ts +21 -4
- package/dist/catalog.json +1 -1
- package/dist/state.d.ts +0 -17
- package/dist/state.js +76 -45
- package/package.json +1 -1
package/dist/api-types.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
export type ItemStatus = "installed" | "update-available" | "not-installed"
|
|
1
|
+
export type ItemStatus = "installed" | "update-available" | "not-installed"
|
|
2
|
+
/** Dual-Agent plugin where some target Agents have the plugin installed
|
|
3
|
+
* and some don't (e.g. Claude side installed, Codex side missing). Distinct
|
|
4
|
+
* from `update-available` because the action is "install on the missing
|
|
5
|
+
* side", not "upgrade to a newer version". The missing agents are
|
|
6
|
+
* enumerated in `PluginState.missingAgents`. */
|
|
7
|
+
| "partial-install";
|
|
2
8
|
/**
|
|
3
9
|
* Per-category scan scope. Each category (workflow / skills / plugins / hooks)
|
|
4
10
|
* can be independently scanned in either user scope (~/.claude/, ~/.codex/)
|
|
@@ -53,9 +59,15 @@ export interface PluginState {
|
|
|
53
59
|
* `agents.length === 2` the UI shows a BOTH badge and Apply installs to
|
|
54
60
|
* each agent in turn. Status is aggregated across all targeted agents:
|
|
55
61
|
* `installed` ⇔ all agents installed; `not-installed` ⇔ all not-installed;
|
|
56
|
-
*
|
|
57
|
-
*
|
|
62
|
+
* partial state (some installed, some not) → `partial-install`; agent-
|
|
63
|
+
* uniform version drift → `update-available`. */
|
|
58
64
|
agents: ApplyAgent[];
|
|
65
|
+
/** Agents that target this plugin but don't have it installed. Populated
|
|
66
|
+
* iff `status === "partial-install"`. Lets the UI render per-agent
|
|
67
|
+
* ✓/✗ marks and tell the user exactly which side needs `auriga-cli`
|
|
68
|
+
* to backfill. Always omitted for `installed` / `not-installed` /
|
|
69
|
+
* `update-available`. */
|
|
70
|
+
missingAgents?: ApplyAgent[];
|
|
59
71
|
currentVersion?: string;
|
|
60
72
|
expectedVersion?: string;
|
|
61
73
|
versionSource: "upstream-live" | "catalog";
|
|
@@ -80,7 +92,12 @@ export interface HookState {
|
|
|
80
92
|
observedScope?: ScanScope;
|
|
81
93
|
}
|
|
82
94
|
export interface StateWarning {
|
|
83
|
-
code: "claude-cli-missing" | "codex-cli-missing" | "marketplace-offline" | "claude-code-not-installed" | "settings-unreadable" | "skill-malformed"
|
|
95
|
+
code: "claude-cli-missing" | "codex-cli-missing" | "marketplace-offline" | "claude-code-not-installed" | "settings-unreadable" | "skill-malformed"
|
|
96
|
+
/** Project-scope CLAUDE.md (or the user-scope fallback when scanning
|
|
97
|
+
* user scope) is present but has no recognizable `# auriga Workflow (vX.Y.Z)`
|
|
98
|
+
* header. The row reports `not-installed`; install will back up the
|
|
99
|
+
* existing file to `CLAUDE.md.bak` and write ours. */
|
|
100
|
+
| "workflow-foreign-claudemd";
|
|
84
101
|
message: string;
|
|
85
102
|
}
|
|
86
103
|
export type ApplyCategory = "workflow" | "skill" | "recommended-skill" | "plugin" | "hook";
|
package/dist/catalog.json
CHANGED
package/dist/state.d.ts
CHANGED
|
@@ -71,23 +71,6 @@ export interface ScanOptions {
|
|
|
71
71
|
homeDir?: string;
|
|
72
72
|
}
|
|
73
73
|
export declare function scanState(projectRoot: string, catalog: Catalog, opts?: ScanOptions): Promise<StateReport>;
|
|
74
|
-
/**
|
|
75
|
-
* Dedupe plugins by `id`, merging dual-Agent records into a single
|
|
76
|
-
* multi-agent row. Aggregation rules:
|
|
77
|
-
*
|
|
78
|
-
* agents: union of all agent arrays for this id (claude before codex).
|
|
79
|
-
* status: installed ⇔ every agent's record is installed
|
|
80
|
-
* not-installed ⇔ every agent's record is not-installed
|
|
81
|
-
* otherwise → update-available (partial install or any agent
|
|
82
|
-
* with a pending update). One Apply covers all
|
|
83
|
-
* gaps because the handler iterates `agents`.
|
|
84
|
-
*
|
|
85
|
-
* Non-status fields (description, currentVersion, expectedVersion,
|
|
86
|
-
* versionSource) come from the first record we see. Today both sides report
|
|
87
|
-
* the same description (catalog-driven) and the same versions for any
|
|
88
|
-
* registry-pinned plugin, so this is safe; if a future divergence appears
|
|
89
|
-
* we'll need a deliberate merge policy.
|
|
90
|
-
*/
|
|
91
74
|
export declare function mergePluginsById(records: PluginState[]): PluginState[];
|
|
92
75
|
/** Default: run `claude plugins list --json` (no scope flag — the CLI
|
|
93
76
|
* doesn't expose one) plus the `--available` variant, then filter the
|
package/dist/state.js
CHANGED
|
@@ -94,31 +94,27 @@ function dirExists(p) {
|
|
|
94
94
|
return false;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Dedupe plugins by `id`, merging dual-Agent records into a single
|
|
99
|
-
* multi-agent row. Aggregation rules:
|
|
100
|
-
*
|
|
101
|
-
* agents: union of all agent arrays for this id (claude before codex).
|
|
102
|
-
* status: installed ⇔ every agent's record is installed
|
|
103
|
-
* not-installed ⇔ every agent's record is not-installed
|
|
104
|
-
* otherwise → update-available (partial install or any agent
|
|
105
|
-
* with a pending update). One Apply covers all
|
|
106
|
-
* gaps because the handler iterates `agents`.
|
|
107
|
-
*
|
|
108
|
-
* Non-status fields (description, currentVersion, expectedVersion,
|
|
109
|
-
* versionSource) come from the first record we see. Today both sides report
|
|
110
|
-
* the same description (catalog-driven) and the same versions for any
|
|
111
|
-
* registry-pinned plugin, so this is safe; if a future divergence appears
|
|
112
|
-
* we'll need a deliberate merge policy.
|
|
113
|
-
*/
|
|
114
97
|
export function mergePluginsById(records) {
|
|
115
98
|
const byId = new Map();
|
|
116
|
-
|
|
99
|
+
// Per-agent (agent, status, version) tuples preserved across the fold so
|
|
100
|
+
// the aggregation step can emit `partial-install` + `missingAgents` when
|
|
101
|
+
// one side is installed and the other isn't, AND pick the *stale* side's
|
|
102
|
+
// currentVersion when status === "update-available" (otherwise the merge
|
|
103
|
+
// inherited Claude's version, producing the misleading `vX → vX` display
|
|
104
|
+
// in the v1.18.4 verification).
|
|
105
|
+
const perAgentByIdEntries = new Map();
|
|
117
106
|
for (const rec of records) {
|
|
107
|
+
// Pre-merge records are per-agent: their `agents[]` array contains the
|
|
108
|
+
// single Agent this row was scanned for. The merge step below unions
|
|
109
|
+
// those into the final dual-Agent record.
|
|
110
|
+
const recAgent = rec.agents[0];
|
|
111
|
+
const perAgentEntry = recAgent
|
|
112
|
+
? { agent: recAgent, status: rec.status, currentVersion: rec.currentVersion }
|
|
113
|
+
: null;
|
|
118
114
|
const existing = byId.get(rec.id);
|
|
119
115
|
if (!existing) {
|
|
120
116
|
byId.set(rec.id, { ...rec });
|
|
121
|
-
|
|
117
|
+
perAgentByIdEntries.set(rec.id, perAgentEntry ? [perAgentEntry] : []);
|
|
122
118
|
continue;
|
|
123
119
|
}
|
|
124
120
|
// Union agents preserving order: existing first, then any new ones.
|
|
@@ -129,28 +125,58 @@ export function mergePluginsById(records) {
|
|
|
129
125
|
seen.add(a);
|
|
130
126
|
}
|
|
131
127
|
}
|
|
132
|
-
|
|
128
|
+
if (perAgentEntry) {
|
|
129
|
+
perAgentByIdEntries.get(rec.id).push(perAgentEntry);
|
|
130
|
+
}
|
|
133
131
|
}
|
|
134
|
-
// Fold
|
|
135
|
-
|
|
132
|
+
// Fold per-agent tuples into the aggregated status, missingAgents, and
|
|
133
|
+
// (when applicable) the corrected currentVersion.
|
|
134
|
+
for (const [id, perAgent] of perAgentByIdEntries) {
|
|
136
135
|
const rec = byId.get(id);
|
|
137
136
|
if (!rec)
|
|
138
137
|
continue;
|
|
139
|
-
|
|
138
|
+
const aggregated = aggregateStatus(perAgent);
|
|
139
|
+
rec.status = aggregated.status;
|
|
140
|
+
if (aggregated.missingAgents && aggregated.missingAgents.length > 0) {
|
|
141
|
+
rec.missingAgents = aggregated.missingAgents;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
delete rec.missingAgents;
|
|
145
|
+
}
|
|
146
|
+
// When status is update-available, surface the version of the *stale*
|
|
147
|
+
// agent (one whose own status was update-available). Otherwise we'd
|
|
148
|
+
// keep whichever agent's version was merged first — Claude's, which
|
|
149
|
+
// may already be at the expected version, producing a `vX → vX`
|
|
150
|
+
// pseudo-upgrade display.
|
|
151
|
+
if (rec.status === "update-available") {
|
|
152
|
+
const stale = perAgent.find((r) => r.status === "update-available");
|
|
153
|
+
if (stale?.currentVersion) {
|
|
154
|
+
rec.currentVersion = stale.currentVersion;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
140
157
|
}
|
|
141
158
|
return Array.from(byId.values());
|
|
142
159
|
}
|
|
143
|
-
function aggregateStatus(
|
|
144
|
-
if (
|
|
145
|
-
return "not-installed";
|
|
146
|
-
if (
|
|
147
|
-
return "installed";
|
|
148
|
-
if (
|
|
149
|
-
return "not-installed";
|
|
150
|
-
//
|
|
151
|
-
// —
|
|
152
|
-
//
|
|
153
|
-
|
|
160
|
+
function aggregateStatus(records) {
|
|
161
|
+
if (records.length === 0)
|
|
162
|
+
return { status: "not-installed" };
|
|
163
|
+
if (records.every((r) => r.status === "installed"))
|
|
164
|
+
return { status: "installed" };
|
|
165
|
+
if (records.every((r) => r.status === "not-installed"))
|
|
166
|
+
return { status: "not-installed" };
|
|
167
|
+
// Mixed. If ANY agent reports not-installed, the row is partially installed
|
|
168
|
+
// — the user-facing action is "install on the missing side". Surfaces as a
|
|
169
|
+
// distinct status from version-drift `update-available` so the UI doesn't
|
|
170
|
+
// render misleading `vX → vX` upgrades (the v1.18.4 deep-review symptom).
|
|
171
|
+
const missingAgents = records
|
|
172
|
+
.filter((r) => r.status === "not-installed")
|
|
173
|
+
.map((r) => r.agent);
|
|
174
|
+
if (missingAgents.length > 0) {
|
|
175
|
+
return { status: "partial-install", missingAgents };
|
|
176
|
+
}
|
|
177
|
+
// Otherwise version drift on at least one targeted agent — single Apply
|
|
178
|
+
// upgrades the stale side(s).
|
|
179
|
+
return { status: "update-available" };
|
|
154
180
|
}
|
|
155
181
|
// ---------------------------------------------------------------------------
|
|
156
182
|
// Workflow
|
|
@@ -160,11 +186,12 @@ function workflowPathsForScope(scope, projectRoot, home) {
|
|
|
160
186
|
if (scope === "user") {
|
|
161
187
|
return [path.join(home, ".claude", "CLAUDE.md")];
|
|
162
188
|
}
|
|
163
|
-
// Project:
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
189
|
+
// Project: only `<proj>/CLAUDE.md` — the auriga workflow installer
|
|
190
|
+
// (src/workflow.ts) writes here and never to `<proj>/.claude/CLAUDE.md`.
|
|
191
|
+
// The old fallback collapsed onto `$HOME/.claude/CLAUDE.md` when
|
|
192
|
+
// projectRoot === $HOME (user runs `web-ui` from home dir), leaking
|
|
193
|
+
// user-scope content into the project-scope row.
|
|
194
|
+
return [path.join(projectRoot, "CLAUDE.md")];
|
|
168
195
|
}
|
|
169
196
|
function scanWorkflow(scope, projectRoot, home, catalog, warnings) {
|
|
170
197
|
const expectedVersion = catalog.workflowVersion;
|
|
@@ -197,14 +224,18 @@ function scanWorkflow(scope, projectRoot, home, catalog, warnings) {
|
|
|
197
224
|
if (line.trim().length > 0)
|
|
198
225
|
break;
|
|
199
226
|
}
|
|
200
|
-
// CLAUDE.md exists but no recognizable auriga marker.
|
|
201
|
-
//
|
|
202
|
-
//
|
|
227
|
+
// CLAUDE.md exists but no recognizable auriga marker. The file is foreign
|
|
228
|
+
// — not our workflow. Report `not-installed` honestly; the install path
|
|
229
|
+
// (src/workflow.ts) already protects user content by backing it up to
|
|
230
|
+
// `CLAUDE.md.bak` before overwriting. Conflating "something exists here"
|
|
231
|
+
// with "auriga workflow installed" caused the v1.18.4 verification bug
|
|
232
|
+
// where running web-ui from `~` reported the user's `# Global`-headed
|
|
233
|
+
// `~/.claude/CLAUDE.md` as an installed workflow.
|
|
203
234
|
warnings.push({
|
|
204
|
-
code: "workflow-
|
|
205
|
-
message: `CLAUDE.md
|
|
235
|
+
code: "workflow-foreign-claudemd",
|
|
236
|
+
message: `Foreign CLAUDE.md detected at the workflow path — no auriga-workflow header. Install will back up to CLAUDE.md.bak.`,
|
|
206
237
|
});
|
|
207
|
-
return { status: "installed", expectedVersion, observedScope: scope };
|
|
238
|
+
return { status: "not-installed", expectedVersion, observedScope: scope };
|
|
208
239
|
}
|
|
209
240
|
// ---------------------------------------------------------------------------
|
|
210
241
|
// Skills + recommendedSkills
|
package/package.json
CHANGED