@moda-ai/cli 1.55.10 → 1.55.11

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.
@@ -0,0 +1,459 @@
1
+ import {
2
+ buildDoctorReport
3
+ } from "./cli-11fevr8y.js";
4
+ import"./cli-t4jjhn3g.js";
5
+ import"./cli-fq7kk77e.js";
6
+ import"./cli-mm48br00.js";
7
+ import {
8
+ HARNESS_REPORT_APPROVAL_PATH,
9
+ HARNESS_REPORT_PATH,
10
+ graphForSync,
11
+ hashHarnessReport,
12
+ hashStableJson,
13
+ readHarnessReport,
14
+ readHarnessSyncState,
15
+ summarizeHarness,
16
+ validateHarnessReport
17
+ } from "./cli-m857n028.js";
18
+ import"./cli-97fnztpy.js";
19
+ import"./cli-k5qqj2bp.js";
20
+ import"./cli-g7ferymy.js";
21
+ import"./cli-tmqd1f0m.js";
22
+ import"./cli-m16taf4z.js";
23
+ import {
24
+ CliInputError,
25
+ resolveApiKey,
26
+ resolveIngestUrl,
27
+ resolveModaBaseUrl,
28
+ resolveTenantId
29
+ } from "./cli-429zt7g4.js";
30
+ import"./cli-0v6na3yp.js";
31
+
32
+ // src/agent.ts
33
+ import { existsSync, readFileSync, statSync } from "node:fs";
34
+ import { join, relative, resolve } from "node:path";
35
+ var MODA_DIR = ".moda";
36
+ var HARNESS_PATH = join(MODA_DIR, "harness.json");
37
+ var HARNESS_REPORT_MARKDOWN_PATH = join(MODA_DIR, "HARNESS_REPORT.md");
38
+ var HARNESS_SUMMARY_PATH = join(MODA_DIR, "HARNESS.md");
39
+ async function runAgentCommand(context) {
40
+ const subcommand = context.positionals[0] ?? "context";
41
+ switch (subcommand) {
42
+ case "context": {
43
+ const loaded = await buildAgentContext(context);
44
+ context.output.writeData(loaded.payload, agentWriteOptions(loaded));
45
+ return { exitCode: 0 };
46
+ }
47
+ case "investigate": {
48
+ const passthrough = Object.entries(context.flags).filter(([key]) => ["days-back", "tool", "trace", "conversation"].includes(key)).map(([key, value]) => `--${key}=${value}`);
49
+ throw new CliInputError("'moda agent investigate' has been removed. Use 'moda investigate' for the ranked production investigation.", `Run: ${["moda investigate", ...passthrough].join(" ")} (flags: --days-back, --tool, --trace). For local readiness use 'moda agent context'.`);
50
+ }
51
+ case "next-action":
52
+ case "next-actions": {
53
+ const loaded = await buildAgentContext(context);
54
+ context.output.writeData({
55
+ schemaVersion: "agent_next_actions.v0.1",
56
+ generatedAt: loaded.payload.generatedAt,
57
+ status: loaded.payload.doctor.status,
58
+ recommendedActions: loaded.payload.recommendedActions,
59
+ nextCommands: loaded.payload.nextCommands
60
+ }, agentWriteOptions(loaded, {
61
+ summary: `${loaded.payload.recommendedActions.length} recommended action(s) are ready for an agent to evaluate.`
62
+ }));
63
+ return { exitCode: 0 };
64
+ }
65
+ case "evidence": {
66
+ const ref = context.positionals[1] ?? context.flags.id ?? context.flags.ref ?? context.flags.finding;
67
+ if (!ref) {
68
+ throw new CliInputError("<ref> is required", "Usage: moda agent evidence <ref>");
69
+ }
70
+ const loaded = await buildAgentContext(context);
71
+ const evidence = expandEvidenceRef(ref, loaded, context.cwd);
72
+ context.output.writeData(evidence, {
73
+ summary: {
74
+ text: `Expanded evidence reference ${ref}.`,
75
+ confidence: "high"
76
+ },
77
+ evidenceRefs: [evidence.ref],
78
+ artifacts: evidence.artifact ? [evidence.artifact] : []
79
+ });
80
+ return { exitCode: 0 };
81
+ }
82
+ default:
83
+ throw new CliInputError(`Unknown agent subcommand '${subcommand}'`, "Usage: moda agent context|next-action|evidence (for production issues use moda investigate)");
84
+ }
85
+ }
86
+ async function buildAgentContext(context) {
87
+ const doctor = await buildDoctorReport(context, {
88
+ offline: context.flags.online !== "true"
89
+ });
90
+ const graph = readHarnessGraphIfPresent(context.cwd);
91
+ const reportState = readHarnessReportState(context.cwd);
92
+ const syncState = readHarnessSyncState(context.cwd);
93
+ const topFindings = doctor.checks.filter((check) => check.status === "fail" || check.status === "warning").slice(0, 12).map(checkToFinding);
94
+ const evidenceRefs = [
95
+ ...doctor.checks.map(checkToEvidenceRef),
96
+ ...reportEvidenceRefs(reportState.report).slice(0, 60)
97
+ ];
98
+ const artifacts = existingArtifacts(context.cwd);
99
+ const recommendedActions = recommendedActionsForDoctor(doctor);
100
+ const nextCommands = nextCommandsForActions(recommendedActions, doctor.nextCommands);
101
+ const payload = {
102
+ schemaVersion: "agent_context.v0.1",
103
+ generatedAt: new Date().toISOString(),
104
+ mode: "local",
105
+ workspace: {
106
+ cwd: context.cwd,
107
+ profile: context.profile,
108
+ tenantId: resolveTenantId({ profile: context.profile, env: context.env }) ?? null,
109
+ apiKey: resolveApiKey({ profile: context.profile, env: context.env }) ? "configured" : "missing",
110
+ baseUrl: resolveModaBaseUrl({ profile: context.profile, env: context.env }),
111
+ ingestUrl: resolveIngestUrl({ profile: context.profile, env: context.env })
112
+ },
113
+ doctor: {
114
+ status: doctor.summary.status,
115
+ summary: doctor.summary,
116
+ topFindings
117
+ },
118
+ harness: {
119
+ manifest: {
120
+ path: HARNESS_PATH,
121
+ exists: graph !== undefined,
122
+ summary: graph ? summarizeHarness(graph) : null
123
+ },
124
+ report: reportState.state,
125
+ sync: syncState ? {
126
+ path: join(MODA_DIR, "sync-state.json"),
127
+ exists: true,
128
+ source: syncState.source,
129
+ updatedAt: syncState.updatedAt,
130
+ stale: graph ? syncState.localGraphHash !== hashStableJson(graphForSync(graph)) : undefined,
131
+ remoteHarnessId: syncState.remote.harnessId,
132
+ remoteVersionId: syncState.remote.versionId
133
+ } : {
134
+ path: join(MODA_DIR, "sync-state.json"),
135
+ exists: false
136
+ }
137
+ },
138
+ recommendedActions,
139
+ evidenceRefs,
140
+ artifacts,
141
+ nextCommands,
142
+ limitations: [
143
+ "This context is local and bounded. It does not upload source content or prove production behavior.",
144
+ "Use evidence refs to expand claims instead of asking agents to scrape human output."
145
+ ]
146
+ };
147
+ return {
148
+ payload,
149
+ doctor,
150
+ graph,
151
+ report: reportState.report,
152
+ reportValidation: reportState.validation,
153
+ reportApproval: reportState.approval,
154
+ syncState
155
+ };
156
+ }
157
+ function agentWriteOptions(loaded, overrides = {}) {
158
+ return {
159
+ summary: overrides.summary ?? summarizeAgentContext(loaded.payload, "context"),
160
+ findings: loaded.payload.doctor.topFindings,
161
+ evidenceRefs: loaded.payload.evidenceRefs,
162
+ recommendedActions: loaded.payload.recommendedActions,
163
+ nextCommands: loaded.payload.nextCommands,
164
+ artifacts: loaded.payload.artifacts,
165
+ warnings: [
166
+ ...loaded.payload.harness.report.warnings ?? [],
167
+ ...loaded.payload.limitations
168
+ ].slice(0, 40)
169
+ };
170
+ }
171
+ function summarizeAgentContext(payload, noun) {
172
+ const fail = payload.doctor.summary.fail;
173
+ const warning = payload.doctor.summary.warning;
174
+ const agents = payload.harness.manifest.summary?.runtimeAgentCount ?? 0;
175
+ if (fail > 0) {
176
+ return `Local Moda ${noun} found ${fail} failing check(s), ${warning} warning(s), and ${agents} runtime agent(s).`;
177
+ }
178
+ if (warning > 0) {
179
+ return `Local Moda ${noun} is usable with ${warning} warning(s) and ${agents} runtime agent(s).`;
180
+ }
181
+ return `Local Moda ${noun} is healthy with ${agents} runtime agent(s).`;
182
+ }
183
+ function readHarnessGraphIfPresent(cwd) {
184
+ const path = join(cwd, HARNESS_PATH);
185
+ if (!existsSync(path))
186
+ return;
187
+ try {
188
+ return JSON.parse(readFileSync(path, "utf8"));
189
+ } catch {
190
+ return;
191
+ }
192
+ }
193
+ function readHarnessReportState(cwd) {
194
+ const path = join(cwd, HARNESS_REPORT_PATH);
195
+ if (!existsSync(path)) {
196
+ return {
197
+ state: {
198
+ path: HARNESS_REPORT_PATH,
199
+ exists: false,
200
+ status: "missing"
201
+ }
202
+ };
203
+ }
204
+ try {
205
+ const report = readHarnessReport(path);
206
+ const validation = validateHarnessReport(report, cwd);
207
+ const approval = readApproval(cwd);
208
+ const reportHash = hashHarnessReport(report);
209
+ return {
210
+ state: {
211
+ path: HARNESS_REPORT_PATH,
212
+ exists: true,
213
+ status: validation.status === "pass" ? "valid" : "invalid",
214
+ reportId: report.reportId,
215
+ reportHash,
216
+ validationStatus: validation.status,
217
+ approved: approval?.approved === true && approval.reportHash === reportHash,
218
+ claimCount: report.claims.length,
219
+ citationCount: report.citations.length,
220
+ warnings: validation.warnings,
221
+ errors: validation.errors
222
+ },
223
+ report,
224
+ validation,
225
+ approval
226
+ };
227
+ } catch (error) {
228
+ return {
229
+ state: {
230
+ path: HARNESS_REPORT_PATH,
231
+ exists: true,
232
+ status: "invalid",
233
+ errors: [error instanceof Error ? error.message : String(error)]
234
+ }
235
+ };
236
+ }
237
+ }
238
+ function readApproval(cwd) {
239
+ const path = join(cwd, HARNESS_REPORT_APPROVAL_PATH);
240
+ if (!existsSync(path))
241
+ return;
242
+ try {
243
+ return JSON.parse(readFileSync(path, "utf8"));
244
+ } catch {
245
+ return;
246
+ }
247
+ }
248
+ function checkToFinding(check) {
249
+ return {
250
+ id: check.id,
251
+ title: check.title,
252
+ status: check.status,
253
+ severity: check.severity,
254
+ description: check.remediation ?? `Doctor check ${check.id} is ${check.status}.`,
255
+ evidence_ref_ids: [`doctor:${check.id}`]
256
+ };
257
+ }
258
+ function checkToEvidenceRef(check) {
259
+ return {
260
+ id: `doctor:${check.id}`,
261
+ kind: "doctor_check",
262
+ label: check.title,
263
+ status: check.status
264
+ };
265
+ }
266
+ function reportEvidenceRefs(report) {
267
+ if (!report)
268
+ return [];
269
+ return [
270
+ ...report.claims.map((claim) => ({
271
+ id: `harness-report:claim:${claim.id}`,
272
+ kind: "harness_claim",
273
+ label: claim.title,
274
+ status: claim.inference
275
+ })),
276
+ ...report.citations.map((citation) => ({
277
+ id: `harness-report:citation:${citation.id}`,
278
+ kind: citation.type,
279
+ label: citation.reason,
280
+ path: citation.path,
281
+ line: citation.line
282
+ }))
283
+ ];
284
+ }
285
+ function recommendedActionsForDoctor(report) {
286
+ return report.fixPlan.slice(0, 12).map((item, index) => ({
287
+ id: `action_${index + 1}_${item.checkId}`,
288
+ title: item.action,
289
+ command: item.command,
290
+ rationale: `Doctor check ${item.checkId} is not passing.`,
291
+ mutability: item.command ? inferMutability(item.command) : "unknown",
292
+ requires_approval: item.command ? commandRequiresApproval(item.command) : true
293
+ }));
294
+ }
295
+ function nextCommandsForActions(actions, doctorNextCommands) {
296
+ const seen = new Set;
297
+ const commands = [
298
+ ...actions.map((action) => action.command).filter((command) => Boolean(command)),
299
+ ...doctorNextCommands
300
+ ].filter((command) => {
301
+ if (seen.has(command))
302
+ return false;
303
+ seen.add(command);
304
+ return true;
305
+ });
306
+ return commands.slice(0, 12).map((command) => ({
307
+ command,
308
+ purpose: purposeForCommand(command),
309
+ mutability: inferMutability(command),
310
+ requires_approval: commandRequiresApproval(command)
311
+ }));
312
+ }
313
+ function existingArtifacts(cwd) {
314
+ return [
315
+ [HARNESS_PATH, "harness_manifest", "Local harness graph manifest."],
316
+ [HARNESS_REPORT_PATH, "harness_report", "Cited harness analyst report."],
317
+ [HARNESS_REPORT_MARKDOWN_PATH, "harness_report_markdown", "Human-readable harness analyst report."],
318
+ [HARNESS_SUMMARY_PATH, "harness_summary", "Human-readable harness graph summary."],
319
+ [join(MODA_DIR, "sync-state.json"), "sync_state", "Last local harness sync state."],
320
+ [join(MODA_DIR, "prompts.yml"), "prompt_manifest", "Local prompt discovery manifest."]
321
+ ].flatMap(([path, kind, description]) => existsSync(join(cwd, path)) ? [{ path, kind, description }] : []);
322
+ }
323
+ function expandEvidenceRef(ref, loaded, cwd) {
324
+ if (ref.startsWith("doctor:")) {
325
+ const checkId = ref.slice("doctor:".length);
326
+ const check = loaded.doctor.checks.find((candidate) => candidate.id === checkId);
327
+ if (!check)
328
+ throw missingEvidence(ref);
329
+ return {
330
+ schemaVersion: "agent_evidence.v0.1",
331
+ ref: checkToEvidenceRef(check),
332
+ value: check
333
+ };
334
+ }
335
+ if (ref.startsWith("harness-report:claim:")) {
336
+ const claimId = ref.slice("harness-report:claim:".length);
337
+ const claim = loaded.report?.claims.find((candidate) => candidate.id === claimId);
338
+ if (!claim)
339
+ throw missingEvidence(ref);
340
+ return {
341
+ schemaVersion: "agent_evidence.v0.1",
342
+ ref: claimToEvidenceRef(claim),
343
+ value: claim,
344
+ artifact: { kind: "harness_report", path: HARNESS_REPORT_PATH }
345
+ };
346
+ }
347
+ if (ref.startsWith("harness-report:citation:")) {
348
+ const citationId = ref.slice("harness-report:citation:".length);
349
+ const citation = loaded.report?.citations.find((candidate) => candidate.id === citationId);
350
+ if (!citation)
351
+ throw missingEvidence(ref);
352
+ return {
353
+ schemaVersion: "agent_evidence.v0.1",
354
+ ref: citationToEvidenceRef(citation),
355
+ value: {
356
+ citation,
357
+ currentExcerpt: citation.path ? readCitationExcerpt(cwd, citation) : undefined
358
+ },
359
+ artifact: citation.path ? { kind: "citation_source", path: citation.path } : undefined
360
+ };
361
+ }
362
+ if (ref.startsWith("artifact:")) {
363
+ const path = ref.slice("artifact:".length);
364
+ const artifact = loaded.payload.artifacts.find((candidate) => candidate.path === path);
365
+ if (!artifact)
366
+ throw missingEvidence(ref);
367
+ return {
368
+ schemaVersion: "agent_evidence.v0.1",
369
+ ref: {
370
+ id: ref,
371
+ kind: artifact.kind,
372
+ label: artifact.description ?? artifact.path,
373
+ path: artifact.path
374
+ },
375
+ value: readModaArtifact(cwd, artifact.path),
376
+ artifact
377
+ };
378
+ }
379
+ throw missingEvidence(ref);
380
+ }
381
+ function claimToEvidenceRef(claim) {
382
+ return {
383
+ id: `harness-report:claim:${claim.id}`,
384
+ kind: "harness_claim",
385
+ label: claim.title,
386
+ status: claim.inference
387
+ };
388
+ }
389
+ function citationToEvidenceRef(citation) {
390
+ return {
391
+ id: `harness-report:citation:${citation.id}`,
392
+ kind: citation.type,
393
+ label: citation.reason,
394
+ path: citation.path,
395
+ line: citation.line
396
+ };
397
+ }
398
+ function readCitationExcerpt(cwd, citation) {
399
+ if (!citation.path || citation.type !== "file" && citation.type !== "generated_doc")
400
+ return citation.excerpt;
401
+ const absolute = safeResolve(cwd, citation.path);
402
+ if (!absolute || !existsSync(absolute))
403
+ return citation.excerpt;
404
+ const text = readFileSync(absolute, "utf8");
405
+ if (citation.line && citation.line > 0) {
406
+ return text.split(/\r?\n/)[citation.line - 1] ?? citation.excerpt;
407
+ }
408
+ return text;
409
+ }
410
+ function readModaArtifact(cwd, artifactPath) {
411
+ if (!artifactPath.startsWith(".moda/")) {
412
+ throw new CliInputError(`Artifact '${artifactPath}' is outside .moda and cannot be expanded directly.`, "Use a citation evidence ref for source-file evidence.");
413
+ }
414
+ const absolute = safeResolve(cwd, artifactPath);
415
+ if (!absolute || !existsSync(absolute))
416
+ throw missingEvidence(`artifact:${artifactPath}`);
417
+ const size = statSync(absolute).size;
418
+ return {
419
+ path: artifactPath,
420
+ bytes: size,
421
+ text: readFileSync(absolute, "utf8")
422
+ };
423
+ }
424
+ function safeResolve(cwd, path) {
425
+ const absolute = resolve(cwd, path);
426
+ const rel = relative(cwd, absolute);
427
+ if (rel.startsWith("..") || rel === ".." || rel.startsWith("/"))
428
+ return;
429
+ return absolute;
430
+ }
431
+ function missingEvidence(ref) {
432
+ return new CliInputError(`Evidence reference '${ref}' was not found.`, "Run `moda agent context` to list available evidence_refs.");
433
+ }
434
+ function inferMutability(command) {
435
+ if (/\bsync\b/.test(command))
436
+ return "sync";
437
+ if (/\b(init|install|approve|pull|gen|promote|remove)\b/.test(command))
438
+ return "write";
439
+ return "read";
440
+ }
441
+ function commandRequiresApproval(command) {
442
+ return inferMutability(command) !== "read" && !command.includes("--dry-run");
443
+ }
444
+ function purposeForCommand(command) {
445
+ if (command.includes("harness approve"))
446
+ return "Approve the current harness report after human review.";
447
+ if (command.includes("harness sync"))
448
+ return "Sync approved harness state to Moda Cloud.";
449
+ if (command.includes("harness analyze"))
450
+ return "Produce or refresh a cited harness report.";
451
+ if (command.includes("doctor"))
452
+ return "Re-run local diagnostics.";
453
+ if (command.includes("init"))
454
+ return "Complete local Moda onboarding.";
455
+ return "Inspect or repair local Moda state.";
456
+ }
457
+ export {
458
+ runAgentCommand
459
+ };