@moda-ai/cli 1.34.0 → 1.35.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.
@@ -648,7 +648,7 @@ function validateConfig() {
648
648
  }
649
649
  }
650
650
 
651
- // ../../../ModaObservability-prompt-sync/packages/harness-snapshot/src/policy.ts
651
+ // ../../packages/harness-snapshot/src/policy.ts
652
652
  var MAX_SCANNED_FILE_BYTES = 512 * 1024;
653
653
  var DEFAULT_MAX_INVENTORY_FILES = 12000;
654
654
  var DEFAULT_MAX_INVENTORY_TEXT_BYTES = 48 * 1024 * 1024;
@@ -790,7 +790,7 @@ function isSecretishPath(path) {
790
790
  return name === ".env" || name.startsWith(".env.") || name.includes("secret") || name.includes("private-key") || name.endsWith(".pem");
791
791
  }
792
792
 
793
- // ../../../ModaObservability-prompt-sync/packages/harness-snapshot/src/redact.ts
793
+ // ../../packages/harness-snapshot/src/redact.ts
794
794
  var REDACTED = "[REDACTED]";
795
795
  var MAX_DEPTH = 256;
796
796
  var SECRET_KEYS = new Set([
@@ -887,7 +887,7 @@ function redactSnapshotText(text) {
887
887
  return { text: parts.join(""), redactionCount };
888
888
  }
889
889
 
890
- // ../../../ModaObservability-prompt-sync/packages/harness-snapshot/src/pack.ts
890
+ // ../../packages/harness-snapshot/src/pack.ts
891
891
  function utf8ByteLength(value) {
892
892
  let bytes = 0;
893
893
  for (let index = 0;index < value.length; index += 1) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  authFetch,
3
3
  getCachedLoginContext
4
- } from "./cli-eggpzt87.js";
4
+ } from "./cli-yz99t7n8.js";
5
5
  import {
6
6
  CliAccessError,
7
7
  CliInputError,
@@ -15,7 +15,7 @@ import {
15
15
  resolveTenantIdFromActiveProfile,
16
16
  saveCliConfig,
17
17
  writeSecretJsonFile
18
- } from "./cli-0h32yvwq.js";
18
+ } from "./cli-drabjmaj.js";
19
19
 
20
20
  // src/init/tenant.ts
21
21
  import { randomUUID } from "node:crypto";
@@ -8,7 +8,7 @@ import {
8
8
  saveProfileConfig,
9
9
  secretFilePathFromRef,
10
10
  writeSecretJsonFile
11
- } from "./cli-0h32yvwq.js";
11
+ } from "./cli-drabjmaj.js";
12
12
 
13
13
  // src/auth-storage.ts
14
14
  import { existsSync, readFileSync, rmSync } from "node:fs";
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  runPromptsCommand,
9
9
  runSkillsCommand,
10
10
  runStatusCommand
11
- } from "./cli-q9t1tr1z.js";
11
+ } from "./cli-7qkhy41j.js";
12
12
  import {
13
13
  ApiError,
14
14
  HARNESS_REPORT_APPROVAL_PATH,
@@ -29,7 +29,7 @@ import {
29
29
  summarizeHarness,
30
30
  terminalStyles,
31
31
  validateHarnessReport
32
- } from "./cli-xwqb83jb.js";
32
+ } from "./cli-0p6n391h.js";
33
33
  import {
34
34
  authFetch,
35
35
  clearAuthSession,
@@ -37,7 +37,7 @@ import {
37
37
  loadAuthSession,
38
38
  login,
39
39
  revokeCliSessionToken
40
- } from "./cli-eggpzt87.js";
40
+ } from "./cli-yz99t7n8.js";
41
41
  import {
42
42
  AGENT_ERROR_CODES,
43
43
  CliAccessError,
@@ -84,9 +84,10 @@ import {
84
84
  validateConfig,
85
85
  wasOutputCancelled,
86
86
  writeSecretJsonFile
87
- } from "./cli-0h32yvwq.js";
87
+ } from "./cli-drabjmaj.js";
88
88
 
89
89
  // src/cli.ts
90
+ import { randomUUID as randomUUID2 } from "node:crypto";
90
91
  import { z as z2 } from "zod";
91
92
 
92
93
  // src/schemas.ts
@@ -209,6 +210,30 @@ var ProblemFeedbackSchema = z.object({
209
210
  new_name: z.string().max(255).optional(),
210
211
  actor: z.string().max(255).optional()
211
212
  });
213
+ var SignalSchema = z.object({
214
+ id: z.string().min(1).max(255),
215
+ detections: boolFlag(),
216
+ days_back: z.number().min(1).max(90).optional(),
217
+ limit: z.number().min(1).max(20).optional(),
218
+ offset: z.number().min(0).max(1e4).optional()
219
+ });
220
+ var SIGNAL_LABELS = ["fits", "does_not_fit"];
221
+ var SignalLabelSchema = z.object({
222
+ id: z.string().min(1).max(255),
223
+ conversation_id: z.string().min(1).max(255),
224
+ label: z.enum(SIGNAL_LABELS),
225
+ note: z.string().max(2000).optional(),
226
+ msg_index: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
227
+ msg_dedup_token: z.string().min(1).max(200).optional()
228
+ });
229
+ var DETECTION_VERDICTS = ["correct", "false_positive", "clear"];
230
+ var DetectionReviewSchema = z.object({
231
+ id: z.string().regex(UUID_RE, "Problem id must be a canonical UUID"),
232
+ conversation_id: z.string().min(1).max(255),
233
+ attribution_id: z.string().regex(UUID_RE, "Attribution id must be a UUID"),
234
+ verdict: z.enum(DETECTION_VERDICTS),
235
+ note: z.string().max(2000).optional()
236
+ });
212
237
  var EMOTION_FAMILIES = [
213
238
  "frustration",
214
239
  "sadness",
@@ -5382,6 +5407,12 @@ Commands:
5382
5407
  problem-impact Live problem/use-case impact (--node-id, --problem-id, --mode, --days-back)
5383
5408
  problem <problem_id> Open one Problem: dossier, or --evidence/--reports/--traces/--feedback
5384
5409
  problem-feedback <problem_id> Mark a Problem fixed, dismiss, rename, or flag a bad attribution
5410
+ detection-reviews <conv_id> Problem detections on a trace with their review state
5411
+ detection-review <problem_id> Mark a problem detection correct, a false positive, or clear the review
5412
+ signals List custom signals (name, criteria, status, 7-day stats)
5413
+ signal <signal_id> One custom signal, or --detections for its recent hits
5414
+ trace-signals <conversation_id> Custom signal hits on one trace
5415
+ signal-label <signal_id> Label a trace fits / does_not_fit (false positive) for a signal
5385
5416
  step-scores <conversation_id> Graph-PRM step scores (per-segment curves, first bad step, rollup)
5386
5417
  tail Live-tail new traces/detections as NDJSON (one line per item)
5387
5418
  feedback "<note>" Flag wrong/missing data or CLI quirks to the Moda team
@@ -5502,6 +5533,24 @@ Problem-feedback flags:
5502
5533
  --attribution-id=UUID Required for flag_attribution (ids come from problem --evidence)
5503
5534
  --new-name=NAME Required for rename
5504
5535
 
5536
+ Detection-review flags (moda detection-review <problem_id>):
5537
+ --conversation-id=ID Trace the detection is on (required)
5538
+ --attribution-id=UUID Detection id (from problem --evidence or detection-reviews; required)
5539
+ --verdict=V correct|false_positive|clear (required; clear undoes a review)
5540
+ --note=TEXT Why (optional; kept with the review)
5541
+
5542
+ Signal flags:
5543
+ --detections moda signal <id>: list recent hits instead of the summary
5544
+ --days-back=N --limit=N --offset=N
5545
+ Hits window 1-90 (default 7); page size 1-20 (default 10)
5546
+
5547
+ Signal-label flags (moda signal-label <signal_id>):
5548
+ --conversation-id=ID Trace to label (required)
5549
+ --label=fits|does_not_fit does_not_fit marks a false positive and retracts the hit (required)
5550
+ --note=TEXT Why (recommended for does_not_fit)
5551
+ --msg-index=N --msg-dedup-token=T
5552
+ Anchor message (from the hit's anchor_msg_index / anchor_dedup_token)
5553
+
5505
5554
  Tail flags:
5506
5555
  --signal=S traces|emotions|all (default traces)
5507
5556
  --interval=N Poll every N seconds (5-3600, default 15)
@@ -5626,6 +5675,11 @@ Examples:
5626
5675
  moda problems --days-back=7
5627
5676
  moda problem <problem_id> --evidence --limit=10
5628
5677
  moda problem-feedback <problem_id> --action=mark_fixed
5678
+ moda detection-reviews <conversation_id>
5679
+ moda detection-review <problem_id> --conversation-id=<id> --attribution-id=<uuid> --verdict=false_positive --note="expected retry"
5680
+ moda signals
5681
+ moda signal <signal_id> --detections --days-back=30
5682
+ moda signal-label <signal_id> --conversation-id=<id> --label=does_not_fit --note="refund was approved"
5629
5683
  moda step-scores <conversation_id>
5630
5684
  moda tail --signal=all --interval=30
5631
5685
  moda frustrations --days-back=14 --limit=20
@@ -6378,6 +6432,112 @@ async function runCommand(command, positional, flags, positionals = positional ?
6378
6432
  context.output.writeData(data);
6379
6433
  break;
6380
6434
  }
6435
+ case "signals": {
6436
+ const data = await callDataAPI("/custom-signals");
6437
+ context.output.writeData(data);
6438
+ break;
6439
+ }
6440
+ case "signal": {
6441
+ if (!positional) {
6442
+ throw new CliInputError("<signal_id> is required", "Usage: moda signal <signal_id> [--detections] [--days-back=N] [--limit=N] [--offset=N]");
6443
+ }
6444
+ const args = flagsToArgs(flags, "id", positional);
6445
+ args.id = positional;
6446
+ const params = SignalSchema.parse(args);
6447
+ const id = encodeURIComponent(params.id);
6448
+ if (params.detections !== true) {
6449
+ const data2 = await callDataAPI(`/custom-signals/${id}`);
6450
+ context.output.writeData(data2);
6451
+ break;
6452
+ }
6453
+ const query = new URLSearchParams;
6454
+ if (params.days_back)
6455
+ query.set("days_back", params.days_back.toString());
6456
+ if (params.limit)
6457
+ query.set("limit", params.limit.toString());
6458
+ if (params.offset !== undefined)
6459
+ query.set("offset", params.offset.toString());
6460
+ const queryString = query.toString() ? `?${query.toString()}` : "";
6461
+ const data = await callDataAPI(`/custom-signals/${id}/detections${queryString}`);
6462
+ context.output.writeData(data);
6463
+ break;
6464
+ }
6465
+ case "trace-signals": {
6466
+ if (!positional) {
6467
+ throw new CliInputError("<conversation_id> is required", "Usage: moda trace-signals <conversation_id>");
6468
+ }
6469
+ const data = await callDataAPI(`/conversations/${encodeURIComponent(positional)}/custom-signals`);
6470
+ context.output.writeData(data);
6471
+ break;
6472
+ }
6473
+ case "signal-label": {
6474
+ const usage = `Usage: moda signal-label <signal_id> --conversation-id=ID --label=${SIGNAL_LABELS.join("|")} [--note=TEXT] [--msg-index=N] [--msg-dedup-token=T]`;
6475
+ if (!positional) {
6476
+ throw new CliInputError("<signal_id> is required", usage);
6477
+ }
6478
+ const params = SignalLabelSchema.parse({
6479
+ id: positional,
6480
+ ...flags["conversation-id"] !== undefined ? { conversation_id: flags["conversation-id"] } : {},
6481
+ ...flags.label !== undefined ? { label: flags.label } : {},
6482
+ ...flags.note !== undefined ? { note: flags.note } : {},
6483
+ ...flags["msg-index"] !== undefined ? { msg_index: flags["msg-index"] } : {},
6484
+ ...flags["msg-dedup-token"] !== undefined ? { msg_dedup_token: flags["msg-dedup-token"] } : {}
6485
+ });
6486
+ const note = params.note?.trim() ?? "";
6487
+ const data = await callDataAPI(`/custom-signals/${encodeURIComponent(params.id)}/labels`, {
6488
+ method: "POST",
6489
+ body: JSON.stringify({
6490
+ conversation_id: params.conversation_id,
6491
+ label: params.label,
6492
+ ...note !== "" ? { note } : {},
6493
+ ...params.msg_index !== undefined ? { msg_index: params.msg_index } : {},
6494
+ ...params.msg_dedup_token ? { msg_dedup_token: params.msg_dedup_token } : {}
6495
+ }),
6496
+ headers: { "Content-Type": "application/json" }
6497
+ }, { retries: 0 });
6498
+ context.output.writeData(data);
6499
+ break;
6500
+ }
6501
+ case "detection-reviews": {
6502
+ if (!positional) {
6503
+ throw new CliInputError("<conversation_id> is required", "Usage: moda detection-reviews <conversation_id> [--attribution-id=UUID]");
6504
+ }
6505
+ const attributionId = flags["attribution-id"];
6506
+ if (attributionId !== undefined && !UUID_RE.test(attributionId)) {
6507
+ throw new CliInputError("--attribution-id must be a UUID.");
6508
+ }
6509
+ const queryString = attributionId ? `?attribution_id=${encodeURIComponent(attributionId)}` : "";
6510
+ const data = await callDataAPI(`/conversations/${encodeURIComponent(positional)}/detection-reviews${queryString}`);
6511
+ context.output.writeData(data);
6512
+ break;
6513
+ }
6514
+ case "detection-review": {
6515
+ const usage = `Usage: moda detection-review <problem_id> --conversation-id=ID --attribution-id=UUID --verdict=${DETECTION_VERDICTS.join("|")} [--note=TEXT]`;
6516
+ if (!positional) {
6517
+ throw new CliInputError("<problem_id> is required", usage);
6518
+ }
6519
+ const params = DetectionReviewSchema.parse({
6520
+ id: positional,
6521
+ ...flags["conversation-id"] !== undefined ? { conversation_id: flags["conversation-id"] } : {},
6522
+ ...flags["attribution-id"] !== undefined ? { attribution_id: flags["attribution-id"] } : {},
6523
+ ...flags.verdict !== undefined ? { verdict: flags.verdict } : {},
6524
+ ...flags.note !== undefined ? { note: flags.note } : {}
6525
+ });
6526
+ const note = params.verdict === "clear" ? "" : params.note?.trim() ?? "";
6527
+ const data = await callDataAPI(`/problems/${params.id}/detection-reviews`, {
6528
+ method: "POST",
6529
+ body: JSON.stringify({
6530
+ conversation_id: params.conversation_id,
6531
+ attribution_id: params.attribution_id,
6532
+ verdict: params.verdict,
6533
+ ...note !== "" ? { note } : {},
6534
+ request_nonce: randomUUID2()
6535
+ }),
6536
+ headers: { "Content-Type": "application/json" }
6537
+ });
6538
+ context.output.writeData(data);
6539
+ break;
6540
+ }
6381
6541
  case "emotions": {
6382
6542
  const args = flagsToArgs(flags);
6383
6543
  const params = EmotionsSchema.parse(args);
@@ -6580,7 +6740,7 @@ var commandRegistry = createCommandRegistry([
6580
6740
  resetApiRequestCountBeforeRun: true,
6581
6741
  telemetry: "result",
6582
6742
  handler: async (context) => {
6583
- const { runInit } = await import("./index-a0hvade2.js");
6743
+ const { runInit } = await import("./index-pf2hvadv.js");
6584
6744
  if (context.outputMode === "agent-stream") {
6585
6745
  context.output.writeEvent({
6586
6746
  event: "started",
@@ -6621,7 +6781,7 @@ var commandRegistry = createCommandRegistry([
6621
6781
  resetApiRequestCountBeforeRun: true,
6622
6782
  telemetry: "result-and-error",
6623
6783
  handler: async (context) => {
6624
- const { runProvision } = await import("./provision-c5sx3s32.js");
6784
+ const { runProvision } = await import("./provision-d242y9qd.js");
6625
6785
  return runProvision(context, {
6626
6786
  resumeCommand: buildResumeCommand("provision", context.rawFlags)
6627
6787
  });
@@ -7001,6 +7161,57 @@ var commandRegistry = createCommandRegistry([
7001
7161
  ...dataApiDefaults,
7002
7162
  mutability: "write"
7003
7163
  }),
7164
+ legacyCommand({
7165
+ name: "detection-reviews",
7166
+ description: "List problem detections on a trace with their review state (correct / false_positive / clear)",
7167
+ examples: [
7168
+ "moda detection-reviews <conversation_id>",
7169
+ "moda detection-reviews <conversation_id> --attribution-id=<uuid>"
7170
+ ],
7171
+ ...dataApiDefaults
7172
+ }),
7173
+ legacyCommand({
7174
+ name: "detection-review",
7175
+ description: "Review a problem detection on a trace: mark it correct, a false positive, or clear the review",
7176
+ examples: [
7177
+ 'moda detection-review <problem_id> --conversation-id=<id> --attribution-id=<uuid> --verdict=false_positive --note="expected retry"',
7178
+ "moda detection-review <problem_id> --conversation-id=<id> --attribution-id=<uuid> --verdict=correct",
7179
+ "moda detection-review <problem_id> --conversation-id=<id> --attribution-id=<uuid> --verdict=clear"
7180
+ ],
7181
+ ...dataApiDefaults,
7182
+ mutability: "write"
7183
+ }),
7184
+ legacyCommand({
7185
+ name: "signals",
7186
+ description: "List custom signals with criteria, status, and 7-day judged/matched stats",
7187
+ examples: ["moda signals"],
7188
+ ...dataApiDefaults
7189
+ }),
7190
+ legacyCommand({
7191
+ name: "signal",
7192
+ description: "Open one custom signal, or --detections for its recent hits (paged)",
7193
+ examples: [
7194
+ "moda signal <signal_id>",
7195
+ "moda signal <signal_id> --detections --days-back=30 --limit=20"
7196
+ ],
7197
+ ...dataApiDefaults
7198
+ }),
7199
+ legacyCommand({
7200
+ name: "trace-signals",
7201
+ description: "Custom signal hits on one trace",
7202
+ examples: ["moda trace-signals <conversation_id>"],
7203
+ ...dataApiDefaults
7204
+ }),
7205
+ legacyCommand({
7206
+ name: "signal-label",
7207
+ description: "Label a trace for a custom signal: fits, or does_not_fit to mark a false positive",
7208
+ examples: [
7209
+ 'moda signal-label <signal_id> --conversation-id=<id> --label=does_not_fit --note="refund was approved"',
7210
+ "moda signal-label <signal_id> --conversation-id=<id> --label=fits --msg-index=12"
7211
+ ],
7212
+ ...dataApiDefaults,
7213
+ mutability: "write"
7214
+ }),
7004
7215
  legacyCommand({
7005
7216
  name: "emotions",
7006
7217
  description: "Multi-family emotion detections (frustration, sadness, confusion, anxiety, trust, positive)",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  buildSourceSnapshot
3
- } from "./cli-xwqb83jb.js";
4
- import"./cli-0h32yvwq.js";
3
+ } from "./cli-0p6n391h.js";
4
+ import"./cli-drabjmaj.js";
5
5
 
6
6
  // src/harness-github-actions.ts
7
7
  var DEFAULT_MODA_GITHUB_URL = "https://moda-github.modas.workers.dev";
@@ -42,8 +42,8 @@ import {
42
42
  writeHarnessAnalyzeResult,
43
43
  writeHarnessArtifacts,
44
44
  writeHumanProgress
45
- } from "./cli-xwqb83jb.js";
46
- import"./cli-0h32yvwq.js";
45
+ } from "./cli-0p6n391h.js";
46
+ import"./cli-drabjmaj.js";
47
47
  export {
48
48
  writeHumanProgress,
49
49
  writeHarnessArtifacts,
@@ -10,7 +10,7 @@ import {
10
10
  runPromptSync,
11
11
  runSkillSync,
12
12
  upsertSkillManifestRecord
13
- } from "./cli-q9t1tr1z.js";
13
+ } from "./cli-7qkhy41j.js";
14
14
  import {
15
15
  codingAgentDisplayName,
16
16
  describeCodingAgentEvent,
@@ -28,14 +28,14 @@ import {
28
28
  runHarnessCommand,
29
29
  startRemoteAnalyze,
30
30
  stripAnsi
31
- } from "./cli-xwqb83jb.js";
31
+ } from "./cli-0p6n391h.js";
32
32
  import {
33
33
  selectTenantAndCreateKey
34
- } from "./cli-4ycvzfdg.js";
34
+ } from "./cli-scjxgaba.js";
35
35
  import {
36
36
  loadToken,
37
37
  login
38
- } from "./cli-eggpzt87.js";
38
+ } from "./cli-yz99t7n8.js";
39
39
  import {
40
40
  CliAuthError,
41
41
  CliInputError,
@@ -43,7 +43,7 @@ import {
43
43
  createCommandContext,
44
44
  resolveIngestUrl,
45
45
  resolveModaBaseUrl
46
- } from "./cli-0h32yvwq.js";
46
+ } from "./cli-drabjmaj.js";
47
47
 
48
48
  // src/init/index.ts
49
49
  import { existsSync as existsSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";