@aiaiai-pt/martha-cli 0.63.2 → 0.64.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to `@aiaiai-pt/martha-cli`. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project adheres to semver — `0.x` releases may include breaking changes between minor versions.
4
4
 
5
+ ## [0.64.0] — 2026-10-20
6
+
7
+ ### Added
8
+
9
+ - `martha documents lifecycle <id>` explains ingestion, storage and presence states, search eligibility, event permissions, linked source freshness and transition history. `--json` returns the API payload unchanged. Requires a server with the document lifecycle endpoint (#1685).
10
+
11
+ ### Fixed
12
+
13
+ - Store-only `skipped` ingestion finishes `--wait` and `--follow` successfully.
14
+ - Failed ingestion returns a nonzero exit from JSON wait mode, matching text mode.
15
+
5
16
  ## [0.63.2] — 2026-10-15
6
17
 
7
18
  ### Changed
package/dist/index.js CHANGED
@@ -11244,7 +11244,7 @@ init_config();
11244
11244
  init_errors();
11245
11245
 
11246
11246
  // src/version.ts
11247
- var CLI_VERSION = "0.63.2";
11247
+ var CLI_VERSION = "0.64.0";
11248
11248
 
11249
11249
  // src/commands/sessions.ts
11250
11250
  function relativeTime(iso) {
@@ -17720,7 +17720,41 @@ var triggersConfig = {
17720
17720
  // src/commands/documents.ts
17721
17721
  import fs10 from "node:fs";
17722
17722
  init_errors();
17723
- var TERMINAL_STATUSES2 = new Set(["ready", "error"]);
17723
+
17724
+ // src/lib/document-lifecycle.ts
17725
+ function formatDocumentLifecycle(value) {
17726
+ const lines = [
17727
+ `Document: ${value.document_id}`,
17728
+ `Searchable: ${value.searchable ? "yes" : "no"}`,
17729
+ ...value.searchability_reasons.map((reason) => ` ${reason}`)
17730
+ ];
17731
+ for (const region of value.regions) {
17732
+ lines.push(`
17733
+ ${region.kind}: ${region.state ?? "Not recorded"} (${region.mode})`);
17734
+ for (const event of region.events) {
17735
+ lines.push(` ${event.event} → ${event.to_state}: ${event.allowed ? "allowed" : `unavailable (${event.reason ?? "not authorized"})`}`);
17736
+ }
17737
+ }
17738
+ lines.push(`
17739
+ Sync sources:`);
17740
+ if (!value.sync_sources.length)
17741
+ lines.push(" None");
17742
+ for (const source of value.sync_sources) {
17743
+ lines.push(` ${source.id}: ${source.provider}, ${source.status}; last synced ${source.last_synced_at ?? "never"}`);
17744
+ }
17745
+ lines.push(`
17746
+ History:`);
17747
+ if (!value.history.length)
17748
+ lines.push(" No recorded transitions");
17749
+ for (const row of value.history) {
17750
+ lines.push(` ${row.seq} ${row.created_at} ${row.kind}: ${row.from_state ?? "∅"} → ${row.to_state} (${row.event}, ${row.actor_kind}:${row.actor_id ?? "unknown"})`);
17751
+ }
17752
+ return lines.join(`
17753
+ `);
17754
+ }
17755
+
17756
+ // src/commands/documents.ts
17757
+ var TERMINAL_STATUSES2 = new Set(["ready", "error", "skipped"]);
17724
17758
  var SPINNER_FRAMES2 = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
17725
17759
  var spinnerIdx = 0;
17726
17760
  function nextSpinner() {
@@ -17850,6 +17884,8 @@ Detached. Check status with: martha documents status ${documentId}`));
17850
17884
  if (TERMINAL_STATUSES2.has(status.ingestion_status)) {
17851
17885
  if (status.ingestion_status === "ready") {
17852
17886
  lines.push(source_default.green("Ingestion complete"));
17887
+ } else if (status.ingestion_status === "skipped") {
17888
+ lines.push("Ingestion skipped (store-only document)");
17853
17889
  } else {
17854
17890
  lines.push(source_default.red(`Error: ${status.error ?? "unknown error"}`));
17855
17891
  }
@@ -17869,6 +17905,8 @@ Detached. Check status with: martha documents status ${documentId}`));
17869
17905
  if (!isJson && !isTTY) {
17870
17906
  if (status.ingestion_status === "ready") {
17871
17907
  console.log(`Ingestion complete. ${status.chunk_count ?? 0} chunks created.`);
17908
+ } else if (status.ingestion_status === "skipped") {
17909
+ console.log("Ingestion skipped (store-only document).");
17872
17910
  } else {
17873
17911
  console.error(`Ingestion failed: ${status.error ?? "unknown error"}`);
17874
17912
  process.exitCode = 1 /* Error */;
@@ -17898,6 +17936,10 @@ function registerDocumentCommands(program) {
17898
17936
  function isJson() {
17899
17937
  return !!program.opts().json;
17900
17938
  }
17939
+ cmd.command("lifecycle <document-id>").description("Explain document states, search eligibility, event permissions and history").action(async (documentId) => {
17940
+ const value = await getCtx().api.get(`/api/admin/documents/${encodeURIComponent(documentId)}/lifecycle`);
17941
+ console.log(isJson() ? JSON.stringify(value, null, 2) : formatDocumentLifecycle(value));
17942
+ });
17901
17943
  async function resolveCollection(ctx, ref) {
17902
17944
  const looksLikeUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(ref);
17903
17945
  if (looksLikeUuid) {
@@ -18124,11 +18166,15 @@ ${items.length} collections`));
18124
18166
  console.log(source_default.dim(`Uploaded ${result.filename}. Waiting for ingestion...`));
18125
18167
  }
18126
18168
  const final = await pollIngestionUntilDone(ctx, result.id);
18169
+ if (final.ingestion_status === "error")
18170
+ process.exitCode = 1 /* Error */;
18127
18171
  if (isJson()) {
18128
18172
  console.log(JSON.stringify(final));
18129
18173
  } else {
18130
18174
  if (final.ingestion_status === "ready") {
18131
18175
  console.log(`Ingestion complete. ${final.chunk_count ?? 0} chunks created.`);
18176
+ } else if (final.ingestion_status === "skipped") {
18177
+ console.log("Ingestion skipped (store-only document).");
18132
18178
  } else {
18133
18179
  console.error(`Ingestion failed: ${final.error ?? "unknown error"}`);
18134
18180
  process.exitCode = 1 /* Error */;
@@ -18307,11 +18353,15 @@ ${items.length} documents`));
18307
18353
  console.log(source_default.dim(`Re-ingestion triggered. Waiting for completion...`));
18308
18354
  }
18309
18355
  const final = await pollIngestionUntilDone(ctx, documentId);
18356
+ if (final.ingestion_status === "error")
18357
+ process.exitCode = 1 /* Error */;
18310
18358
  if (isJson()) {
18311
18359
  console.log(JSON.stringify(final));
18312
18360
  } else {
18313
18361
  if (final.ingestion_status === "ready") {
18314
18362
  console.log(`Ingestion complete. ${final.chunk_count ?? 0} chunks created.`);
18363
+ } else if (final.ingestion_status === "skipped") {
18364
+ console.log("Ingestion skipped (store-only document).");
18315
18365
  } else {
18316
18366
  console.error(`Ingestion failed: ${final.error ?? "unknown error"}`);
18317
18367
  process.exitCode = 1 /* Error */;
@@ -20507,13 +20557,10 @@ function registerMessagingCommands(program) {
20507
20557
  });
20508
20558
  cmd.command("send-sms").description("Send a test SMS").requiredOption("--to <number>", "Destination phone number (E.164)").requiredOption("--from <sender>", "Sender ID or number").requiredOption("--content <text>", "Message content").action(async (opts) => {
20509
20559
  const ctx = getCtx();
20510
- const data = await messagingFetch(ctx.profile.api_url, "/api/messaging/send/sms", {
20511
- method: "POST",
20512
- body: {
20513
- to: opts.to,
20514
- from_number: opts.from,
20515
- content: opts.content
20516
- }
20560
+ const data = await ctx.api.post("/api/messaging/send/sms", {
20561
+ to: opts.to,
20562
+ from_number: opts.from,
20563
+ content: opts.content
20517
20564
  });
20518
20565
  if (isJson()) {
20519
20566
  console.log(JSON.stringify(data, null, 2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiaiai-pt/martha-cli",
3
- "version": "0.63.2",
3
+ "version": "0.64.0",
4
4
  "description": "Terminal-first client for the Martha AI platform",
5
5
  "homepage": "https://docs.martha.nomadriver.co",
6
6
  "repository": {
@@ -640,6 +640,7 @@ martha documents move-collection <id> --parent <slug-or-id> | --root # Atomic m
640
640
  martha documents upload <collection-id> <file> [--wait] [--follow] # --follow streams ingestion progress
641
641
  martha documents list <collection-id> [--inactive] [--limit 50]
642
642
  martha documents get <doc-id> # Full metadata + chunk count
643
+ martha documents lifecycle <doc-id> [--json] # States, search eligibility, event permissions, sources and history
643
644
  martha documents status <doc-id> [--follow] # Ingestion progress: validate → parse → embed → finalize
644
645
  martha documents download <doc-id> [--expires 3600] # Presigned URL (default 1h)
645
646
  martha documents delete <doc-id> [--yes]