@moda-ai/cli 1.55.18 → 1.55.20
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/{agent-cha3kg9d.js → agent-mj622k8s.js} +9 -9
- package/dist/{cli-1exddmc0.js → cli-033n2mpb.js} +2 -2
- package/dist/{cli-c5c6f0yw.js → cli-38p87ykc.js} +1 -1
- package/dist/{cli-av3dqgj5.js → cli-4j8nffsm.js} +10 -6
- package/dist/{cli-5hq827jt.js → cli-569hj0bj.js} +1 -1
- package/dist/{cli-3ezzeqcy.js → cli-5ke3xe6y.js} +47 -3
- package/dist/{cli-eazeanvt.js → cli-7ea02wca.js} +1 -1
- package/dist/{cli-qmjnh4z9.js → cli-9x9adrtj.js} +1 -1
- package/dist/{cli-a1mv0ypm.js → cli-a5c9te95.js} +5 -5
- package/dist/cli-cehskjde.js +1302 -0
- package/dist/{cli-5q1gyvxn.js → cli-pc5cw7mx.js} +5 -5
- package/dist/{cli-c8p69n55.js → cli-rqk6f6n6.js} +2 -2
- package/dist/{cli-ssfq84k5.js → cli-sf0g0fjg.js} +133 -18
- package/dist/{cli-0e8bfvn7.js → cli-wf7gfa1e.js} +8 -8
- package/dist/cli.js +331 -930
- package/dist/{doctor-kg0yq1wf.js → doctor-mx6jf435.js} +9 -9
- package/dist/{fix-q8er8egx.js → fix-9fmy6p2x.js} +7 -7
- package/dist/{harness-github-actions-ver6cprq.js → harness-github-actions-c826bfxs.js} +6 -6
- package/dist/{harness-v9s0k9s7.js → harness-xvg6ws6x.js} +6 -6
- package/dist/{index-7zqa7t5c.js → index-ewqbpnwz.js} +13 -13
- package/dist/{production-intelligence-k36jsvqx.js → production-intelligence-dbe9dmc5.js} +3 -3
- package/dist/{profile-commands-88sdwzbg.js → profile-commands-kmmd9y86.js} +3 -3
- package/dist/prompt-source-mcp.js +6 -6
- package/dist/{prompts-2r756vtd.js → prompts-1tkhrxkq.js} +7 -7
- package/dist/{provision-n3r7yway.js → provision-wzttap58.js} +4 -4
- package/dist/{registry-5v63ga01.js → registry-atqyb5fa.js} +4 -4
- package/dist/skills-br82cpt7.js +19 -0
- package/dist/{skills-bundled-mdmhzfsr.js → skills-bundled-r9a2vs07.js} +2 -2
- package/dist/{sync-r4tncne4.js → sync-25vn78je.js} +9 -9
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +114 -1434
- package/skills/moda-cli/references/auth.md +176 -0
- package/skills/moda-cli/references/commands.md +74 -0
- package/skills/moda-cli/references/dashboard-parity.md +29 -0
- package/skills/moda-cli/references/detections.md +79 -0
- package/skills/moda-cli/references/feedback.md +45 -0
- package/skills/moda-cli/references/output-protocol.md +260 -0
- package/skills/moda-cli/references/production-intelligence.md +96 -0
- package/skills/moda-cli/references/prompts.md +104 -0
- package/skills/moda-cli/references/recipes.md +74 -0
- package/skills/moda-cli/references/replays-and-registry.md +173 -0
- package/skills/moda-cli/references/search-and-traces.md +180 -0
- package/skills/moda-cli/references/signals-and-false-positives.md +79 -0
- package/skills/moda-cli/references/troubleshooting.md +65 -0
- package/dist/cli-kg0kz05e.js +0 -496
- package/dist/skills-fed17et3.js +0 -19
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isAuthSessionValid,
|
|
3
3
|
loadAuthSession
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-9x9adrtj.js";
|
|
5
5
|
import {
|
|
6
6
|
inspectPromptManifest
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-wf7gfa1e.js";
|
|
8
8
|
import {
|
|
9
9
|
readHarnessSyncState,
|
|
10
10
|
renderDoctorHuman,
|
|
11
11
|
renderStatusHuman,
|
|
12
12
|
scanHarness
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-a5c9te95.js";
|
|
14
14
|
import {
|
|
15
15
|
callDataAPI
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-rqk6f6n6.js";
|
|
17
17
|
import {
|
|
18
18
|
ensureSecretFilePermissions,
|
|
19
19
|
getActiveProfile,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
resolveSecretReference,
|
|
28
28
|
resolveTenantId,
|
|
29
29
|
secretFilePathFromRef
|
|
30
|
-
} from "./cli-
|
|
30
|
+
} from "./cli-5ke3xe6y.js";
|
|
31
31
|
|
|
32
32
|
// src/doctor.ts
|
|
33
33
|
import { createHash } from "node:crypto";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
apiKeyHeaders
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-7ea02wca.js";
|
|
4
4
|
import {
|
|
5
5
|
recordApiRequest,
|
|
6
6
|
resolveApiKey,
|
|
7
7
|
resolveModaBaseUrl
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-5ke3xe6y.js";
|
|
9
9
|
|
|
10
10
|
// src/api-client.ts
|
|
11
11
|
var REQUEST_TIMEOUT_MS = 30000;
|
|
@@ -6,8 +6,9 @@ function packageAssetPath(...parts) {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
// src/init/rules.ts
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
11
12
|
import { confirm } from "@inquirer/prompts";
|
|
12
13
|
var SKILLS_SOURCE_DIR = packageAssetPath("skills");
|
|
13
14
|
var SKILLS = [
|
|
@@ -23,6 +24,7 @@ var ADAPTERS = {
|
|
|
23
24
|
dir: join2(".claude", "skills", skillId),
|
|
24
25
|
filename: "SKILL.md"
|
|
25
26
|
}),
|
|
27
|
+
referencesDirFor: (skillId) => join2(".claude", "skills", skillId, "references"),
|
|
26
28
|
transform: (content) => content
|
|
27
29
|
},
|
|
28
30
|
Cursor: {
|
|
@@ -31,7 +33,8 @@ var ADAPTERS = {
|
|
|
31
33
|
dir: join2(".cursor", "rules"),
|
|
32
34
|
filename: `${skillId}.mdc`
|
|
33
35
|
}),
|
|
34
|
-
|
|
36
|
+
referencesDirFor: (skillId) => join2(".cursor", "rules", `${skillId}-references`),
|
|
37
|
+
transform: (content, referencesDir) => claudeSkillToCursorRule(content).replace(/`references\//g, `\`${referencesDir}/`)
|
|
35
38
|
}
|
|
36
39
|
};
|
|
37
40
|
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;
|
|
@@ -53,24 +56,108 @@ function claudeSkillToCursorRule(skillContent) {
|
|
|
53
56
|
${body.replace(/^\s+/, "")}`;
|
|
54
57
|
}
|
|
55
58
|
function loadSkillSource(skillId) {
|
|
56
|
-
const
|
|
59
|
+
const dir = join2(SKILLS_SOURCE_DIR, skillId);
|
|
60
|
+
const path = join2(dir, "SKILL.md");
|
|
57
61
|
if (!existsSync(path)) {
|
|
58
62
|
throw new Error(`Skill source missing: ${path}`);
|
|
59
63
|
}
|
|
60
|
-
|
|
64
|
+
const references = new Map;
|
|
65
|
+
const referencesDir = join2(dir, "references");
|
|
66
|
+
if (existsSync(referencesDir)) {
|
|
67
|
+
for (const name of readdirSync(referencesDir).sort()) {
|
|
68
|
+
if (name.endsWith(".md"))
|
|
69
|
+
references.set(name, readFileSync(join2(referencesDir, name), "utf8"));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return { content: readFileSync(path, "utf8"), references };
|
|
73
|
+
}
|
|
74
|
+
var INSTALL_RECORD_PATH = join2(".moda", "agent-skills.json");
|
|
75
|
+
function sha256(text) {
|
|
76
|
+
return createHash("sha256").update(text).digest("hex");
|
|
77
|
+
}
|
|
78
|
+
function readInstallRecord() {
|
|
79
|
+
try {
|
|
80
|
+
const parsed = JSON.parse(readFileSync(join2(process.cwd(), INSTALL_RECORD_PATH), "utf8"));
|
|
81
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
82
|
+
} catch {
|
|
83
|
+
return {};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function writeInstallRecord(record) {
|
|
87
|
+
const path = join2(process.cwd(), INSTALL_RECORD_PATH);
|
|
88
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
89
|
+
writeFileSync(path, `${JSON.stringify(record, null, 2)}
|
|
90
|
+
`);
|
|
61
91
|
}
|
|
62
|
-
function
|
|
92
|
+
function skillVersion(skillContent) {
|
|
93
|
+
const frontmatter = FRONTMATTER_RE.exec(skillContent)?.[1] ?? "";
|
|
94
|
+
return /^version:\s*(\S+)\s*$/m.exec(frontmatter)?.[1] ?? "unknown";
|
|
95
|
+
}
|
|
96
|
+
function looksLikeShippedSkill(existing, skill) {
|
|
97
|
+
return existing.startsWith(`---
|
|
98
|
+
name: ${skill.id}
|
|
99
|
+
`) || /^# Moda CLI$/m.test(existing);
|
|
100
|
+
}
|
|
101
|
+
function unusedBackupPath(relativePath) {
|
|
102
|
+
let candidate = `${relativePath}.bak`;
|
|
103
|
+
for (let n = 1;existsSync(join2(process.cwd(), candidate)); n++) {
|
|
104
|
+
candidate = `${relativePath}.bak.${n}`;
|
|
105
|
+
}
|
|
106
|
+
return candidate;
|
|
107
|
+
}
|
|
108
|
+
function installSkillForAgent(skill, adapter, source, record) {
|
|
63
109
|
const { dir, filename } = adapter.targetFor(skill.id);
|
|
64
110
|
const dirPath = join2(process.cwd(), dir);
|
|
65
111
|
const filePath = join2(dirPath, filename);
|
|
66
112
|
const relativePath = join2(dir, filename);
|
|
113
|
+
const referencesDir = adapter.referencesDirFor(skill.id);
|
|
114
|
+
const content = adapter.transform(source.content, referencesDir);
|
|
67
115
|
try {
|
|
68
116
|
mkdirSync(dirPath, { recursive: true });
|
|
117
|
+
let status = "wrote";
|
|
118
|
+
let backupPath;
|
|
69
119
|
if (existsSync(filePath)) {
|
|
70
|
-
|
|
120
|
+
const existing = readFileSync(filePath, "utf8");
|
|
121
|
+
const recorded = record[relativePath];
|
|
122
|
+
if (existing === content) {
|
|
123
|
+
status = "current";
|
|
124
|
+
} else if (recorded ? recorded.sha256 === sha256(existing) : looksLikeShippedSkill(existing, skill)) {
|
|
125
|
+
if (!recorded) {
|
|
126
|
+
backupPath = unusedBackupPath(relativePath);
|
|
127
|
+
writeFileSync(join2(process.cwd(), backupPath), existing);
|
|
128
|
+
}
|
|
129
|
+
status = "updated";
|
|
130
|
+
} else {
|
|
131
|
+
return { agent: adapter.name, relativePath, status: "exists" };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (status !== "current")
|
|
135
|
+
writeFileSync(filePath, content);
|
|
136
|
+
const version = skillVersion(source.content);
|
|
137
|
+
record[relativePath] = { version, sha256: sha256(content) };
|
|
138
|
+
const referencesPath = join2(process.cwd(), referencesDir);
|
|
139
|
+
mkdirSync(referencesPath, { recursive: true });
|
|
140
|
+
const keptReferences = [];
|
|
141
|
+
for (const [name, text] of source.references) {
|
|
142
|
+
const referencePath = join2(referencesPath, name);
|
|
143
|
+
const referenceKey = join2(referencesDir, name);
|
|
144
|
+
const existing = existsSync(referencePath) ? readFileSync(referencePath, "utf8") : undefined;
|
|
145
|
+
if (existing !== text) {
|
|
146
|
+
if (existing !== undefined && record[referenceKey]?.sha256 !== sha256(existing)) {
|
|
147
|
+
keptReferences.push(referenceKey);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
writeFileSync(referencePath, text);
|
|
151
|
+
}
|
|
152
|
+
record[referenceKey] = { version, sha256: sha256(text) };
|
|
71
153
|
}
|
|
72
|
-
|
|
73
|
-
|
|
154
|
+
return {
|
|
155
|
+
agent: adapter.name,
|
|
156
|
+
relativePath,
|
|
157
|
+
status,
|
|
158
|
+
...backupPath ? { backupPath } : {},
|
|
159
|
+
...keptReferences.length > 0 ? { keptReferences } : {}
|
|
160
|
+
};
|
|
74
161
|
} catch (err) {
|
|
75
162
|
return {
|
|
76
163
|
agent: adapter.name,
|
|
@@ -103,10 +190,13 @@ async function installRules(detectedAgents, options = {}) {
|
|
|
103
190
|
let wrote = 0;
|
|
104
191
|
let skipped = 0;
|
|
105
192
|
let failed = 0;
|
|
193
|
+
let updated = 0;
|
|
194
|
+
const record = readInstallRecord();
|
|
195
|
+
const recordBefore = JSON.stringify(record);
|
|
106
196
|
for (const skill of SKILLS) {
|
|
107
|
-
let
|
|
197
|
+
let source;
|
|
108
198
|
try {
|
|
109
|
-
|
|
199
|
+
source = loadSkillSource(skill.id);
|
|
110
200
|
} catch (err) {
|
|
111
201
|
const message = err instanceof Error ? err.message : String(err);
|
|
112
202
|
console.error(` Warning: ${message}`);
|
|
@@ -114,16 +204,31 @@ async function installRules(detectedAgents, options = {}) {
|
|
|
114
204
|
continue;
|
|
115
205
|
}
|
|
116
206
|
for (const adapter of adapters) {
|
|
117
|
-
const outcome = installSkillForAgent(skill, adapter,
|
|
207
|
+
const outcome = installSkillForAgent(skill, adapter, source, record);
|
|
208
|
+
if (!options.silent) {
|
|
209
|
+
for (const kept of outcome.keptReferences ?? []) {
|
|
210
|
+
console.log(` ${outcome.agent}: ${kept} was edited locally — skipping (delete it to reinstall)`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
118
213
|
switch (outcome.status) {
|
|
119
214
|
case "wrote":
|
|
120
215
|
if (!options.silent)
|
|
121
216
|
console.log(` ${outcome.agent}: wrote ${outcome.relativePath}`);
|
|
122
217
|
wrote++;
|
|
123
218
|
break;
|
|
219
|
+
case "updated":
|
|
220
|
+
if (!options.silent) {
|
|
221
|
+
const backup = outcome.backupPath ? ` (previous copy saved to ${outcome.backupPath})` : "";
|
|
222
|
+
console.log(` ${outcome.agent}: updated ${outcome.relativePath} to the current skill${backup}`);
|
|
223
|
+
}
|
|
224
|
+
updated++;
|
|
225
|
+
break;
|
|
226
|
+
case "current":
|
|
227
|
+
skipped++;
|
|
228
|
+
break;
|
|
124
229
|
case "exists":
|
|
125
230
|
if (!options.silent) {
|
|
126
|
-
console.log(` ${outcome.agent}: ${outcome.relativePath}
|
|
231
|
+
console.log(` ${outcome.agent}: ${outcome.relativePath} was edited locally — skipping (delete it to reinstall)`);
|
|
127
232
|
}
|
|
128
233
|
skipped++;
|
|
129
234
|
break;
|
|
@@ -136,8 +241,18 @@ async function installRules(detectedAgents, options = {}) {
|
|
|
136
241
|
}
|
|
137
242
|
}
|
|
138
243
|
}
|
|
244
|
+
if (JSON.stringify(record) !== recordBefore) {
|
|
245
|
+
try {
|
|
246
|
+
writeInstallRecord(record);
|
|
247
|
+
} catch (err) {
|
|
248
|
+
if (!options.silent) {
|
|
249
|
+
console.error(` Could not save ${INSTALL_RECORD_PATH} — ${err instanceof Error ? err.message : String(err)}. ` + "A later moda init may overwrite local edits to these skill files.");
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
139
253
|
const summary = [
|
|
140
254
|
wrote && `${wrote} written`,
|
|
255
|
+
updated && `${updated} updated`,
|
|
141
256
|
skipped && `${skipped} already present`,
|
|
142
257
|
failed && `${failed} failed`
|
|
143
258
|
].filter(Boolean).join(", ");
|
|
@@ -175,13 +290,13 @@ function detectAgents() {
|
|
|
175
290
|
import {
|
|
176
291
|
existsSync as existsSync3,
|
|
177
292
|
mkdirSync as mkdirSync2,
|
|
178
|
-
readdirSync,
|
|
293
|
+
readdirSync as readdirSync2,
|
|
179
294
|
readFileSync as readFileSync2,
|
|
180
295
|
rmdirSync,
|
|
181
296
|
unlinkSync,
|
|
182
297
|
writeFileSync as writeFileSync2
|
|
183
298
|
} from "node:fs";
|
|
184
|
-
import { dirname as
|
|
299
|
+
import { dirname as dirname3, isAbsolute, join as join4, normalize, relative, resolve } from "node:path";
|
|
185
300
|
var SKILLS_MANIFEST_PATH = join4(".moda", "skills.yml");
|
|
186
301
|
var SKILL_SOURCE_HARNESS = "moda";
|
|
187
302
|
var SKILL_SOURCE_INTEGRATION_BUNDLED = "integration-bundled";
|
|
@@ -241,7 +356,7 @@ function writeSkillsManifest(cwd, header, records) {
|
|
|
241
356
|
]),
|
|
242
357
|
""
|
|
243
358
|
];
|
|
244
|
-
mkdirSync2(
|
|
359
|
+
mkdirSync2(dirname3(manifestPath), { recursive: true });
|
|
245
360
|
writeFileSync2(manifestPath, lines.join(`
|
|
246
361
|
`));
|
|
247
362
|
}
|
|
@@ -272,9 +387,9 @@ function pruneManagedSkillPaths(cwd, managedPaths, log) {
|
|
|
272
387
|
function pruneEmptyClaudeSkillDir(cwd, relativePath) {
|
|
273
388
|
if (!relativePath.startsWith(".claude/skills/") || !relativePath.endsWith("/SKILL.md"))
|
|
274
389
|
return;
|
|
275
|
-
const dir =
|
|
390
|
+
const dir = dirname3(join4(cwd, relativePath));
|
|
276
391
|
try {
|
|
277
|
-
if (existsSync3(dir) &&
|
|
392
|
+
if (existsSync3(dir) && readdirSync2(dir).length === 0) {
|
|
278
393
|
rmdirSync(dir);
|
|
279
394
|
}
|
|
280
395
|
} catch {}
|
|
@@ -12,28 +12,28 @@ import {
|
|
|
12
12
|
require_typescript,
|
|
13
13
|
resolvePromptSource,
|
|
14
14
|
safePromptEvidencePath
|
|
15
|
-
} from "./cli-
|
|
15
|
+
} from "./cli-a5c9te95.js";
|
|
16
16
|
import {
|
|
17
17
|
createCommandContext
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-569hj0bj.js";
|
|
19
19
|
import {
|
|
20
20
|
assertFlags,
|
|
21
21
|
assertPositionals
|
|
22
|
-
} from "./cli-
|
|
22
|
+
} from "./cli-cehskjde.js";
|
|
23
23
|
import {
|
|
24
24
|
callControlAPI,
|
|
25
25
|
callDataAPI
|
|
26
|
-
} from "./cli-
|
|
26
|
+
} from "./cli-rqk6f6n6.js";
|
|
27
27
|
import {
|
|
28
28
|
setPlatformTenantOverride
|
|
29
|
-
} from "./cli-
|
|
29
|
+
} from "./cli-7ea02wca.js";
|
|
30
30
|
import {
|
|
31
31
|
CliInputError,
|
|
32
32
|
EXIT_ERROR,
|
|
33
33
|
EXIT_OK,
|
|
34
34
|
resolveApiTenantId,
|
|
35
35
|
validateConfig
|
|
36
|
-
} from "./cli-
|
|
36
|
+
} from "./cli-5ke3xe6y.js";
|
|
37
37
|
import {
|
|
38
38
|
__commonJS,
|
|
39
39
|
__require,
|
|
@@ -6731,7 +6731,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
|
|
|
6731
6731
|
const analyzedDefinitions = new Map;
|
|
6732
6732
|
if (flags["no-analyze"] !== "true") {
|
|
6733
6733
|
options.onProgress?.("Analyzing prompt sources before sync.");
|
|
6734
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
6734
|
+
const { analyzeHarnessPrompts } = await import("./harness-xvg6ws6x.js");
|
|
6735
6735
|
const result = await analyzeHarnessPrompts({
|
|
6736
6736
|
rootDir: process.cwd(),
|
|
6737
6737
|
existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
|
|
@@ -7061,7 +7061,7 @@ async function migratePromptManifest(options = {}) {
|
|
|
7061
7061
|
let addedSources = [];
|
|
7062
7062
|
let pendingSources = [];
|
|
7063
7063
|
if (options.discover) {
|
|
7064
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
7064
|
+
const { analyzeHarnessPrompts } = await import("./harness-xvg6ws6x.js");
|
|
7065
7065
|
const result = await analyzeHarnessPrompts({
|
|
7066
7066
|
rootDir: root,
|
|
7067
7067
|
existing: manifest.sources,
|