@aiaiai-pt/martha-cli 0.63.2 → 0.65.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,23 @@
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.65.0] — 2026-10-24
6
+
7
+ ### Added
8
+
9
+ - `martha documents lifecycle <id>` says where a document's recorded history starts: for a document created before the lifecycle ledger existed it prints "Recorded from <time>; earlier transitions were not recorded", so a short or empty history no longer reads as "nothing happened". It prints nothing extra when the history reaches the document's creation, or against a server that does not send `history_complete` (#1685).
10
+
11
+ ## [0.64.0] — 2026-10-20
12
+
13
+ ### Added
14
+
15
+ - `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).
16
+
17
+ ### Fixed
18
+
19
+ - Store-only `skipped` ingestion finishes `--wait` and `--follow` successfully.
20
+ - Failed ingestion returns a nonzero exit from JSON wait mode, matching text mode.
21
+
5
22
  ## [0.63.2] — 2026-10-15
6
23
 
7
24
  ### 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.65.0";
11248
11248
 
11249
11249
  // src/commands/sessions.ts
11250
11250
  function relativeTime(iso) {
@@ -17720,7 +17720,44 @@ 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_complete === false) {
17748
+ lines.push(value.history_recorded_from ? ` Recorded from ${value.history_recorded_from}; earlier transitions were not recorded` : " Earlier transitions were not recorded");
17749
+ }
17750
+ if (!value.history.length)
17751
+ lines.push(" No recorded transitions");
17752
+ for (const row of value.history) {
17753
+ lines.push(` ${row.seq} ${row.created_at} ${row.kind}: ${row.from_state ?? "∅"} → ${row.to_state} (${row.event}, ${row.actor_kind}:${row.actor_id ?? "unknown"})`);
17754
+ }
17755
+ return lines.join(`
17756
+ `);
17757
+ }
17758
+
17759
+ // src/commands/documents.ts
17760
+ var TERMINAL_STATUSES2 = new Set(["ready", "error", "skipped"]);
17724
17761
  var SPINNER_FRAMES2 = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
17725
17762
  var spinnerIdx = 0;
17726
17763
  function nextSpinner() {
@@ -17850,6 +17887,8 @@ Detached. Check status with: martha documents status ${documentId}`));
17850
17887
  if (TERMINAL_STATUSES2.has(status.ingestion_status)) {
17851
17888
  if (status.ingestion_status === "ready") {
17852
17889
  lines.push(source_default.green("Ingestion complete"));
17890
+ } else if (status.ingestion_status === "skipped") {
17891
+ lines.push("Ingestion skipped (store-only document)");
17853
17892
  } else {
17854
17893
  lines.push(source_default.red(`Error: ${status.error ?? "unknown error"}`));
17855
17894
  }
@@ -17869,6 +17908,8 @@ Detached. Check status with: martha documents status ${documentId}`));
17869
17908
  if (!isJson && !isTTY) {
17870
17909
  if (status.ingestion_status === "ready") {
17871
17910
  console.log(`Ingestion complete. ${status.chunk_count ?? 0} chunks created.`);
17911
+ } else if (status.ingestion_status === "skipped") {
17912
+ console.log("Ingestion skipped (store-only document).");
17872
17913
  } else {
17873
17914
  console.error(`Ingestion failed: ${status.error ?? "unknown error"}`);
17874
17915
  process.exitCode = 1 /* Error */;
@@ -17898,6 +17939,10 @@ function registerDocumentCommands(program) {
17898
17939
  function isJson() {
17899
17940
  return !!program.opts().json;
17900
17941
  }
17942
+ cmd.command("lifecycle <document-id>").description("Explain document states, search eligibility, event permissions and history").action(async (documentId) => {
17943
+ const value = await getCtx().api.get(`/api/admin/documents/${encodeURIComponent(documentId)}/lifecycle`);
17944
+ console.log(isJson() ? JSON.stringify(value, null, 2) : formatDocumentLifecycle(value));
17945
+ });
17901
17946
  async function resolveCollection(ctx, ref) {
17902
17947
  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
17948
  if (looksLikeUuid) {
@@ -18124,11 +18169,15 @@ ${items.length} collections`));
18124
18169
  console.log(source_default.dim(`Uploaded ${result.filename}. Waiting for ingestion...`));
18125
18170
  }
18126
18171
  const final = await pollIngestionUntilDone(ctx, result.id);
18172
+ if (final.ingestion_status === "error")
18173
+ process.exitCode = 1 /* Error */;
18127
18174
  if (isJson()) {
18128
18175
  console.log(JSON.stringify(final));
18129
18176
  } else {
18130
18177
  if (final.ingestion_status === "ready") {
18131
18178
  console.log(`Ingestion complete. ${final.chunk_count ?? 0} chunks created.`);
18179
+ } else if (final.ingestion_status === "skipped") {
18180
+ console.log("Ingestion skipped (store-only document).");
18132
18181
  } else {
18133
18182
  console.error(`Ingestion failed: ${final.error ?? "unknown error"}`);
18134
18183
  process.exitCode = 1 /* Error */;
@@ -18307,11 +18356,15 @@ ${items.length} documents`));
18307
18356
  console.log(source_default.dim(`Re-ingestion triggered. Waiting for completion...`));
18308
18357
  }
18309
18358
  const final = await pollIngestionUntilDone(ctx, documentId);
18359
+ if (final.ingestion_status === "error")
18360
+ process.exitCode = 1 /* Error */;
18310
18361
  if (isJson()) {
18311
18362
  console.log(JSON.stringify(final));
18312
18363
  } else {
18313
18364
  if (final.ingestion_status === "ready") {
18314
18365
  console.log(`Ingestion complete. ${final.chunk_count ?? 0} chunks created.`);
18366
+ } else if (final.ingestion_status === "skipped") {
18367
+ console.log("Ingestion skipped (store-only document).");
18315
18368
  } else {
18316
18369
  console.error(`Ingestion failed: ${final.error ?? "unknown error"}`);
18317
18370
  process.exitCode = 1 /* Error */;
@@ -20507,13 +20560,10 @@ function registerMessagingCommands(program) {
20507
20560
  });
20508
20561
  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
20562
  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
- }
20563
+ const data = await ctx.api.post("/api/messaging/send/sms", {
20564
+ to: opts.to,
20565
+ from_number: opts.from,
20566
+ content: opts.content
20517
20567
  });
20518
20568
  if (isJson()) {
20519
20569
  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.65.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]