@theplato/tiro-cli 0.2.0 → 0.2.2

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/bin/tiro.js CHANGED
@@ -4,7 +4,28 @@
4
4
  import { Command as Command10 } from "commander";
5
5
 
6
6
  // src/lib/version.ts
7
- var VERSION = "0.1.0";
7
+ import { readFileSync } from "fs";
8
+ import { fileURLToPath } from "url";
9
+ import { dirname, resolve } from "path";
10
+ var HERE = dirname(fileURLToPath(import.meta.url));
11
+ var CANDIDATE_PATHS = [
12
+ resolve(HERE, "../../package.json"),
13
+ resolve(HERE, "../../../package.json")
14
+ ];
15
+ function readVersion() {
16
+ for (const path of CANDIDATE_PATHS) {
17
+ try {
18
+ const raw = readFileSync(path, "utf8");
19
+ const parsed = JSON.parse(raw);
20
+ if (typeof parsed.version === "string" && parsed.version.length > 0) {
21
+ return parsed.version;
22
+ }
23
+ } catch {
24
+ }
25
+ }
26
+ return "0.0.0-unknown";
27
+ }
28
+ var VERSION = readVersion();
8
29
 
9
30
  // src/lib/error.ts
10
31
  var ExitCode = {
@@ -175,8 +196,8 @@ async function startLoopbackServer() {
175
196
  );
176
197
  if (pendingResolve) settle(pendingResolve, { code, state });
177
198
  });
178
- await new Promise((resolve2) => {
179
- server.listen(0, "127.0.0.1", () => resolve2());
199
+ await new Promise((resolve4) => {
200
+ server.listen(0, "127.0.0.1", () => resolve4());
180
201
  });
181
202
  const address = server.address();
182
203
  const port = address.port;
@@ -185,7 +206,7 @@ async function startLoopbackServer() {
185
206
  redirectUri,
186
207
  port,
187
208
  waitForCallback(timeoutMs) {
188
- return new Promise((resolve2, reject) => {
209
+ return new Promise((resolve4, reject) => {
189
210
  const timer = setTimeout(() => {
190
211
  pendingResolve = null;
191
212
  pendingReject = null;
@@ -193,7 +214,7 @@ async function startLoopbackServer() {
193
214
  }, timeoutMs);
194
215
  pendingResolve = (r) => {
195
216
  clearTimeout(timer);
196
- resolve2(r);
217
+ resolve4(r);
197
218
  };
198
219
  pendingReject = (e) => {
199
220
  clearTimeout(timer);
@@ -971,15 +992,49 @@ function invalidDate(input) {
971
992
  );
972
993
  }
973
994
 
995
+ // src/lib/util/noteFilter.ts
996
+ var PLACEHOLDER_TITLE = "Untitled";
997
+ var PLACEHOLDER_SOURCE_TYPES = /* @__PURE__ */ new Set(["onboarding"]);
998
+ function isVisibleNote(note) {
999
+ if (note.title === PLACEHOLDER_TITLE) return false;
1000
+ if (note.sourceType !== null && note.sourceType !== void 0 && PLACEHOLDER_SOURCE_TYPES.has(note.sourceType)) {
1001
+ return false;
1002
+ }
1003
+ return true;
1004
+ }
1005
+
974
1006
  // src/commands/notes/list.ts
975
1007
  var ListResponseSchema = PageCursorResponseSchema(NoteSchema);
976
1008
  var DEFAULT_PAGE_SIZE = 100;
977
1009
  var MAX_PAGE_SIZE = 1e3;
1010
+ var HELP_AFTER = `
1011
+ Examples:
1012
+ tiro notes list --since 7d
1013
+ tiro notes list --keyword "OKR" --since 30d --json
1014
+ tiro notes list --folder <id> --limit 50
1015
+
1016
+ Keyword matching:
1017
+ --keyword reorders results by OpenSearch relevance (case-insensitive,
1018
+ full-text against note title and paragraph content). When --keyword is
1019
+ set, nextCursor is always null. Without --keyword, results are ordered
1020
+ by createdAt desc.
1021
+
1022
+ Note: placeholder notes (title='Untitled' or sourceType='onboarding') are
1023
+ filtered out by default. A page of N may return fewer than N visible notes \u2014
1024
+ keep paginating to fetch more, or pass --include-untitled to surface them.
1025
+ `;
978
1026
  function registerNotesList(parent) {
979
- parent.command("list").description("List notes (lightweight metadata)").option("--keyword <text>", "Reorder by OpenSearch relevance for this keyword").option("--folder <id>", "Restrict to a folder (recursive)").option("--since <date>", "ISO-8601 or relative (7d, 24h, 30m); maps to createdAtFrom").option("--until <date>", "ISO-8601 or relative; maps to createdAtTo").option(
1027
+ parent.command("list").description("List notes (lightweight metadata).").option("--keyword <text>", 'Reorder by OpenSearch relevance for this keyword (e.g. "OKR")').option("--folder <id>", "Restrict to a folder and its descendants").option(
1028
+ "--since <date>",
1029
+ "Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)"
1030
+ ).option("--until <date>", "Exclusive upper bound on createdAt").option(
980
1031
  "--limit <n>",
981
- `Page size (default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE})`
982
- ).option("--cursor <token>", "Cursor for the next page").action(async (opts, cmd) => {
1032
+ `Max results per page (default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE})`
1033
+ ).option("--cursor <token>", "Continue a previous page").option(
1034
+ "--include-untitled",
1035
+ "Include placeholder notes (title='Untitled' or sourceType='onboarding'). Default: hidden",
1036
+ false
1037
+ ).addHelpText("after", HELP_AFTER).action(async (opts, cmd) => {
983
1038
  const globalOpts = cmd.optsWithGlobals();
984
1039
  const client = createApiClient({
985
1040
  ...globalOpts.hostname !== void 0 && { hostnameOverride: globalOpts.hostname }
@@ -993,12 +1048,13 @@ function registerNotesList(parent) {
993
1048
  if (size !== void 0) params["size"] = size;
994
1049
  if (opts.cursor) params["cursor"] = opts.cursor;
995
1050
  const res = await client.getJson("/v1/external/notes", ListResponseSchema, params);
1051
+ const visible = opts.includeUntitled === true ? res.content : res.content.filter(isVisibleNote);
996
1052
  const mode = resolveOutputMode(globalOpts);
997
1053
  if (mode === "json") {
998
- for (const note of res.content) printNdjson(note);
1054
+ for (const note of visible) printNdjson(note);
999
1055
  if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });
1000
1056
  } else {
1001
- printPretty(res.content, res.nextCursor, globalOpts);
1057
+ printPretty(visible, res.nextCursor, globalOpts);
1002
1058
  }
1003
1059
  });
1004
1060
  }
@@ -1054,8 +1110,41 @@ import "commander";
1054
1110
  var SearchResponseSchema = PageCursorResponseSchema(NoteSchema).passthrough();
1055
1111
  var DEFAULT_PAGE_SIZE2 = 100;
1056
1112
  var MAX_PAGE_SIZE2 = 1e3;
1113
+ var HELP_AFTER2 = `
1114
+ Examples:
1115
+ tiro notes search "Q3 Planning"
1116
+ tiro notes search "Acme Corp" --since 7d --json
1117
+ tiro notes search "release" --since 2026-04-01 --until 2026-05-01
1118
+
1119
+ Keyword matching:
1120
+ Full-text against note title + paragraph content via OpenSearch.
1121
+ Case-insensitive. Multi-word keywords are tokenized \u2014 "OKR planning"
1122
+ matches notes containing both terms. The deep search variant (this
1123
+ command) hydrates each result with its primary documents (one-pager,
1124
+ custom) so an MCP/LLM client can read content alongside metadata in
1125
+ one call.
1126
+
1127
+ Note: placeholder notes (title='Untitled' or sourceType='onboarding') are
1128
+ filtered out by default. Pass --include-untitled to surface them.
1129
+ `;
1057
1130
  function registerNotesSearch(parent) {
1058
- parent.command("search [keyword]").description("Deep keyword search \u2014 returns notes hydrated with their primary documents").option("--keyword <text>", "Alternative to positional keyword").option("--folder <id>", "Restrict hits to a folder (recursive)").option("--since <date>", "ISO-8601 or relative (7d, 24h, 30m); maps to filter.createdAtFrom").option("--until <date>", "ISO-8601 or relative; maps to filter.createdAtTo").option("--limit <n>", `Page size (default ${DEFAULT_PAGE_SIZE2}, max ${MAX_PAGE_SIZE2})`).option("--cursor <token>", "Cursor for the next page (reserved \u2014 currently always null)").action(async (positional, opts, cmd) => {
1131
+ parent.command("search [keyword]").description("Deep keyword search \u2014 returns notes hydrated with their primary documents.").option(
1132
+ "--keyword <text>",
1133
+ 'Alternative to positional keyword (e.g. --keyword "Q3 Planning")'
1134
+ ).option("--folder <id>", "Restrict hits to a folder and its descendants").option(
1135
+ "--since <date>",
1136
+ "Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)"
1137
+ ).option("--until <date>", "Exclusive upper bound on createdAt").option(
1138
+ "--limit <n>",
1139
+ `Max results per page (default ${DEFAULT_PAGE_SIZE2}, max ${MAX_PAGE_SIZE2})`
1140
+ ).option(
1141
+ "--cursor <token>",
1142
+ "Continue a previous page (reserved \u2014 backend currently always null)"
1143
+ ).option(
1144
+ "--include-untitled",
1145
+ "Include placeholder notes. Default: hidden",
1146
+ false
1147
+ ).addHelpText("after", HELP_AFTER2).action(async (positional, opts, cmd) => {
1059
1148
  const globalOpts = cmd.optsWithGlobals();
1060
1149
  const keyword = (positional ?? opts.keyword ?? "").trim();
1061
1150
  if (!keyword) {
@@ -1088,12 +1177,13 @@ function registerNotesSearch(parent) {
1088
1177
  SearchResponseSchema,
1089
1178
  body
1090
1179
  );
1180
+ const visible = opts.includeUntitled === true ? res.content : res.content.filter(isVisibleNote);
1091
1181
  const mode = resolveOutputMode(globalOpts);
1092
1182
  if (mode === "json") {
1093
- for (const note of res.content) printNdjson(note);
1183
+ for (const note of visible) printNdjson(note);
1094
1184
  if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });
1095
1185
  } else {
1096
- printPretty2(res.content, res.nextCursor, globalOpts);
1186
+ printPretty2(visible, res.nextCursor, globalOpts);
1097
1187
  }
1098
1188
  });
1099
1189
  }
@@ -1130,10 +1220,10 @@ import "commander";
1130
1220
 
1131
1221
  // src/lib/output/file.ts
1132
1222
  import { mkdir, rename, stat, writeFile, access } from "fs/promises";
1133
- import { dirname, resolve } from "path";
1223
+ import { dirname as dirname2, resolve as resolve2 } from "path";
1134
1224
  async function writeFileAtomic(filepath, content, opts = {}) {
1135
- const absPath = resolve(filepath);
1136
- await mkdir(dirname(absPath), { recursive: true });
1225
+ const absPath = resolve2(filepath);
1226
+ await mkdir(dirname2(absPath), { recursive: true });
1137
1227
  if (!opts.force) {
1138
1228
  const exists = await fileExists(absPath);
1139
1229
  if (exists) {
@@ -1329,11 +1419,24 @@ var ALLOWED_INCLUDES = /* @__PURE__ */ new Set(["transcript"]);
1329
1419
  var ParagraphsListSchema = SimpleListResponseSchema(ParagraphSchema);
1330
1420
  var ParagraphsCursorSchema = PageCursorResponseSchema(ParagraphSchema);
1331
1421
  function registerNotesGet(parent) {
1332
- parent.command("get <guid>").description("Get a single note (stdout or file)").option("--output <path>", "Write to file (stdout becomes metadata only)").option("--format <md|json|txt>", "Output format (default: md for TTY, json for pipe)").option(
1422
+ parent.command("get <guid>").description("Get a single note. Outputs to stdout, or saves to a file with --output.").option("--output <path>", "Write to file (stdout becomes a single metadata line)").option(
1423
+ "--format <md|json|txt>",
1424
+ "Output format (default: md for TTY, json when piped)"
1425
+ ).option(
1333
1426
  "--include <items>",
1334
- "Comma-separated extras (v0.2.0 supports: transcript)",
1427
+ "Comma-separated extras (v0.2 supports: transcript)",
1335
1428
  ""
1336
- ).option("--force", "Overwrite existing file").action(async (guid, opts, cmd) => {
1429
+ ).option("--force", "Overwrite existing file at --output path").addHelpText("after", `
1430
+ Examples:
1431
+ tiro notes get <guid> # markdown to stdout
1432
+ tiro notes get <guid> --include transcript # add speaker-attributed paragraphs
1433
+ tiro notes get <guid> --output ./meeting.md --include transcript
1434
+ tiro notes get <guid> --format json # JSON to stdout
1435
+
1436
+ Tip for agents: prefer --output <path>. The actual content goes to disk
1437
+ and stdout collapses to a single metadata line, keeping your context
1438
+ window light.
1439
+ `).action(async (guid, opts, cmd) => {
1337
1440
  const globalOpts = cmd.optsWithGlobals();
1338
1441
  const includes = parseIncludes(opts.include);
1339
1442
  validateIncludes(includes);
@@ -1463,10 +1566,21 @@ import "commander";
1463
1566
  var ParagraphsListSchema2 = SimpleListResponseSchema(ParagraphSchema);
1464
1567
  var ParagraphsCursorSchema2 = PageCursorResponseSchema(ParagraphSchema);
1465
1568
  function registerNotesTranscript(parent) {
1466
- parent.command("transcript <guid>").description("Get the full transcript of a note (matches MCP get_note_transcript JSON shape)").option("--output <path>", "Write to file (stdout = metadata only)").option(
1569
+ parent.command("transcript <guid>").description(
1570
+ "Get the full transcript of a note as speaker-attributed paragraphs.\nJSON output matches MCP get_note_transcript shape exactly."
1571
+ ).option("--output <path>", "Write to file (stdout = single metadata line)").option(
1467
1572
  "--format <md|json|txt>",
1468
- "Output format (default: md for TTY, txt for pipe; json mirrors MCP shape)"
1469
- ).option("--force", "Overwrite existing file").action(async (guid, opts, cmd) => {
1573
+ "Output format (default: md if TTY, txt when piped; json mirrors MCP)"
1574
+ ).option("--force", "Overwrite existing file at --output path").addHelpText("after", `
1575
+ Examples:
1576
+ tiro notes transcript <guid> # md in TTY, txt in pipe
1577
+ tiro notes transcript <guid> --format md --output ./t.md
1578
+ tiro notes transcript <guid> --format json # MCP-shape JSON
1579
+ tiro notes transcript <guid> --format txt --output ./embed.txt
1580
+
1581
+ The --format json output is byte-for-byte identical to MCP's
1582
+ get_note_transcript so agents can swap surfaces without changing parsers.
1583
+ `).action(async (guid, opts, cmd) => {
1470
1584
  const globalOpts = cmd.optsWithGlobals();
1471
1585
  const format = pickFormat2(opts.format, opts.output, globalOpts);
1472
1586
  const client = createApiClient({
@@ -1560,21 +1674,74 @@ function registerNotes(program) {
1560
1674
  registerNotesTranscript(notes);
1561
1675
  }
1562
1676
 
1677
+ // src/lib/updateCheck.ts
1678
+ import updateNotifier from "update-notifier";
1679
+ import { readFile } from "fs/promises";
1680
+ import { fileURLToPath as fileURLToPath2 } from "url";
1681
+ import { dirname as dirname3, resolve as resolve3 } from "path";
1682
+ var HERE2 = dirname3(fileURLToPath2(import.meta.url));
1683
+ var CANDIDATE_PATHS2 = [
1684
+ resolve3(HERE2, "../../package.json"),
1685
+ resolve3(HERE2, "../../../package.json")
1686
+ ];
1687
+ var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
1688
+ async function startUpdateCheck() {
1689
+ if (process.env["NO_UPDATE_NOTIFIER"] === "1") return null;
1690
+ if (process.env["CI"]) return null;
1691
+ if (process.stdout.isTTY !== true) return null;
1692
+ const pkg = await loadPkg();
1693
+ if (!pkg) return null;
1694
+ try {
1695
+ const factory = updateNotifier;
1696
+ return factory({
1697
+ pkg,
1698
+ updateCheckInterval: ONE_DAY_MS,
1699
+ shouldNotifyInNpmScript: false
1700
+ });
1701
+ } catch {
1702
+ return null;
1703
+ }
1704
+ }
1705
+ function emitUpdateBanner(notifier) {
1706
+ if (!notifier) return;
1707
+ if (!notifier.update) return;
1708
+ notifier.notify({
1709
+ isGlobal: true,
1710
+ defer: false,
1711
+ message: "Update available {currentVersion} \u2192 {latestVersion}\nRun npm install -g {packageName} to update\n\nChangelog: https://www.npmjs.com/package/{packageName}?activeTab=versions"
1712
+ });
1713
+ }
1714
+ async function loadPkg() {
1715
+ for (const path of CANDIDATE_PATHS2) {
1716
+ try {
1717
+ const raw = await readFile(path, "utf8");
1718
+ const parsed = JSON.parse(raw);
1719
+ if (typeof parsed.name === "string" && typeof parsed.version === "string" && parsed.name.length > 0 && parsed.version.length > 0) {
1720
+ return { name: parsed.name, version: parsed.version };
1721
+ }
1722
+ } catch {
1723
+ }
1724
+ }
1725
+ return null;
1726
+ }
1727
+
1563
1728
  // src/bin/tiro.ts
1564
1729
  var EXAMPLES = `
1565
1730
  EXAMPLES
1566
1731
  $ tiro auth login
1567
- $ tiro notes search --speaker "\uAE40\uCCA0\uC218" --since 7d --json
1732
+ $ tiro notes list --since 7d
1733
+ $ tiro notes search "Q3 Planning" --since 30d --json
1568
1734
  $ tiro notes get <guid> --output ./meeting.md --include transcript
1569
- $ tiro notes transcript <guid> --format txt
1735
+ $ tiro notes transcript <guid> --format md --output ./transcript.md
1570
1736
 
1571
1737
  ENVIRONMENT
1572
- TIRO_TOKEN Bearer token (overrides keychain)
1573
- TIRO_HOSTNAME API base URL (default: https://api.tiro.ooo)
1574
- NO_COLOR Disable colors
1738
+ TIRO_TOKEN Bearer token (overrides keychain \u2014 for CI / agents)
1739
+ TIRO_HOSTNAME API base URL (default: https://api.tiro.ooo)
1740
+ NO_COLOR Disable colors (https://no-color.org)
1741
+ NO_UPDATE_NOTIFIER Set to "1" to disable the update banner
1575
1742
 
1576
1743
  DOCS
1577
- https://api.tiro.ooo/cli
1744
+ https://api-docs.tiro.ooo/cli
1578
1745
  `;
1579
1746
  function buildProgram() {
1580
1747
  const program = new Command10();
@@ -1586,8 +1753,10 @@ function buildProgram() {
1586
1753
  }
1587
1754
  async function main() {
1588
1755
  const program = buildProgram();
1756
+ const notifier = await startUpdateCheck();
1589
1757
  try {
1590
1758
  await program.parseAsync(process.argv);
1759
+ emitUpdateBanner(notifier);
1591
1760
  } catch (err) {
1592
1761
  handleError(err, program);
1593
1762
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/tiro.ts","../../src/lib/version.ts","../../src/lib/error.ts","../../src/lib/output/tty.ts","../../src/lib/output/print.ts","../../src/commands/auth/index.ts","../../src/commands/auth/login.ts","../../src/lib/auth/flow.ts","../../src/lib/auth/pkce.ts","../../src/lib/auth/loopback.ts","../../src/lib/auth/browser.ts","../../src/lib/auth/keychain.ts","../../src/lib/auth/token.ts","../../src/lib/config.ts","../../src/commands/auth/status.ts","../../src/commands/auth/logout.ts","../../src/commands/notes/index.ts","../../src/commands/notes/list.ts","../../src/lib/api/client.ts","../../src/lib/api/types.ts","../../src/lib/util/parseDate.ts","../../src/commands/notes/search.ts","../../src/commands/notes/get.ts","../../src/lib/output/file.ts","../../src/lib/output/transcript.ts","../../src/lib/output/format.ts","../../src/commands/notes/transcript.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { VERSION } from \"../lib/version.ts\";\nimport { TiroError, ExitCode } from \"../lib/error.ts\";\nimport { printError } from \"../lib/output/print.ts\";\nimport { color } from \"../lib/output/tty.ts\";\nimport { registerAuth } from \"../commands/auth/index.ts\";\nimport { registerNotes } from \"../commands/notes/index.ts\";\n\nconst EXAMPLES = `\nEXAMPLES\n $ tiro auth login\n $ tiro notes search --speaker \"김철수\" --since 7d --json\n $ tiro notes get <guid> --output ./meeting.md --include transcript\n $ tiro notes transcript <guid> --format txt\n\nENVIRONMENT\n TIRO_TOKEN Bearer token (overrides keychain)\n TIRO_HOSTNAME API base URL (default: https://api.tiro.ooo)\n NO_COLOR Disable colors\n\nDOCS\n https://api.tiro.ooo/cli\n`;\n\nfunction buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"tiro\")\n .description(\"Tiro AI notes & transcripts — agent-first command line\")\n .version(VERSION, \"-v, --version\", \"Print version\")\n .option(\"--hostname <url>\", \"API base URL (default: https://api.tiro.ooo)\")\n .option(\"--json\", \"Force JSON output\")\n .option(\"--pretty\", \"Force pretty (human) output\")\n .option(\"--quiet\", \"Suppress non-error output\")\n .option(\"--verbose\", \"Verbose logging to stderr\")\n .option(\"--no-color\", \"Disable ANSI colors\")\n .addHelpText(\"after\", EXAMPLES);\n\n program.showHelpAfterError(\"(run `tiro --help` for available commands)\");\n\n registerAuth(program);\n registerNotes(program);\n\n return program;\n}\n\nasync function main(): Promise<void> {\n const program = buildProgram();\n try {\n await program.parseAsync(process.argv);\n } catch (err) {\n handleError(err, program);\n }\n}\n\nfunction handleError(err: unknown, program: Command): never {\n const opts = program.opts<{ json?: boolean; quiet?: boolean }>();\n\n if (err instanceof TiroError) {\n if (opts.json) {\n printError(err.toJSON());\n } else if (!opts.quiet) {\n process.stderr.write(`${color(\"✗\", \"red\", opts)} ${err.message}\\n`);\n if (err.suggestion) {\n process.stderr.write(` ${color(\"→\", \"gray\", opts)} ${err.suggestion}\\n`);\n }\n }\n process.exit(err.exitCode);\n }\n\n if (err instanceof Error) {\n if (opts.json) {\n printError({\n ok: false,\n error: { code: \"internal_error\", message: err.message, errorType: \"internal_error\" },\n });\n } else if (!opts.quiet) {\n process.stderr.write(`${color(\"✗\", \"red\", opts)} ${err.message}\\n`);\n }\n process.exit(ExitCode.Generic);\n }\n\n process.stderr.write(`Unknown error: ${String(err)}\\n`);\n process.exit(ExitCode.Generic);\n}\n\nmain().catch((err) => {\n process.stderr.write(`Fatal: ${String(err)}\\n`);\n process.exit(ExitCode.Generic);\n});\n","export const VERSION = \"0.1.0\";\n","export const ExitCode = {\n Ok: 0,\n Generic: 1,\n Usage: 2,\n AuthRequired: 4,\n ExUsage: 64,\n ExDataErr: 65,\n ExConfig: 78,\n} as const;\n\nexport type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode];\n\nexport type ErrorType =\n | \"bad_request\"\n | \"unauthorized\"\n | \"forbidden\"\n | \"not_found\"\n | \"not_acceptable\"\n | \"conflict\"\n | \"payload_too_large\"\n | \"unprocessable_entity\"\n | \"too_many_requests\"\n | \"internal_error\"\n | \"auth_required\"\n | \"config_missing\"\n | \"network_error\";\n\nexport interface ErrorPayload {\n code: string;\n message: string;\n suggestion?: string;\n errorType?: ErrorType;\n httpStatus?: number;\n requestId?: string;\n}\n\nexport class TiroError extends Error {\n readonly code: string;\n readonly suggestion?: string;\n readonly errorType?: ErrorType;\n readonly httpStatus?: number;\n readonly requestId?: string;\n readonly exitCode: ExitCodeValue;\n\n constructor(payload: ErrorPayload, exitCode: ExitCodeValue = ExitCode.Generic) {\n super(payload.message);\n this.name = \"TiroError\";\n this.code = payload.code;\n this.suggestion = payload.suggestion;\n this.errorType = payload.errorType;\n this.httpStatus = payload.httpStatus;\n this.requestId = payload.requestId;\n this.exitCode = exitCode;\n }\n\n toJSON(): { ok: false; error: ErrorPayload } {\n return {\n ok: false,\n error: {\n code: this.code,\n message: this.message,\n ...(this.suggestion !== undefined && { suggestion: this.suggestion }),\n ...(this.errorType !== undefined && { errorType: this.errorType }),\n ...(this.httpStatus !== undefined && { httpStatus: this.httpStatus }),\n ...(this.requestId !== undefined && { requestId: this.requestId }),\n },\n };\n }\n}\n\nexport function authRequired(): TiroError {\n return new TiroError(\n {\n code: \"auth_required\",\n message:\n \"Not authenticated. Run `tiro auth login` to sign in, or set TIRO_TOKEN env var.\",\n suggestion: \"tiro auth login\",\n errorType: \"auth_required\",\n },\n ExitCode.AuthRequired,\n );\n}\n\nexport function configMissing(message: string, suggestion?: string): TiroError {\n return new TiroError(\n {\n code: \"config_missing\",\n message,\n ...(suggestion !== undefined && { suggestion }),\n errorType: \"config_missing\",\n },\n ExitCode.ExConfig,\n );\n}\n","export type OutputMode = \"json\" | \"pretty\";\n\nexport interface OutputOptions {\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function resolveOutputMode(opts: OutputOptions): OutputMode {\n if (opts.json) return \"json\";\n if (opts.pretty) return \"pretty\";\n return process.stdout.isTTY ? \"pretty\" : \"json\";\n}\n\nexport function colorEnabled(opts: OutputOptions): boolean {\n if (opts.noColor) return false;\n if (process.env[\"NO_COLOR\"]) return false;\n if (process.env[\"FORCE_COLOR\"]) return true;\n return process.stdout.isTTY === true;\n}\n\nconst ANSI = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n gray: \"\\x1b[90m\",\n} as const;\n\nexport function color(\n text: string,\n style: keyof typeof ANSI,\n opts: OutputOptions = {},\n): string {\n if (!colorEnabled(opts)) return text;\n return `${ANSI[style]}${text}${ANSI.reset}`;\n}\n","import { resolveOutputMode, type OutputOptions } from \"./tty.ts\";\n\nexport function printOutput(value: unknown, opts: OutputOptions = {}): void {\n if (opts.quiet) return;\n const mode = resolveOutputMode(opts);\n if (mode === \"json\") {\n process.stdout.write(`${JSON.stringify(value)}\\n`);\n } else {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n }\n}\n\nexport function printError(value: unknown): void {\n process.stderr.write(`${JSON.stringify(value)}\\n`);\n}\n\nexport function printNdjson(item: unknown): void {\n process.stdout.write(`${JSON.stringify(item)}\\n`);\n}\n","import { Command } from \"commander\";\nimport { registerAuthLogin } from \"./login.ts\";\nimport { registerAuthStatus } from \"./status.ts\";\nimport { registerAuthLogout } from \"./logout.ts\";\n\nexport function registerAuth(program: Command): void {\n const auth = program.command(\"auth\").description(\"Manage authentication\");\n registerAuthLogin(auth);\n registerAuthStatus(auth);\n registerAuthLogout(auth);\n}\n","import { Command } from \"commander\";\nimport { performLogin } from \"../../lib/auth/flow.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { color } from \"../../lib/output/tty.ts\";\nimport { getHostname } from \"../../lib/config.ts\";\n\ninterface LoginOptions {\n hostname?: string;\n noBrowser?: boolean;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function registerAuthLogin(parent: Command): void {\n parent\n .command(\"login\")\n .description(\"Sign in to Tiro via OAuth (browser-based, PKCE)\")\n .option(\"--hostname <url>\", \"API base URL (overrides config / TIRO_HOSTNAME)\")\n .option(\"--no-browser\", \"Print the URL instead of opening a browser\")\n .action(async (opts: LoginOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<LoginOptions>();\n const result = await performLogin({\n ...(opts.hostname !== undefined && { hostname: opts.hostname }),\n noBrowser: opts.noBrowser === true,\n onPrompt: (msg) => {\n if (globalOpts.quiet) return;\n process.stderr.write(`${color(msg, \"cyan\", globalOpts)}\\n`);\n },\n });\n\n const hostname = getHostname(opts.hostname);\n const expiresIso = new Date(result.expiresAt).toISOString();\n\n if (globalOpts.json) {\n printOutput(\n {\n ok: true,\n data: {\n signedIn: true,\n hostname,\n userId: result.userId ?? null,\n expiresAt: expiresIso,\n },\n },\n globalOpts,\n );\n } else if (!globalOpts.quiet) {\n process.stderr.write(`${color(\"✓\", \"green\", globalOpts)} Signed in to ${hostname}\\n`);\n if (result.userId) {\n process.stderr.write(` user: ${result.userId}\\n`);\n }\n process.stderr.write(` token expires: ${expiresIso}\\n`);\n }\n });\n}\n","import { z } from \"zod\";\nimport { TiroError, ExitCode } from \"../error.ts\";\nimport { generatePkce, generateState } from \"./pkce.ts\";\nimport { startLoopbackServer } from \"./loopback.ts\";\nimport { openBrowser } from \"./browser.ts\";\nimport { saveToken, type StoredToken } from \"./keychain.ts\";\nimport { decodeJwtPayload } from \"./token.ts\";\nimport {\n getHostname,\n getOauthClientId,\n setOauthClientId,\n clearOauthClientId,\n} from \"../config.ts\";\n\nconst RegisterResponseSchema = z.object({\n client_id: z.string(),\n client_secret: z.string().optional(),\n});\n\nconst TokenResponseSchema = z.object({\n access_token: z.string(),\n token_type: z.string(),\n expires_in: z.number().optional(),\n scope: z.string().optional(),\n});\n\nconst CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;\nconst DEFAULT_SCOPE = \"mcp:notes:read\";\n\nexport interface LoginOptions {\n hostname?: string;\n noBrowser?: boolean;\n scope?: string;\n onPrompt?: (msg: string) => void;\n}\n\nexport interface LoginResult {\n hostname: string;\n userId: string | undefined;\n expiresAt: number;\n}\n\nexport async function performLogin(options: LoginOptions = {}): Promise<LoginResult> {\n const hostname = getHostname(options.hostname);\n const onPrompt = options.onPrompt ?? ((msg: string) => process.stderr.write(`${msg}\\n`));\n\n const loopback = await startLoopbackServer();\n\n try {\n const clientId = await ensureOauthClient(hostname, loopback.redirectUri);\n const { codeVerifier, codeChallenge } = generatePkce();\n const state = generateState();\n\n const authorizeUrl = buildAuthorizeUrl({\n hostname,\n clientId,\n redirectUri: loopback.redirectUri,\n state,\n codeChallenge,\n scope: options.scope ?? DEFAULT_SCOPE,\n });\n\n if (options.noBrowser) {\n onPrompt(`Open this URL in your browser:\\n${authorizeUrl}`);\n } else {\n onPrompt(`Opening browser for sign-in...`);\n onPrompt(`If the browser does not open, visit:\\n${authorizeUrl}`);\n await openBrowser(authorizeUrl);\n }\n\n const callback = await loopback.waitForCallback(CALLBACK_TIMEOUT_MS);\n\n if (callback.state !== state) {\n throw new TiroError(\n {\n code: \"auth_state_mismatch\",\n message: \"OAuth state mismatch — possible CSRF. Aborting.\",\n errorType: \"unauthorized\",\n },\n ExitCode.Generic,\n );\n }\n\n const tokenRes = await exchangeToken({\n hostname,\n clientId,\n code: callback.code,\n redirectUri: loopback.redirectUri,\n codeVerifier,\n });\n\n const expiresAt = computeExpiry(tokenRes.expires_in);\n const payload = decodeJwtPayload(tokenRes.access_token);\n const userId = typeof payload?.[\"sub\"] === \"string\" ? (payload[\"sub\"] as string) : undefined;\n\n const stored: StoredToken = {\n accessToken: tokenRes.access_token,\n tokenType: tokenRes.token_type,\n expiresAt,\n hostname,\n ...(tokenRes.scope !== undefined && { scope: tokenRes.scope }),\n ...(userId !== undefined && { userId }),\n };\n saveToken(stored);\n\n return { hostname, userId, expiresAt };\n } finally {\n loopback.close();\n }\n}\n\nasync function ensureOauthClient(hostname: string, redirectUri: string): Promise<string> {\n const cached = getOauthClientId();\n if (cached) return cached;\n\n const url = `${hostname}/v1/mcp/oauth/register`;\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_name: \"tiro-cli\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: DEFAULT_SCOPE,\n }),\n });\n } catch (err) {\n throw new TiroError(\n {\n code: \"network_error\",\n message: `Failed to reach ${hostname}: ${(err as Error).message}`,\n errorType: \"network_error\",\n suggestion: \"Check your network connection or --hostname.\",\n },\n ExitCode.Generic,\n );\n }\n\n if (!res.ok) {\n const detail = await safeText(res);\n throw new TiroError(\n {\n code: \"oauth_register_failed\",\n message: `Dynamic Client Registration failed: HTTP ${res.status}`,\n errorType: \"internal_error\",\n httpStatus: res.status,\n ...(detail !== \"\" && { suggestion: detail.slice(0, 200) }),\n },\n ExitCode.Generic,\n );\n }\n\n const json = (await res.json()) as unknown;\n const parsed = RegisterResponseSchema.safeParse(json);\n if (!parsed.success) {\n throw new TiroError(\n {\n code: \"oauth_register_invalid\",\n message: \"Registration response did not match expected shape.\",\n errorType: \"internal_error\",\n },\n ExitCode.Generic,\n );\n }\n\n setOauthClientId(parsed.data.client_id);\n return parsed.data.client_id;\n}\n\ninterface AuthorizeUrlInput {\n hostname: string;\n clientId: string;\n redirectUri: string;\n state: string;\n codeChallenge: string;\n scope: string;\n}\n\nfunction buildAuthorizeUrl(input: AuthorizeUrlInput): string {\n const u = new URL(`${input.hostname}/v1/mcp/oauth/authorize`);\n u.searchParams.set(\"response_type\", \"code\");\n u.searchParams.set(\"client_id\", input.clientId);\n u.searchParams.set(\"redirect_uri\", input.redirectUri);\n u.searchParams.set(\"state\", input.state);\n u.searchParams.set(\"code_challenge\", input.codeChallenge);\n u.searchParams.set(\"code_challenge_method\", \"S256\");\n u.searchParams.set(\"scope\", input.scope);\n return u.toString();\n}\n\ninterface ExchangeInput {\n hostname: string;\n clientId: string;\n code: string;\n redirectUri: string;\n codeVerifier: string;\n}\n\nasync function exchangeToken(input: ExchangeInput): Promise<z.infer<typeof TokenResponseSchema>> {\n const url = `${input.hostname}/v1/mcp/oauth/token`;\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: input.redirectUri,\n client_id: input.clientId,\n code_verifier: input.codeVerifier,\n });\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n } catch (err) {\n throw new TiroError(\n {\n code: \"network_error\",\n message: `Failed to reach ${input.hostname}: ${(err as Error).message}`,\n errorType: \"network_error\",\n },\n ExitCode.Generic,\n );\n }\n\n if (!res.ok) {\n if (res.status === 400 || res.status === 401) {\n // Cached client_id may have expired (Redis 30-day TTL). Force re-registration on next try.\n clearOauthClientId();\n }\n const detail = await safeText(res);\n throw new TiroError(\n {\n code: \"oauth_token_failed\",\n message: `Token exchange failed: HTTP ${res.status}`,\n errorType: \"unauthorized\",\n httpStatus: res.status,\n ...(detail !== \"\" && { suggestion: detail.slice(0, 200) }),\n },\n ExitCode.AuthRequired,\n );\n }\n\n const json = (await res.json()) as unknown;\n const parsed = TokenResponseSchema.safeParse(json);\n if (!parsed.success) {\n throw new TiroError(\n {\n code: \"oauth_token_invalid\",\n message: \"Token response did not match expected shape.\",\n errorType: \"internal_error\",\n },\n ExitCode.Generic,\n );\n }\n return parsed.data;\n}\n\nfunction computeExpiry(expiresIn?: number): number {\n // McpJwtService issues 180-day tokens; if expires_in absent, fall back to 180 days.\n const fallbackSeconds = 180 * 24 * 60 * 60;\n const seconds = expiresIn ?? fallbackSeconds;\n return Date.now() + seconds * 1000;\n}\n\nasync function safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return \"\";\n }\n}\n","import { createHash, randomBytes } from \"node:crypto\";\n\nexport interface PkcePair {\n codeVerifier: string;\n codeChallenge: string;\n method: \"S256\";\n}\n\nexport function generatePkce(): PkcePair {\n const codeVerifier = base64url(randomBytes(32));\n const codeChallenge = base64url(createHash(\"sha256\").update(codeVerifier).digest());\n return { codeVerifier, codeChallenge, method: \"S256\" };\n}\n\nexport function generateState(): string {\n return base64url(randomBytes(24));\n}\n\nfunction base64url(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n","import http from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\nexport interface CallbackResult {\n code: string;\n state: string;\n}\n\nexport interface LoopbackServer {\n redirectUri: string;\n port: number;\n waitForCallback: (timeoutMs: number) => Promise<CallbackResult>;\n close: () => void;\n}\n\nexport async function startLoopbackServer(): Promise<LoopbackServer> {\n let pendingResolve: ((r: CallbackResult) => void) | null = null;\n let pendingReject: ((e: Error) => void) | null = null;\n\n const settle = (\n fn: ((arg: CallbackResult) => void) | ((arg: Error) => void),\n arg: CallbackResult | Error,\n ): void => {\n pendingResolve = null;\n pendingReject = null;\n (fn as (arg: CallbackResult | Error) => void)(arg);\n };\n\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400).end();\n return;\n }\n const url = new URL(req.url, `http://127.0.0.1`);\n if (url.pathname !== \"/callback\") {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" }).end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n const errorDesc = url.searchParams.get(\"error_description\") ?? \"\";\n\n if (error) {\n const msg = `OAuth error: ${error}${errorDesc ? ` — ${errorDesc}` : \"\"}`;\n respondPage(res, 500, \"Login failed\", msg);\n if (pendingReject) settle(pendingReject, new Error(msg));\n return;\n }\n if (!code || !state) {\n respondPage(res, 400, \"Missing parameters\", \"Missing `code` or `state`.\");\n if (pendingReject) settle(pendingReject, new Error(\"Missing code or state\"));\n return;\n }\n\n respondPage(\n res,\n 200,\n \"Login successful\",\n \"You're signed in. You can close this tab and return to the terminal.\",\n );\n if (pendingResolve) settle(pendingResolve, { code, state });\n });\n\n await new Promise<void>((resolve) => {\n server.listen(0, \"127.0.0.1\", () => resolve());\n });\n\n const address = server.address() as AddressInfo;\n const port = address.port;\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n return {\n redirectUri,\n port,\n waitForCallback(timeoutMs: number) {\n return new Promise<CallbackResult>((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingResolve = null;\n pendingReject = null;\n reject(new Error(`Timed out waiting for OAuth callback (${timeoutMs}ms)`));\n }, timeoutMs);\n pendingResolve = (r) => {\n clearTimeout(timer);\n resolve(r);\n };\n pendingReject = (e) => {\n clearTimeout(timer);\n reject(e);\n };\n });\n },\n close() {\n server.close();\n },\n };\n}\n\nfunction respondPage(\n res: http.ServerResponse,\n status: number,\n title: string,\n body: string,\n): void {\n const html = `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>${title}</title>\n <style>\n body { font-family: -apple-system, system-ui, sans-serif; padding: 4rem; max-width: 32rem; margin: 0 auto; color: #1a1a1a; }\n h1 { font-size: 1.5rem; margin-bottom: 1rem; }\n p { color: #555; line-height: 1.5; }\n </style>\n</head>\n<body>\n <h1>${title}</h1>\n <p>${body}</p>\n</body>\n</html>`;\n res.writeHead(status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(html);\n}\n","import open from \"open\";\n\nexport async function openBrowser(url: string): Promise<void> {\n try {\n await open(url, { wait: false });\n } catch {\n // Best-effort. Caller already prints the URL for manual fallback.\n }\n}\n","import { Entry } from \"@napi-rs/keyring\";\nimport { TiroError, ExitCode } from \"../error.ts\";\n\nconst SERVICE = \"io.tiro.cli\";\nconst ACCOUNT = \"default\";\n\nexport interface StoredToken {\n accessToken: string;\n tokenType: string;\n expiresAt: number;\n scope?: string;\n hostname: string;\n userId?: string;\n}\n\nexport function saveToken(token: StoredToken): void {\n const entry = new Entry(SERVICE, ACCOUNT);\n try {\n entry.setPassword(JSON.stringify(token));\n } catch (err) {\n throw new TiroError(\n {\n code: \"keychain_write_failed\",\n message: `Failed to write to OS keychain: ${(err as Error).message}`,\n errorType: \"internal_error\",\n suggestion:\n process.platform === \"linux\"\n ? \"Linux requires a Secret Service daemon (gnome-keyring or kwallet). Or set TIRO_TOKEN env var.\"\n : \"Check OS keychain permissions, or set TIRO_TOKEN env var.\",\n },\n ExitCode.Generic,\n );\n }\n}\n\nexport function loadToken(): StoredToken | null {\n const entry = new Entry(SERVICE, ACCOUNT);\n let raw: string | null;\n try {\n raw = entry.getPassword();\n } catch {\n return null;\n }\n if (!raw) return null;\n try {\n return JSON.parse(raw) as StoredToken;\n } catch {\n return null;\n }\n}\n\nexport function deleteToken(): boolean {\n const entry = new Entry(SERVICE, ACCOUNT);\n try {\n return entry.deletePassword();\n } catch {\n return false;\n }\n}\n","import { loadToken, type StoredToken } from \"./keychain.ts\";\nimport { authRequired } from \"../error.ts\";\n\nexport interface ResolvedToken {\n accessToken: string;\n source: \"env\" | \"keychain\";\n hostname?: string;\n expiresAt?: number;\n userId?: string;\n}\n\nexport function resolveToken(): ResolvedToken | null {\n const envToken = process.env[\"TIRO_TOKEN\"];\n if (envToken) {\n return { accessToken: envToken, source: \"env\" };\n }\n const stored = loadToken();\n if (stored) {\n return {\n accessToken: stored.accessToken,\n source: \"keychain\",\n hostname: stored.hostname,\n expiresAt: stored.expiresAt,\n ...(stored.userId !== undefined && { userId: stored.userId }),\n };\n }\n return null;\n}\n\nexport function requireToken(): ResolvedToken {\n const t = resolveToken();\n if (!t) throw authRequired();\n return t;\n}\n\nexport function decodeJwtPayload(token: string): Record<string, unknown> | null {\n const parts = token.split(\".\");\n if (parts.length !== 3) return null;\n try {\n const payload = parts[1];\n if (!payload) return null;\n const json = Buffer.from(payload, \"base64url\").toString(\"utf8\");\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport function isTokenExpired(stored: StoredToken): boolean {\n return Date.now() >= stored.expiresAt;\n}\n","import Conf from \"conf\";\n\ninterface TiroConfigSchema {\n hostname: string;\n oauthClientId: string | null;\n oauthClientIdRegisteredAt: number | null;\n defaultOutputDir: string | null;\n}\n\nconst DEFAULT_HOSTNAME = \"https://api.tiro.ooo\";\n\nconst config = new Conf<TiroConfigSchema>({\n projectName: \"tiro\",\n defaults: {\n hostname: DEFAULT_HOSTNAME,\n oauthClientId: null,\n oauthClientIdRegisteredAt: null,\n defaultOutputDir: null,\n },\n});\n\nexport function getHostname(override?: string): string {\n if (override) return stripTrailingSlash(override);\n const env = process.env[\"TIRO_HOSTNAME\"];\n if (env) return stripTrailingSlash(env);\n return stripTrailingSlash(config.get(\"hostname\"));\n}\n\nexport function setHostname(hostname: string): void {\n config.set(\"hostname\", stripTrailingSlash(hostname));\n}\n\nexport function getOauthClientId(): string | null {\n const id = config.get(\"oauthClientId\");\n const registeredAt = config.get(\"oauthClientIdRegisteredAt\");\n if (!id || !registeredAt) return null;\n // DCR clients have 30-day TTL on the backend (Redis). Treat them as expired\n // a day earlier to avoid edge-case 401s during exchange.\n const ttlMs = 29 * 24 * 60 * 60 * 1000;\n if (Date.now() - registeredAt > ttlMs) return null;\n return id;\n}\n\nexport function setOauthClientId(clientId: string): void {\n config.set(\"oauthClientId\", clientId);\n config.set(\"oauthClientIdRegisteredAt\", Date.now());\n}\n\nexport function clearOauthClientId(): void {\n config.set(\"oauthClientId\", null);\n config.set(\"oauthClientIdRegisteredAt\", null);\n}\n\nexport function getDefaultOutputDir(): string | null {\n const env = process.env[\"TIRO_OUTPUT_DIR\"];\n if (env) return env;\n return config.get(\"defaultOutputDir\");\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n\nfunction stripTrailingSlash(s: string): string {\n return s.endsWith(\"/\") ? s.slice(0, -1) : s;\n}\n","import { Command } from \"commander\";\nimport { resolveToken, decodeJwtPayload } from \"../../lib/auth/token.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { color } from \"../../lib/output/tty.ts\";\nimport { authRequired } from \"../../lib/error.ts\";\n\ninterface StatusReport {\n signedIn: boolean;\n source: \"env\" | \"keychain\";\n hostname: string | null;\n userId: string | null;\n scope: string | null;\n expiresAt: string | null;\n expired: boolean;\n tokenPrefix: string;\n}\n\ninterface StatusOptions {\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function registerAuthStatus(parent: Command): void {\n parent\n .command(\"status\")\n .description(\"Show current authenticated account and scopes\")\n .action(async (_opts: StatusOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<StatusOptions>();\n const t = resolveToken();\n if (!t) {\n throw authRequired();\n }\n\n const payload = decodeJwtPayload(t.accessToken);\n const sub = typeof payload?.[\"sub\"] === \"string\" ? (payload[\"sub\"] as string) : null;\n const exp = typeof payload?.[\"exp\"] === \"number\" ? (payload[\"exp\"] as number) * 1000 : null;\n const scope = typeof payload?.[\"scope\"] === \"string\" ? (payload[\"scope\"] as string) : null;\n\n const expMs = exp ?? t.expiresAt ?? null;\n const expired = expMs !== null && Date.now() >= expMs;\n\n const report: StatusReport = {\n signedIn: true,\n source: t.source,\n hostname: t.hostname ?? null,\n userId: t.userId ?? sub,\n scope,\n expiresAt: expMs ? new Date(expMs).toISOString() : null,\n expired,\n tokenPrefix: `${t.accessToken.slice(0, 4)}...***`,\n };\n\n if (globalOpts.json || !process.stdout.isTTY) {\n printOutput({ ok: true, data: report }, globalOpts);\n } else {\n const headIcon = expired ? color(\"!\", \"yellow\", globalOpts) : color(\"✓\", \"green\", globalOpts);\n const headText = expired ? \"Token expired\" : \"Signed in\";\n process.stdout.write(`${headIcon} ${headText}\\n`);\n process.stdout.write(` source: ${report.source}\\n`);\n if (report.hostname) process.stdout.write(` hostname: ${report.hostname}\\n`);\n if (report.userId) process.stdout.write(` user: ${report.userId}\\n`);\n if (report.scope) process.stdout.write(` scope: ${report.scope}\\n`);\n if (report.expiresAt) {\n const tag = expired ? color(\" (expired)\", \"red\", globalOpts) : \"\";\n process.stdout.write(` expires at: ${report.expiresAt}${tag}\\n`);\n }\n process.stdout.write(` token: ${report.tokenPrefix}\\n`);\n if (expired) {\n process.stdout.write(\n `\\n${color(\"→\", \"gray\", globalOpts)} Run \\`tiro auth login\\` to refresh.\\n`,\n );\n }\n }\n });\n}\n","import { Command } from \"commander\";\nimport { deleteToken } from \"../../lib/auth/keychain.ts\";\nimport { clearOauthClientId } from \"../../lib/config.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { color } from \"../../lib/output/tty.ts\";\n\ninterface LogoutOptions {\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function registerAuthLogout(parent: Command): void {\n parent\n .command(\"logout\")\n .description(\"Sign out and clear the stored token\")\n .action(async (_opts: LogoutOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<LogoutOptions>();\n const removed = deleteToken();\n clearOauthClientId();\n\n if (globalOpts.json) {\n printOutput({ ok: true, data: { signedOut: true, hadToken: removed } }, globalOpts);\n } else if (!globalOpts.quiet) {\n if (removed) {\n process.stderr.write(`${color(\"✓\", \"green\", globalOpts)} Signed out\\n`);\n } else {\n process.stderr.write(`${color(\"•\", \"gray\", globalOpts)} No token was stored\\n`);\n }\n }\n });\n}\n","import { Command } from \"commander\";\nimport { registerNotesList } from \"./list.ts\";\nimport { registerNotesSearch } from \"./search.ts\";\nimport { registerNotesGet } from \"./get.ts\";\nimport { registerNotesTranscript } from \"./transcript.ts\";\n\nexport function registerNotes(program: Command): void {\n const notes = program.command(\"notes\").description(\"List, search, and download notes\");\n registerNotesList(notes);\n registerNotesSearch(notes);\n registerNotesGet(notes);\n registerNotesTranscript(notes);\n}\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport { NoteSchema, PageCursorResponseSchema } from \"../../lib/api/types.ts\";\nimport { printNdjson } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode, color } from \"../../lib/output/tty.ts\";\nimport { parseDate } from \"../../lib/util/parseDate.ts\";\n\ninterface ListOptions {\n keyword?: string;\n folder?: string;\n since?: string;\n until?: string;\n limit?: string;\n cursor?: string;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst ListResponseSchema = PageCursorResponseSchema(NoteSchema);\n\nconst DEFAULT_PAGE_SIZE = 100;\nconst MAX_PAGE_SIZE = 1000;\n\nexport function registerNotesList(parent: Command): void {\n parent\n .command(\"list\")\n .description(\"List notes (lightweight metadata)\")\n .option(\"--keyword <text>\", \"Reorder by OpenSearch relevance for this keyword\")\n .option(\"--folder <id>\", \"Restrict to a folder (recursive)\")\n .option(\"--since <date>\", \"ISO-8601 or relative (7d, 24h, 30m); maps to createdAtFrom\")\n .option(\"--until <date>\", \"ISO-8601 or relative; maps to createdAtTo\")\n .option(\n \"--limit <n>\",\n `Page size (default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE})`,\n )\n .option(\"--cursor <token>\", \"Cursor for the next page\")\n .action(async (opts: ListOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<ListOptions>();\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const params: Record<string, string | number | undefined> = {};\n if (opts.keyword) params[\"keyword\"] = opts.keyword;\n if (opts.folder) params[\"folderId\"] = opts.folder;\n if (opts.since) params[\"createdAtFrom\"] = parseDate(opts.since);\n if (opts.until) params[\"createdAtTo\"] = parseDate(opts.until);\n const size = clampLimit(opts.limit);\n if (size !== undefined) params[\"size\"] = size;\n if (opts.cursor) params[\"cursor\"] = opts.cursor;\n\n const res = await client.getJson(\"/v1/external/notes\", ListResponseSchema, params);\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\") {\n for (const note of res.content) printNdjson(note);\n if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });\n } else {\n printPretty(res.content, res.nextCursor, globalOpts);\n }\n });\n}\n\nfunction clampLimit(raw?: string): number | undefined {\n if (!raw) return undefined;\n const n = parseInt(raw, 10);\n if (!Number.isFinite(n) || n <= 0) return DEFAULT_PAGE_SIZE;\n return Math.min(n, MAX_PAGE_SIZE);\n}\n\ninterface NoteListItem {\n guid: string;\n title: string;\n createdAt: string;\n recordingDurationSeconds: number;\n webUrl: string;\n}\n\nfunction printPretty(\n notes: NoteListItem[],\n nextCursor: string | null,\n opts: { noColor?: boolean },\n): void {\n if (notes.length === 0) {\n process.stdout.write(`${color(\"(no notes)\", \"gray\", opts)}\\n`);\n return;\n }\n const titleWidth = computeTitleWidth();\n for (const n of notes) {\n const date = n.createdAt.slice(0, 10);\n const dur = formatDuration(n.recordingDurationSeconds);\n const title = truncate(n.title, titleWidth);\n process.stdout.write(\n `${color(date, \"gray\", opts)} ${color(n.guid, \"dim\", opts)} ${color(dur, \"cyan\", opts)} ${title}\\n`,\n );\n }\n if (nextCursor) {\n process.stdout.write(\n `${color(`\\n next: --cursor ${nextCursor}`, \"gray\", opts)}\\n`,\n );\n }\n}\n\nfunction computeTitleWidth(): number {\n const cols = process.stdout.columns;\n if (!cols || cols < 60) return 40;\n return Math.max(20, cols - 60);\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, Math.max(0, max - 1)) + \"…\";\n}\n\nfunction formatDuration(sec: number): string {\n if (!sec || sec <= 0) return \"—\";\n const m = Math.floor(sec / 60);\n const s = Math.floor(sec % 60);\n if (m > 0) return `${m}m${s.toString().padStart(2, \"0\")}s`;\n return `${s}s`;\n}\n","import { z } from \"zod\";\nimport { TiroError, ExitCode, type ErrorType } from \"../error.ts\";\nimport { resolveToken } from \"../auth/token.ts\";\nimport { authRequired } from \"../error.ts\";\nimport { getHostname } from \"../config.ts\";\nimport { ApiErrorSchema } from \"./types.ts\";\n\nexport interface ApiClientOptions {\n hostnameOverride?: string;\n tokenOverride?: string;\n}\n\nexport class TiroApiClient {\n constructor(\n private readonly hostname: string,\n private readonly token: string,\n ) {}\n\n async getJson<S extends z.ZodTypeAny>(\n path: string,\n schema: S,\n params?: Record<string, string | number | undefined>,\n ): Promise<z.infer<S>> {\n const url = this.buildUrl(path, params);\n const res = await this.fetch(url, { method: \"GET\" });\n return this.parseJson(res, schema, \"GET\", path);\n }\n\n async postJson<S extends z.ZodTypeAny>(\n path: string,\n schema: S,\n body: unknown,\n ): Promise<z.infer<S>> {\n const url = this.buildUrl(path);\n const res = await this.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return this.parseJson(res, schema, \"POST\", path);\n }\n\n async putJson<S extends z.ZodTypeAny>(\n path: string,\n schema: S,\n body: unknown,\n ): Promise<z.infer<S>> {\n const url = this.buildUrl(path);\n const res = await this.fetch(url, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return this.parseJson(res, schema, \"PUT\", path);\n }\n\n async deleteVoid(path: string): Promise<void> {\n const url = this.buildUrl(path);\n const res = await this.fetch(url, { method: \"DELETE\" });\n if (!res.ok) throw await mapHttpError(res, \"DELETE\", path);\n }\n\n private buildUrl(path: string, params?: Record<string, string | number | undefined>): string {\n const base = path.startsWith(\"http\") ? path : `${this.hostname}${path}`;\n const u = new URL(base);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null && v !== \"\") {\n u.searchParams.set(k, String(v));\n }\n }\n }\n return u.toString();\n }\n\n private async fetch(url: string, init: RequestInit): Promise<Response> {\n const headers = new Headers(init.headers);\n headers.set(\"Authorization\", `Bearer ${this.token}`);\n headers.set(\"Accept\", \"application/json\");\n try {\n return await fetch(url, { ...init, headers });\n } catch (err) {\n throw new TiroError(\n {\n code: \"network_error\",\n message: `Network error reaching ${this.hostname}: ${(err as Error).message}`,\n errorType: \"network_error\",\n suggestion: \"Check your network or --hostname.\",\n },\n ExitCode.Generic,\n );\n }\n }\n\n private async parseJson<S extends z.ZodTypeAny>(\n res: Response,\n schema: S,\n method: string,\n path: string,\n ): Promise<z.infer<S>> {\n if (!res.ok) throw await mapHttpError(res, method, path);\n let json: unknown;\n try {\n json = await res.json();\n } catch (err) {\n throw new TiroError(\n {\n code: \"invalid_response\",\n message: `Failed to parse JSON from ${method} ${path}: ${(err as Error).message}`,\n errorType: \"internal_error\",\n },\n ExitCode.Generic,\n );\n }\n const parsed = schema.safeParse(json);\n if (!parsed.success) {\n throw new TiroError(\n {\n code: \"schema_mismatch\",\n message: `Response shape did not match expected schema (${method} ${path}).`,\n errorType: \"internal_error\",\n suggestion: parsed.error.issues\n .slice(0, 3)\n .map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"; \"),\n },\n ExitCode.Generic,\n );\n }\n return parsed.data;\n }\n}\n\nasync function mapHttpError(res: Response, method: string, path: string): Promise<TiroError> {\n const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n const exitCode = res.status === 401 ? ExitCode.AuthRequired : ExitCode.Generic;\n\n const apiError = await tryParseApiError(res);\n if (apiError) {\n return new TiroError(\n {\n code: `${apiError.error.errorType}`,\n message: apiError.error.message,\n errorType: apiError.error.errorType as ErrorType,\n httpStatus: res.status,\n ...(requestId !== undefined && { requestId }),\n ...(res.status === 401 && {\n suggestion: \"Run `tiro auth login` to refresh.\",\n }),\n },\n exitCode,\n );\n }\n\n return new TiroError(\n {\n code: \"http_error\",\n message: `${method} ${path} failed: HTTP ${res.status} ${res.statusText}`,\n errorType: httpStatusToErrorType(res.status),\n httpStatus: res.status,\n ...(requestId !== undefined && { requestId }),\n },\n exitCode,\n );\n}\n\nfunction httpStatusToErrorType(status: number): ErrorType {\n if (status === 400) return \"bad_request\";\n if (status === 401) return \"unauthorized\";\n if (status === 403) return \"forbidden\";\n if (status === 404) return \"not_found\";\n if (status === 409) return \"conflict\";\n if (status === 413) return \"payload_too_large\";\n if (status === 422) return \"unprocessable_entity\";\n if (status === 429) return \"too_many_requests\";\n return \"internal_error\";\n}\n\nasync function tryParseApiError(res: Response): Promise<{ error: { code: number; errorType: string; message: string } } | null> {\n try {\n const json = await res.clone().json();\n const parsed = ApiErrorSchema.safeParse(json);\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nexport function createApiClient(opts: ApiClientOptions = {}): TiroApiClient {\n if (opts.tokenOverride) {\n return new TiroApiClient(getHostname(opts.hostnameOverride), opts.tokenOverride);\n }\n const t = resolveToken();\n if (!t) throw authRequired();\n const hostname = getHostname(opts.hostnameOverride ?? t.hostname);\n return new TiroApiClient(hostname, t.accessToken);\n}\n","import { z } from \"zod\";\n\nexport const CollaboratorSchema = z.object({\n guid: z.string(),\n name: z.string(),\n email: z.string(),\n role: z.enum([\"OWNER\", \"EDITOR\", \"VIEWER\"]),\n});\n\nexport const ParticipantSchema = z.object({\n name: z.string().nullable().optional(),\n email: z.string().nullable().optional(),\n});\n\nexport const NoteSchema = z\n .object({\n guid: z.string(),\n title: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n sourceType: z.string(),\n recordingDurationSeconds: z.number(),\n collaborators: z.array(CollaboratorSchema).optional().default([]),\n participants: z.array(ParticipantSchema).optional().default([]),\n webUrl: z.string(),\n recordingStartAt: z.string().nullable().optional(),\n recordingEndAt: z.string().nullable().optional(),\n })\n .passthrough();\nexport type Note = z.infer<typeof NoteSchema>;\n\nexport const TextObjectSchema = z.object({\n type: z.string(),\n content: z.string(),\n});\nexport type TextObject = z.infer<typeof TextObjectSchema>;\n\nexport const SpeakerInfoSchema = z.object({\n label: z.string(),\n personName: z.string().nullable().optional(),\n});\nexport type SpeakerInfo = z.infer<typeof SpeakerInfoSchema>;\n\nexport const DiarizedSegmentSchema = z.object({\n content: z.string(),\n speaker: SpeakerInfoSchema,\n});\nexport type DiarizedSegment = z.infer<typeof DiarizedSegmentSchema>;\n\nexport const ParagraphSchema = z\n .object({\n uuid: z.string(),\n transcribeLocale: z.string().nullable().optional(),\n transcript: TextObjectSchema.nullable().optional(),\n diarizedSegments: z.array(DiarizedSegmentSchema).nullable().optional(),\n timeFrom: z.string().nullable().optional(),\n timeTo: z.string().nullable().optional(),\n locked: z.boolean().optional(),\n })\n .passthrough();\nexport type Paragraph = z.infer<typeof ParagraphSchema>;\n\nexport const McpSegmentSchema = z.object({\n content: z.string(),\n speaker: z\n .object({\n label: z.string(),\n name: z.string().nullable(),\n })\n .nullable(),\n});\nexport type McpSegment = z.infer<typeof McpSegmentSchema>;\n\nexport const McpParagraphSchema = z.object({\n timeFrom: z.string().nullable(),\n timeTo: z.string().nullable(),\n segments: z.array(McpSegmentSchema),\n});\nexport type McpParagraph = z.infer<typeof McpParagraphSchema>;\n\nexport const McpTranscriptSchema = z.object({\n noteGuid: z.string(),\n title: z.string(),\n participants: z.array(z.string()),\n createdAt: z.string(),\n recordingDurationSeconds: z.number(),\n paragraphs: z.array(McpParagraphSchema),\n});\nexport type McpTranscript = z.infer<typeof McpTranscriptSchema>;\n\nexport const PageCursorResponseSchema = <T extends z.ZodTypeAny>(item: T) =>\n z.object({\n content: z.array(item),\n nextCursor: z.string().nullable(),\n });\n\nexport const SimpleListResponseSchema = <T extends z.ZodTypeAny>(item: T) =>\n z.object({\n content: z.array(item),\n });\n\nexport const ApiErrorSchema = z.object({\n error: z.object({\n code: z.number(),\n errorType: z.string(),\n message: z.string(),\n detail: z.string().nullable().optional(),\n }),\n});\nexport type ApiError = z.infer<typeof ApiErrorSchema>;\n","import { TiroError, ExitCode } from \"../error.ts\";\n\nconst RELATIVE_RE = /^(\\d+)([smhdw])$/i;\nconst UNIT_MS: Record<string, number> = {\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n};\n\nexport function parseDate(input: string): string {\n const trimmed = input.trim();\n\n const rel = trimmed.match(RELATIVE_RE);\n if (rel) {\n const num = parseInt(rel[1] ?? \"\", 10);\n const unit = (rel[2] ?? \"\").toLowerCase();\n const factor = UNIT_MS[unit];\n if (!factor || !Number.isFinite(num)) {\n throw invalidDate(input);\n }\n return new Date(Date.now() - num * factor).toISOString();\n }\n\n const d = new Date(trimmed);\n if (Number.isNaN(d.getTime())) throw invalidDate(input);\n return d.toISOString();\n}\n\nfunction invalidDate(input: string): TiroError {\n return new TiroError(\n {\n code: \"invalid_date\",\n message: `Invalid date: \"${input}\". Use ISO-8601 (e.g. 2026-04-01T10:00:00Z) or relative (e.g. 7d, 24h, 30m).`,\n errorType: \"bad_request\",\n },\n ExitCode.Usage,\n );\n}\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport { NoteSchema, PageCursorResponseSchema } from \"../../lib/api/types.ts\";\nimport { printNdjson } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode, color } from \"../../lib/output/tty.ts\";\nimport { parseDate } from \"../../lib/util/parseDate.ts\";\nimport { TiroError, ExitCode } from \"../../lib/error.ts\";\n\ninterface SearchOptions {\n keyword?: string;\n folder?: string;\n since?: string;\n until?: string;\n limit?: string;\n cursor?: string;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst SearchResponseSchema = PageCursorResponseSchema(NoteSchema).passthrough();\n\nconst DEFAULT_PAGE_SIZE = 100;\nconst MAX_PAGE_SIZE = 1000;\n\nexport function registerNotesSearch(parent: Command): void {\n parent\n .command(\"search [keyword]\")\n .description(\"Deep keyword search — returns notes hydrated with their primary documents\")\n .option(\"--keyword <text>\", \"Alternative to positional keyword\")\n .option(\"--folder <id>\", \"Restrict hits to a folder (recursive)\")\n .option(\"--since <date>\", \"ISO-8601 or relative (7d, 24h, 30m); maps to filter.createdAtFrom\")\n .option(\"--until <date>\", \"ISO-8601 or relative; maps to filter.createdAtTo\")\n .option(\"--limit <n>\", `Page size (default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE})`)\n .option(\"--cursor <token>\", \"Cursor for the next page (reserved — currently always null)\")\n .action(async (positional: string | undefined, opts: SearchOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<SearchOptions>();\n\n const keyword = (positional ?? opts.keyword ?? \"\").trim();\n if (!keyword) {\n throw new TiroError(\n {\n code: \"missing_keyword\",\n message: \"search requires a keyword (positional or --keyword).\",\n errorType: \"bad_request\",\n suggestion: 'tiro notes search \"OKR\"',\n },\n ExitCode.Usage,\n );\n }\n\n const filter: Record<string, string> = {};\n if (opts.folder) filter[\"folderId\"] = opts.folder;\n if (opts.since) filter[\"createdAtFrom\"] = parseDate(opts.since);\n if (opts.until) filter[\"createdAtTo\"] = parseDate(opts.until);\n\n const pagination: Record<string, string | number> = {};\n const size = clampLimit(opts.limit);\n if (size !== undefined) pagination[\"size\"] = size;\n if (opts.cursor) pagination[\"cursor\"] = opts.cursor;\n\n const body: Record<string, unknown> = { keyword };\n if (Object.keys(filter).length > 0) body[\"filter\"] = filter;\n if (Object.keys(pagination).length > 0) body[\"pagination\"] = pagination;\n\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const res = await client.postJson(\n \"/v1/external/notes/search\",\n SearchResponseSchema,\n body,\n );\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\") {\n for (const note of res.content) printNdjson(note);\n if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });\n } else {\n printPretty(res.content, res.nextCursor, globalOpts);\n }\n });\n}\n\nfunction clampLimit(raw?: string): number | undefined {\n if (!raw) return undefined;\n const n = parseInt(raw, 10);\n if (!Number.isFinite(n) || n <= 0) return DEFAULT_PAGE_SIZE;\n return Math.min(n, MAX_PAGE_SIZE);\n}\n\ninterface NoteListItem {\n guid: string;\n title: string;\n createdAt: string;\n}\n\nfunction printPretty(\n notes: NoteListItem[],\n nextCursor: string | null,\n opts: { noColor?: boolean },\n): void {\n if (notes.length === 0) {\n process.stdout.write(`${color(\"(no matches)\", \"gray\", opts)}\\n`);\n return;\n }\n for (const n of notes) {\n const date = n.createdAt.slice(0, 10);\n process.stdout.write(\n `${color(date, \"gray\", opts)} ${color(n.guid, \"dim\", opts)} ${n.title}\\n`,\n );\n }\n if (nextCursor) {\n process.stdout.write(\n `${color(`\\n next: --cursor ${nextCursor}`, \"gray\", opts)}\\n`,\n );\n }\n}\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport {\n NoteSchema,\n ParagraphSchema,\n SimpleListResponseSchema,\n PageCursorResponseSchema,\n type Paragraph,\n} from \"../../lib/api/types.ts\";\nimport { writeFileAtomic } from \"../../lib/output/file.ts\";\nimport { formatNote, type FileFormat } from \"../../lib/output/format.ts\";\nimport { paragraphsToMcp } from \"../../lib/output/transcript.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode, color } from \"../../lib/output/tty.ts\";\nimport { TiroError, ExitCode } from \"../../lib/error.ts\";\n\ninterface GetOptions {\n output?: string;\n format?: string;\n include?: string;\n force?: boolean;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst ALLOWED_INCLUDES = new Set([\"transcript\"]);\n\nconst ParagraphsListSchema = SimpleListResponseSchema(ParagraphSchema);\nconst ParagraphsCursorSchema = PageCursorResponseSchema(ParagraphSchema);\n\nexport function registerNotesGet(parent: Command): void {\n parent\n .command(\"get <guid>\")\n .description(\"Get a single note (stdout or file)\")\n .option(\"--output <path>\", \"Write to file (stdout becomes metadata only)\")\n .option(\"--format <md|json|txt>\", \"Output format (default: md for TTY, json for pipe)\")\n .option(\n \"--include <items>\",\n \"Comma-separated extras (v0.2.0 supports: transcript)\",\n \"\",\n )\n .option(\"--force\", \"Overwrite existing file\")\n .action(async (guid: string, opts: GetOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GetOptions>();\n\n const includes = parseIncludes(opts.include);\n validateIncludes(includes);\n const format = pickFormat(opts.format, opts.output);\n\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const note = await client.getJson(`/v1/external/notes/${guid}`, NoteSchema);\n\n let paragraphs: Paragraph[] | undefined;\n if (includes.has(\"transcript\") || format === \"txt\") {\n paragraphs = await fetchAllParagraphs(client, guid);\n }\n\n const content = formatNote(note, format, {\n includeTranscript: includes.has(\"transcript\"),\n ...(paragraphs !== undefined && { paragraphs }),\n });\n\n if (opts.output) {\n const result = await writeFileAtomic(opts.output, content, {\n ...(opts.force === true && { force: true }),\n });\n printOutput(\n {\n ok: true,\n data: {\n saved: result.path,\n size: result.size,\n format,\n guid: note.guid,\n title: note.title,\n },\n },\n globalOpts,\n );\n return;\n }\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\" && format !== \"json\") {\n printOutput(\n {\n ok: true,\n data: {\n ...note,\n ...(paragraphs && { transcript: { paragraphs: paragraphsToMcp(paragraphs) } }),\n },\n },\n globalOpts,\n );\n } else if (format === \"json\") {\n process.stdout.write(content);\n } else {\n if (process.stdout.isTTY && format === \"txt\") {\n process.stdout.write(`${color(`# ${note.title}`, \"bold\", globalOpts)}\\n\\n`);\n }\n process.stdout.write(content);\n }\n });\n}\n\nasync function fetchAllParagraphs(\n client: ReturnType<typeof createApiClient>,\n guid: string,\n): Promise<Paragraph[]> {\n const first = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema.or(ParagraphsListSchema),\n );\n const all: Paragraph[] = [...first.content];\n if (\"nextCursor\" in first) {\n let cursor = first.nextCursor;\n while (cursor) {\n const next = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema,\n { cursor },\n );\n all.push(...next.content);\n cursor = next.nextCursor;\n }\n }\n return all;\n}\n\nfunction parseIncludes(raw?: string): Set<string> {\n if (!raw) return new Set();\n return new Set(\n raw\n .split(\",\")\n .map((s) => s.trim().toLowerCase())\n .filter((s) => s.length > 0),\n );\n}\n\nfunction validateIncludes(includes: Set<string>): void {\n for (const inc of includes) {\n if (!ALLOWED_INCLUDES.has(inc)) {\n throw new TiroError(\n {\n code: \"invalid_include\",\n message: `Invalid --include \"${inc}\". v0.2.0 supports: transcript.`,\n errorType: \"bad_request\",\n suggestion: \"Use --include transcript\",\n },\n ExitCode.Usage,\n );\n }\n }\n}\n\nfunction pickFormat(format: string | undefined, output: string | undefined): FileFormat {\n const allowed: FileFormat[] = [\"md\", \"json\", \"txt\"];\n if (format) {\n const f = format.toLowerCase() as FileFormat;\n if (!allowed.includes(f)) {\n throw new TiroError(\n {\n code: \"invalid_format\",\n message: `Invalid --format \"${format}\". Allowed: md, json, txt.`,\n errorType: \"bad_request\",\n },\n ExitCode.Usage,\n );\n }\n return f;\n }\n if (output) {\n if (output.endsWith(\".json\")) return \"json\";\n if (output.endsWith(\".txt\")) return \"txt\";\n return \"md\";\n }\n return process.stdout.isTTY ? \"md\" : \"json\";\n}\n","import { mkdir, rename, stat, writeFile, access } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { TiroError, ExitCode } from \"../error.ts\";\n\nexport interface WriteResult {\n path: string;\n size: number;\n}\n\nexport async function writeFileAtomic(\n filepath: string,\n content: string,\n opts: { force?: boolean } = {},\n): Promise<WriteResult> {\n const absPath = resolve(filepath);\n await mkdir(dirname(absPath), { recursive: true });\n\n if (!opts.force) {\n const exists = await fileExists(absPath);\n if (exists) {\n throw new TiroError(\n {\n code: \"file_exists\",\n message: `File already exists: ${absPath}`,\n errorType: \"conflict\",\n suggestion: \"Use --force to overwrite, or pick a different --output.\",\n },\n ExitCode.Generic,\n );\n }\n }\n\n const tmp = `${absPath}.tmp.${process.pid}.${Date.now()}`;\n await writeFile(tmp, content, \"utf8\");\n await rename(tmp, absPath);\n const s = await stat(absPath);\n return { path: absPath, size: s.size };\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n","import type {\n McpParagraph,\n McpSegment,\n McpTranscript,\n Note,\n Paragraph,\n} from \"../api/types.ts\";\n\nexport function buildMcpTranscript(note: Note, paragraphs: Paragraph[]): McpTranscript {\n return {\n noteGuid: note.guid,\n title: note.title,\n participants:\n note.participants\n ?.map((p) => p.name || p.email || \"\")\n .filter((s): s is string => typeof s === \"string\" && s.length > 0) ?? [],\n createdAt: note.createdAt,\n recordingDurationSeconds: note.recordingDurationSeconds,\n paragraphs: paragraphsToMcp(paragraphs),\n };\n}\n\nexport function paragraphsToMcp(paragraphs: Paragraph[]): McpParagraph[] {\n return paragraphs\n .map((p) => ({\n timeFrom: p.timeFrom ?? null,\n timeTo: p.timeTo ?? null,\n segments: paragraphToSegments(p),\n }))\n .filter((p) => p.segments.length > 0);\n}\n\nfunction paragraphToSegments(p: Paragraph): McpSegment[] {\n const ds = p.diarizedSegments;\n if (ds && ds.length > 0) {\n return ds\n .map((s) => ({\n content: stripHtml(s.content),\n speaker: {\n label: s.speaker.label,\n name: s.speaker.personName ? stripHtml(s.speaker.personName) : null,\n },\n }))\n .filter((s) => s.content.length > 0);\n }\n const plain = stripHtml(p.transcript?.content ?? \"\");\n return plain ? [{ content: plain, speaker: null }] : [];\n}\n\nexport function renderTranscriptJson(t: McpTranscript): string {\n return `${JSON.stringify(t, null, 2)}\\n`;\n}\n\nexport function renderTranscriptMarkdown(t: McpTranscript): string {\n const anchor = anchorTime(t);\n const lines: string[] = [];\n lines.push(`# ${t.title}`, \"\");\n\n if (t.participants.length > 0) {\n lines.push(`**Participants**: ${t.participants.join(\", \")}`, \"\");\n }\n\n lines.push(\"## Transcript\", \"\");\n for (const p of t.paragraphs) {\n const ts = elapsed(p.timeFrom, anchor);\n for (const s of p.segments) {\n const who = s.speaker?.name ?? s.speaker?.label ?? \"Unknown\";\n const tag = ts ? `${who}, ${ts}` : who;\n lines.push(`**[${tag}]** ${s.content}`);\n }\n lines.push(\"\");\n }\n\n return `${lines.join(\"\\n\").trimEnd()}\\n`;\n}\n\nexport function renderTranscriptText(t: McpTranscript): string {\n const lines: string[] = [];\n for (const p of t.paragraphs) {\n for (const s of p.segments) {\n const who = s.speaker?.name ?? s.speaker?.label ?? \"Unknown\";\n lines.push(`[${who}] ${s.content}`);\n }\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction anchorTime(t: McpTranscript): string | null {\n for (const p of t.paragraphs) {\n if (p.timeFrom) return p.timeFrom;\n }\n return null;\n}\n\nfunction elapsed(currentIso: string | null, anchorIso: string | null): string {\n if (!currentIso || !anchorIso) return \"\";\n const cur = Date.parse(currentIso);\n const anc = Date.parse(anchorIso);\n if (!Number.isFinite(cur) || !Number.isFinite(anc)) return \"\";\n const seconds = Math.max(0, Math.floor((cur - anc) / 1000));\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = seconds % 60;\n if (h > 0) return `${pad(h)}:${pad(m)}:${pad(s)}`;\n return `${pad(m)}:${pad(s)}`;\n}\n\nfunction pad(n: number): string {\n return n.toString().padStart(2, \"0\");\n}\n\nfunction stripHtml(s: string): string {\n return s\n .replace(/<[^>]*>/g, \"\")\n .replace(/&nbsp;/g, \" \")\n .replace(/&amp;/g, \"&\")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .trim();\n}\n","import type { Note, Paragraph } from \"../api/types.ts\";\nimport {\n buildMcpTranscript,\n paragraphsToMcp,\n renderTranscriptJson,\n renderTranscriptMarkdown,\n renderTranscriptText,\n} from \"./transcript.ts\";\n\nexport type FileFormat = \"md\" | \"json\" | \"txt\";\n\nexport interface FormatOptions {\n includeTranscript?: boolean;\n paragraphs?: Paragraph[];\n}\n\nexport function formatNote(\n note: Note,\n format: FileFormat,\n opts: FormatOptions = {},\n): string {\n switch (format) {\n case \"md\":\n return formatMarkdown(note, opts);\n case \"json\":\n return formatJson(note, opts);\n case \"txt\":\n return formatText(note, opts);\n }\n}\n\nfunction formatMarkdown(note: Note, opts: FormatOptions): string {\n const fm = [\n \"---\",\n `guid: ${escapeYaml(note.guid)}`,\n `title: ${escapeYaml(note.title)}`,\n `createdAt: ${note.createdAt}`,\n `updatedAt: ${note.updatedAt}`,\n `sourceType: ${note.sourceType}`,\n `recordingDurationSeconds: ${note.recordingDurationSeconds}`,\n `webUrl: ${note.webUrl}`,\n ];\n if (note.recordingStartAt) fm.push(`recordingStartAt: ${note.recordingStartAt}`);\n if (note.recordingEndAt) fm.push(`recordingEndAt: ${note.recordingEndAt}`);\n fm.push(\"---\", \"\");\n\n const parts: string[] = [fm.join(\"\\n\"), `# ${note.title}`, \"\"];\n\n if (note.participants && note.participants.length > 0) {\n parts.push(\"## Participants\", \"\");\n for (const p of note.participants) {\n const name = p.name ?? \"(no name)\";\n const email = p.email ? ` <${p.email}>` : \"\";\n parts.push(`- ${name}${email}`);\n }\n parts.push(\"\");\n }\n\n if (opts.includeTranscript && opts.paragraphs && opts.paragraphs.length > 0) {\n const mcp = buildMcpTranscript(note, opts.paragraphs);\n const transcriptBody = renderTranscriptMarkdown(mcp);\n const startsWithHeader = transcriptBody.startsWith(`# ${note.title}`);\n const trimmed = startsWithHeader\n ? transcriptBody.slice(transcriptBody.indexOf(\"\\n\") + 1)\n : transcriptBody;\n parts.push(trimmed.replace(/^\\s*\\n+/, \"\"));\n }\n\n return `${parts.join(\"\\n\").trimEnd()}\\n`;\n}\n\nfunction formatJson(note: Note, opts: FormatOptions): string {\n const out: Record<string, unknown> = { ...note };\n if (opts.includeTranscript && opts.paragraphs) {\n out[\"transcript\"] = { paragraphs: paragraphsToMcp(opts.paragraphs) };\n }\n return `${JSON.stringify(out, null, 2)}\\n`;\n}\n\nfunction formatText(note: Note, opts: FormatOptions): string {\n if (!opts.paragraphs || opts.paragraphs.length === 0) {\n return `${note.title}\\n${note.webUrl}\\n`;\n }\n const mcp = buildMcpTranscript(note, opts.paragraphs);\n return renderTranscriptText(mcp);\n}\n\nfunction escapeYaml(s: string): string {\n if (/[:#\\n\"']/.test(s)) {\n return JSON.stringify(s);\n }\n return s;\n}\n\nexport {\n buildMcpTranscript,\n renderTranscriptJson,\n renderTranscriptMarkdown,\n renderTranscriptText,\n};\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport {\n ParagraphSchema,\n PageCursorResponseSchema,\n SimpleListResponseSchema,\n NoteSchema,\n type Paragraph,\n} from \"../../lib/api/types.ts\";\nimport { writeFileAtomic } from \"../../lib/output/file.ts\";\nimport {\n buildMcpTranscript,\n renderTranscriptJson,\n renderTranscriptMarkdown,\n renderTranscriptText,\n} from \"../../lib/output/transcript.ts\";\nimport { type FileFormat } from \"../../lib/output/format.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode } from \"../../lib/output/tty.ts\";\nimport { TiroError, ExitCode } from \"../../lib/error.ts\";\n\ninterface TranscriptOptions {\n output?: string;\n format?: string;\n force?: boolean;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst ParagraphsListSchema = SimpleListResponseSchema(ParagraphSchema);\nconst ParagraphsCursorSchema = PageCursorResponseSchema(ParagraphSchema);\n\nexport function registerNotesTranscript(parent: Command): void {\n parent\n .command(\"transcript <guid>\")\n .description(\"Get the full transcript of a note (matches MCP get_note_transcript JSON shape)\")\n .option(\"--output <path>\", \"Write to file (stdout = metadata only)\")\n .option(\n \"--format <md|json|txt>\",\n \"Output format (default: md for TTY, txt for pipe; json mirrors MCP shape)\",\n )\n .option(\"--force\", \"Overwrite existing file\")\n .action(async (guid: string, opts: TranscriptOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<TranscriptOptions>();\n const format = pickFormat(opts.format, opts.output, globalOpts);\n\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const note = await client.getJson(`/v1/external/notes/${guid}`, NoteSchema);\n const paragraphs = await fetchAllParagraphs(client, guid);\n const mcp = buildMcpTranscript(note, paragraphs);\n\n const content =\n format === \"json\"\n ? renderTranscriptJson(mcp)\n : format === \"md\"\n ? renderTranscriptMarkdown(mcp)\n : renderTranscriptText(mcp);\n\n if (opts.output) {\n const result = await writeFileAtomic(opts.output, content, {\n ...(opts.force === true && { force: true }),\n });\n printOutput(\n {\n ok: true,\n data: {\n saved: result.path,\n size: result.size,\n format,\n guid: note.guid,\n paragraphCount: mcp.paragraphs.length,\n segmentCount: mcp.paragraphs.reduce((sum, p) => sum + p.segments.length, 0),\n },\n },\n globalOpts,\n );\n return;\n }\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\" && format !== \"json\") {\n printOutput({ ok: true, data: mcp }, globalOpts);\n } else {\n process.stdout.write(content);\n }\n });\n}\n\nasync function fetchAllParagraphs(\n client: ReturnType<typeof createApiClient>,\n guid: string,\n): Promise<Paragraph[]> {\n const first = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema.or(ParagraphsListSchema),\n );\n const all: Paragraph[] = [...first.content];\n if (\"nextCursor\" in first) {\n let cursor = first.nextCursor;\n while (cursor) {\n const next = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema,\n { cursor },\n );\n all.push(...next.content);\n cursor = next.nextCursor;\n }\n }\n return all;\n}\n\nfunction pickFormat(\n format: string | undefined,\n output: string | undefined,\n globalOpts: { json?: boolean; pretty?: boolean },\n): FileFormat {\n const allowed: FileFormat[] = [\"md\", \"json\", \"txt\"];\n if (format) {\n const f = format.toLowerCase() as FileFormat;\n if (!allowed.includes(f)) {\n throw new TiroError(\n {\n code: \"invalid_format\",\n message: `Invalid --format \"${format}\". Allowed: md, json, txt.`,\n errorType: \"bad_request\",\n },\n ExitCode.Usage,\n );\n }\n return f;\n }\n if (output) {\n if (output.endsWith(\".json\")) return \"json\";\n if (output.endsWith(\".md\")) return \"md\";\n if (output.endsWith(\".txt\")) return \"txt\";\n return \"md\";\n }\n if (globalOpts.json) return \"json\";\n if (globalOpts.pretty) return \"md\";\n return process.stdout.isTTY ? \"md\" : \"txt\";\n}\n"],"mappings":"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","names":["Command","resolve","z","DEFAULT_PAGE_SIZE","MAX_PAGE_SIZE","clampLimit","printPretty","ParagraphsListSchema","ParagraphsCursorSchema","pickFormat","fetchAllParagraphs","Command"]}
1
+ {"version":3,"sources":["../../src/bin/tiro.ts","../../src/lib/version.ts","../../src/lib/error.ts","../../src/lib/output/tty.ts","../../src/lib/output/print.ts","../../src/commands/auth/index.ts","../../src/commands/auth/login.ts","../../src/lib/auth/flow.ts","../../src/lib/auth/pkce.ts","../../src/lib/auth/loopback.ts","../../src/lib/auth/browser.ts","../../src/lib/auth/keychain.ts","../../src/lib/auth/token.ts","../../src/lib/config.ts","../../src/commands/auth/status.ts","../../src/commands/auth/logout.ts","../../src/commands/notes/index.ts","../../src/commands/notes/list.ts","../../src/lib/api/client.ts","../../src/lib/api/types.ts","../../src/lib/util/parseDate.ts","../../src/lib/util/noteFilter.ts","../../src/commands/notes/search.ts","../../src/commands/notes/get.ts","../../src/lib/output/file.ts","../../src/lib/output/transcript.ts","../../src/lib/output/format.ts","../../src/commands/notes/transcript.ts","../../src/lib/updateCheck.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { VERSION } from \"../lib/version.ts\";\nimport { TiroError, ExitCode } from \"../lib/error.ts\";\nimport { printError } from \"../lib/output/print.ts\";\nimport { color } from \"../lib/output/tty.ts\";\nimport { registerAuth } from \"../commands/auth/index.ts\";\nimport { registerNotes } from \"../commands/notes/index.ts\";\nimport { emitUpdateBanner, startUpdateCheck } from \"../lib/updateCheck.ts\";\n\nconst EXAMPLES = `\nEXAMPLES\n $ tiro auth login\n $ tiro notes list --since 7d\n $ tiro notes search \"Q3 Planning\" --since 30d --json\n $ tiro notes get <guid> --output ./meeting.md --include transcript\n $ tiro notes transcript <guid> --format md --output ./transcript.md\n\nENVIRONMENT\n TIRO_TOKEN Bearer token (overrides keychain — for CI / agents)\n TIRO_HOSTNAME API base URL (default: https://api.tiro.ooo)\n NO_COLOR Disable colors (https://no-color.org)\n NO_UPDATE_NOTIFIER Set to \"1\" to disable the update banner\n\nDOCS\n https://api-docs.tiro.ooo/cli\n`;\n\nfunction buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"tiro\")\n .description(\"Tiro AI notes & transcripts — agent-first command line\")\n .version(VERSION, \"-v, --version\", \"Print version\")\n .option(\"--hostname <url>\", \"API base URL (default: https://api.tiro.ooo)\")\n .option(\"--json\", \"Force JSON output\")\n .option(\"--pretty\", \"Force pretty (human) output\")\n .option(\"--quiet\", \"Suppress non-error output\")\n .option(\"--verbose\", \"Verbose logging to stderr\")\n .option(\"--no-color\", \"Disable ANSI colors\")\n .addHelpText(\"after\", EXAMPLES);\n\n program.showHelpAfterError(\"(run `tiro --help` for available commands)\");\n\n registerAuth(program);\n registerNotes(program);\n\n return program;\n}\n\nasync function main(): Promise<void> {\n const program = buildProgram();\n const notifier = await startUpdateCheck();\n try {\n await program.parseAsync(process.argv);\n emitUpdateBanner(notifier);\n } catch (err) {\n handleError(err, program);\n }\n}\n\nfunction handleError(err: unknown, program: Command): never {\n const opts = program.opts<{ json?: boolean; quiet?: boolean }>();\n\n if (err instanceof TiroError) {\n if (opts.json) {\n printError(err.toJSON());\n } else if (!opts.quiet) {\n process.stderr.write(`${color(\"✗\", \"red\", opts)} ${err.message}\\n`);\n if (err.suggestion) {\n process.stderr.write(` ${color(\"→\", \"gray\", opts)} ${err.suggestion}\\n`);\n }\n }\n process.exit(err.exitCode);\n }\n\n if (err instanceof Error) {\n if (opts.json) {\n printError({\n ok: false,\n error: { code: \"internal_error\", message: err.message, errorType: \"internal_error\" },\n });\n } else if (!opts.quiet) {\n process.stderr.write(`${color(\"✗\", \"red\", opts)} ${err.message}\\n`);\n }\n process.exit(ExitCode.Generic);\n }\n\n process.stderr.write(`Unknown error: ${String(err)}\\n`);\n process.exit(ExitCode.Generic);\n}\n\nmain().catch((err) => {\n process.stderr.write(`Fatal: ${String(err)}\\n`);\n process.exit(ExitCode.Generic);\n});\n","import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, resolve } from \"node:path\";\n\nconst HERE = dirname(fileURLToPath(import.meta.url));\nconst CANDIDATE_PATHS = [\n resolve(HERE, \"../../package.json\"),\n resolve(HERE, \"../../../package.json\"),\n];\n\ninterface CliPackage {\n name?: string;\n version?: string;\n}\n\nfunction readVersion(): string {\n for (const path of CANDIDATE_PATHS) {\n try {\n const raw = readFileSync(path, \"utf8\");\n const parsed = JSON.parse(raw) as CliPackage;\n if (typeof parsed.version === \"string\" && parsed.version.length > 0) {\n return parsed.version;\n }\n } catch {\n // try next candidate\n }\n }\n return \"0.0.0-unknown\";\n}\n\nexport const VERSION = readVersion();\n","export const ExitCode = {\n Ok: 0,\n Generic: 1,\n Usage: 2,\n AuthRequired: 4,\n ExUsage: 64,\n ExDataErr: 65,\n ExConfig: 78,\n} as const;\n\nexport type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode];\n\nexport type ErrorType =\n | \"bad_request\"\n | \"unauthorized\"\n | \"forbidden\"\n | \"not_found\"\n | \"not_acceptable\"\n | \"conflict\"\n | \"payload_too_large\"\n | \"unprocessable_entity\"\n | \"too_many_requests\"\n | \"internal_error\"\n | \"auth_required\"\n | \"config_missing\"\n | \"network_error\";\n\nexport interface ErrorPayload {\n code: string;\n message: string;\n suggestion?: string;\n errorType?: ErrorType;\n httpStatus?: number;\n requestId?: string;\n}\n\nexport class TiroError extends Error {\n readonly code: string;\n readonly suggestion?: string;\n readonly errorType?: ErrorType;\n readonly httpStatus?: number;\n readonly requestId?: string;\n readonly exitCode: ExitCodeValue;\n\n constructor(payload: ErrorPayload, exitCode: ExitCodeValue = ExitCode.Generic) {\n super(payload.message);\n this.name = \"TiroError\";\n this.code = payload.code;\n this.suggestion = payload.suggestion;\n this.errorType = payload.errorType;\n this.httpStatus = payload.httpStatus;\n this.requestId = payload.requestId;\n this.exitCode = exitCode;\n }\n\n toJSON(): { ok: false; error: ErrorPayload } {\n return {\n ok: false,\n error: {\n code: this.code,\n message: this.message,\n ...(this.suggestion !== undefined && { suggestion: this.suggestion }),\n ...(this.errorType !== undefined && { errorType: this.errorType }),\n ...(this.httpStatus !== undefined && { httpStatus: this.httpStatus }),\n ...(this.requestId !== undefined && { requestId: this.requestId }),\n },\n };\n }\n}\n\nexport function authRequired(): TiroError {\n return new TiroError(\n {\n code: \"auth_required\",\n message:\n \"Not authenticated. Run `tiro auth login` to sign in, or set TIRO_TOKEN env var.\",\n suggestion: \"tiro auth login\",\n errorType: \"auth_required\",\n },\n ExitCode.AuthRequired,\n );\n}\n\nexport function configMissing(message: string, suggestion?: string): TiroError {\n return new TiroError(\n {\n code: \"config_missing\",\n message,\n ...(suggestion !== undefined && { suggestion }),\n errorType: \"config_missing\",\n },\n ExitCode.ExConfig,\n );\n}\n","export type OutputMode = \"json\" | \"pretty\";\n\nexport interface OutputOptions {\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function resolveOutputMode(opts: OutputOptions): OutputMode {\n if (opts.json) return \"json\";\n if (opts.pretty) return \"pretty\";\n return process.stdout.isTTY ? \"pretty\" : \"json\";\n}\n\nexport function colorEnabled(opts: OutputOptions): boolean {\n if (opts.noColor) return false;\n if (process.env[\"NO_COLOR\"]) return false;\n if (process.env[\"FORCE_COLOR\"]) return true;\n return process.stdout.isTTY === true;\n}\n\nconst ANSI = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n gray: \"\\x1b[90m\",\n} as const;\n\nexport function color(\n text: string,\n style: keyof typeof ANSI,\n opts: OutputOptions = {},\n): string {\n if (!colorEnabled(opts)) return text;\n return `${ANSI[style]}${text}${ANSI.reset}`;\n}\n","import { resolveOutputMode, type OutputOptions } from \"./tty.ts\";\n\nexport function printOutput(value: unknown, opts: OutputOptions = {}): void {\n if (opts.quiet) return;\n const mode = resolveOutputMode(opts);\n if (mode === \"json\") {\n process.stdout.write(`${JSON.stringify(value)}\\n`);\n } else {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n }\n}\n\nexport function printError(value: unknown): void {\n process.stderr.write(`${JSON.stringify(value)}\\n`);\n}\n\nexport function printNdjson(item: unknown): void {\n process.stdout.write(`${JSON.stringify(item)}\\n`);\n}\n","import { Command } from \"commander\";\nimport { registerAuthLogin } from \"./login.ts\";\nimport { registerAuthStatus } from \"./status.ts\";\nimport { registerAuthLogout } from \"./logout.ts\";\n\nexport function registerAuth(program: Command): void {\n const auth = program.command(\"auth\").description(\"Manage authentication\");\n registerAuthLogin(auth);\n registerAuthStatus(auth);\n registerAuthLogout(auth);\n}\n","import { Command } from \"commander\";\nimport { performLogin } from \"../../lib/auth/flow.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { color } from \"../../lib/output/tty.ts\";\nimport { getHostname } from \"../../lib/config.ts\";\n\ninterface LoginOptions {\n hostname?: string;\n noBrowser?: boolean;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function registerAuthLogin(parent: Command): void {\n parent\n .command(\"login\")\n .description(\"Sign in to Tiro via OAuth (browser-based, PKCE)\")\n .option(\"--hostname <url>\", \"API base URL (overrides config / TIRO_HOSTNAME)\")\n .option(\"--no-browser\", \"Print the URL instead of opening a browser\")\n .action(async (opts: LoginOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<LoginOptions>();\n const result = await performLogin({\n ...(opts.hostname !== undefined && { hostname: opts.hostname }),\n noBrowser: opts.noBrowser === true,\n onPrompt: (msg) => {\n if (globalOpts.quiet) return;\n process.stderr.write(`${color(msg, \"cyan\", globalOpts)}\\n`);\n },\n });\n\n const hostname = getHostname(opts.hostname);\n const expiresIso = new Date(result.expiresAt).toISOString();\n\n if (globalOpts.json) {\n printOutput(\n {\n ok: true,\n data: {\n signedIn: true,\n hostname,\n userId: result.userId ?? null,\n expiresAt: expiresIso,\n },\n },\n globalOpts,\n );\n } else if (!globalOpts.quiet) {\n process.stderr.write(`${color(\"✓\", \"green\", globalOpts)} Signed in to ${hostname}\\n`);\n if (result.userId) {\n process.stderr.write(` user: ${result.userId}\\n`);\n }\n process.stderr.write(` token expires: ${expiresIso}\\n`);\n }\n });\n}\n","import { z } from \"zod\";\nimport { TiroError, ExitCode } from \"../error.ts\";\nimport { generatePkce, generateState } from \"./pkce.ts\";\nimport { startLoopbackServer } from \"./loopback.ts\";\nimport { openBrowser } from \"./browser.ts\";\nimport { saveToken, type StoredToken } from \"./keychain.ts\";\nimport { decodeJwtPayload } from \"./token.ts\";\nimport {\n getHostname,\n getOauthClientId,\n setOauthClientId,\n clearOauthClientId,\n} from \"../config.ts\";\n\nconst RegisterResponseSchema = z.object({\n client_id: z.string(),\n client_secret: z.string().optional(),\n});\n\nconst TokenResponseSchema = z.object({\n access_token: z.string(),\n token_type: z.string(),\n expires_in: z.number().optional(),\n scope: z.string().optional(),\n});\n\nconst CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;\nconst DEFAULT_SCOPE = \"mcp:notes:read\";\n\nexport interface LoginOptions {\n hostname?: string;\n noBrowser?: boolean;\n scope?: string;\n onPrompt?: (msg: string) => void;\n}\n\nexport interface LoginResult {\n hostname: string;\n userId: string | undefined;\n expiresAt: number;\n}\n\nexport async function performLogin(options: LoginOptions = {}): Promise<LoginResult> {\n const hostname = getHostname(options.hostname);\n const onPrompt = options.onPrompt ?? ((msg: string) => process.stderr.write(`${msg}\\n`));\n\n const loopback = await startLoopbackServer();\n\n try {\n const clientId = await ensureOauthClient(hostname, loopback.redirectUri);\n const { codeVerifier, codeChallenge } = generatePkce();\n const state = generateState();\n\n const authorizeUrl = buildAuthorizeUrl({\n hostname,\n clientId,\n redirectUri: loopback.redirectUri,\n state,\n codeChallenge,\n scope: options.scope ?? DEFAULT_SCOPE,\n });\n\n if (options.noBrowser) {\n onPrompt(`Open this URL in your browser:\\n${authorizeUrl}`);\n } else {\n onPrompt(`Opening browser for sign-in...`);\n onPrompt(`If the browser does not open, visit:\\n${authorizeUrl}`);\n await openBrowser(authorizeUrl);\n }\n\n const callback = await loopback.waitForCallback(CALLBACK_TIMEOUT_MS);\n\n if (callback.state !== state) {\n throw new TiroError(\n {\n code: \"auth_state_mismatch\",\n message: \"OAuth state mismatch — possible CSRF. Aborting.\",\n errorType: \"unauthorized\",\n },\n ExitCode.Generic,\n );\n }\n\n const tokenRes = await exchangeToken({\n hostname,\n clientId,\n code: callback.code,\n redirectUri: loopback.redirectUri,\n codeVerifier,\n });\n\n const expiresAt = computeExpiry(tokenRes.expires_in);\n const payload = decodeJwtPayload(tokenRes.access_token);\n const userId = typeof payload?.[\"sub\"] === \"string\" ? (payload[\"sub\"] as string) : undefined;\n\n const stored: StoredToken = {\n accessToken: tokenRes.access_token,\n tokenType: tokenRes.token_type,\n expiresAt,\n hostname,\n ...(tokenRes.scope !== undefined && { scope: tokenRes.scope }),\n ...(userId !== undefined && { userId }),\n };\n saveToken(stored);\n\n return { hostname, userId, expiresAt };\n } finally {\n loopback.close();\n }\n}\n\nasync function ensureOauthClient(hostname: string, redirectUri: string): Promise<string> {\n const cached = getOauthClientId();\n if (cached) return cached;\n\n const url = `${hostname}/v1/mcp/oauth/register`;\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_name: \"tiro-cli\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: DEFAULT_SCOPE,\n }),\n });\n } catch (err) {\n throw new TiroError(\n {\n code: \"network_error\",\n message: `Failed to reach ${hostname}: ${(err as Error).message}`,\n errorType: \"network_error\",\n suggestion: \"Check your network connection or --hostname.\",\n },\n ExitCode.Generic,\n );\n }\n\n if (!res.ok) {\n const detail = await safeText(res);\n throw new TiroError(\n {\n code: \"oauth_register_failed\",\n message: `Dynamic Client Registration failed: HTTP ${res.status}`,\n errorType: \"internal_error\",\n httpStatus: res.status,\n ...(detail !== \"\" && { suggestion: detail.slice(0, 200) }),\n },\n ExitCode.Generic,\n );\n }\n\n const json = (await res.json()) as unknown;\n const parsed = RegisterResponseSchema.safeParse(json);\n if (!parsed.success) {\n throw new TiroError(\n {\n code: \"oauth_register_invalid\",\n message: \"Registration response did not match expected shape.\",\n errorType: \"internal_error\",\n },\n ExitCode.Generic,\n );\n }\n\n setOauthClientId(parsed.data.client_id);\n return parsed.data.client_id;\n}\n\ninterface AuthorizeUrlInput {\n hostname: string;\n clientId: string;\n redirectUri: string;\n state: string;\n codeChallenge: string;\n scope: string;\n}\n\nfunction buildAuthorizeUrl(input: AuthorizeUrlInput): string {\n const u = new URL(`${input.hostname}/v1/mcp/oauth/authorize`);\n u.searchParams.set(\"response_type\", \"code\");\n u.searchParams.set(\"client_id\", input.clientId);\n u.searchParams.set(\"redirect_uri\", input.redirectUri);\n u.searchParams.set(\"state\", input.state);\n u.searchParams.set(\"code_challenge\", input.codeChallenge);\n u.searchParams.set(\"code_challenge_method\", \"S256\");\n u.searchParams.set(\"scope\", input.scope);\n return u.toString();\n}\n\ninterface ExchangeInput {\n hostname: string;\n clientId: string;\n code: string;\n redirectUri: string;\n codeVerifier: string;\n}\n\nasync function exchangeToken(input: ExchangeInput): Promise<z.infer<typeof TokenResponseSchema>> {\n const url = `${input.hostname}/v1/mcp/oauth/token`;\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: input.redirectUri,\n client_id: input.clientId,\n code_verifier: input.codeVerifier,\n });\n\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n } catch (err) {\n throw new TiroError(\n {\n code: \"network_error\",\n message: `Failed to reach ${input.hostname}: ${(err as Error).message}`,\n errorType: \"network_error\",\n },\n ExitCode.Generic,\n );\n }\n\n if (!res.ok) {\n if (res.status === 400 || res.status === 401) {\n // Cached client_id may have expired (Redis 30-day TTL). Force re-registration on next try.\n clearOauthClientId();\n }\n const detail = await safeText(res);\n throw new TiroError(\n {\n code: \"oauth_token_failed\",\n message: `Token exchange failed: HTTP ${res.status}`,\n errorType: \"unauthorized\",\n httpStatus: res.status,\n ...(detail !== \"\" && { suggestion: detail.slice(0, 200) }),\n },\n ExitCode.AuthRequired,\n );\n }\n\n const json = (await res.json()) as unknown;\n const parsed = TokenResponseSchema.safeParse(json);\n if (!parsed.success) {\n throw new TiroError(\n {\n code: \"oauth_token_invalid\",\n message: \"Token response did not match expected shape.\",\n errorType: \"internal_error\",\n },\n ExitCode.Generic,\n );\n }\n return parsed.data;\n}\n\nfunction computeExpiry(expiresIn?: number): number {\n // McpJwtService issues 180-day tokens; if expires_in absent, fall back to 180 days.\n const fallbackSeconds = 180 * 24 * 60 * 60;\n const seconds = expiresIn ?? fallbackSeconds;\n return Date.now() + seconds * 1000;\n}\n\nasync function safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return \"\";\n }\n}\n","import { createHash, randomBytes } from \"node:crypto\";\n\nexport interface PkcePair {\n codeVerifier: string;\n codeChallenge: string;\n method: \"S256\";\n}\n\nexport function generatePkce(): PkcePair {\n const codeVerifier = base64url(randomBytes(32));\n const codeChallenge = base64url(createHash(\"sha256\").update(codeVerifier).digest());\n return { codeVerifier, codeChallenge, method: \"S256\" };\n}\n\nexport function generateState(): string {\n return base64url(randomBytes(24));\n}\n\nfunction base64url(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n","import http from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\nexport interface CallbackResult {\n code: string;\n state: string;\n}\n\nexport interface LoopbackServer {\n redirectUri: string;\n port: number;\n waitForCallback: (timeoutMs: number) => Promise<CallbackResult>;\n close: () => void;\n}\n\nexport async function startLoopbackServer(): Promise<LoopbackServer> {\n let pendingResolve: ((r: CallbackResult) => void) | null = null;\n let pendingReject: ((e: Error) => void) | null = null;\n\n const settle = (\n fn: ((arg: CallbackResult) => void) | ((arg: Error) => void),\n arg: CallbackResult | Error,\n ): void => {\n pendingResolve = null;\n pendingReject = null;\n (fn as (arg: CallbackResult | Error) => void)(arg);\n };\n\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400).end();\n return;\n }\n const url = new URL(req.url, `http://127.0.0.1`);\n if (url.pathname !== \"/callback\") {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" }).end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n const errorDesc = url.searchParams.get(\"error_description\") ?? \"\";\n\n if (error) {\n const msg = `OAuth error: ${error}${errorDesc ? ` — ${errorDesc}` : \"\"}`;\n respondPage(res, 500, \"Login failed\", msg);\n if (pendingReject) settle(pendingReject, new Error(msg));\n return;\n }\n if (!code || !state) {\n respondPage(res, 400, \"Missing parameters\", \"Missing `code` or `state`.\");\n if (pendingReject) settle(pendingReject, new Error(\"Missing code or state\"));\n return;\n }\n\n respondPage(\n res,\n 200,\n \"Login successful\",\n \"You're signed in. You can close this tab and return to the terminal.\",\n );\n if (pendingResolve) settle(pendingResolve, { code, state });\n });\n\n await new Promise<void>((resolve) => {\n server.listen(0, \"127.0.0.1\", () => resolve());\n });\n\n const address = server.address() as AddressInfo;\n const port = address.port;\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n return {\n redirectUri,\n port,\n waitForCallback(timeoutMs: number) {\n return new Promise<CallbackResult>((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingResolve = null;\n pendingReject = null;\n reject(new Error(`Timed out waiting for OAuth callback (${timeoutMs}ms)`));\n }, timeoutMs);\n pendingResolve = (r) => {\n clearTimeout(timer);\n resolve(r);\n };\n pendingReject = (e) => {\n clearTimeout(timer);\n reject(e);\n };\n });\n },\n close() {\n server.close();\n },\n };\n}\n\nfunction respondPage(\n res: http.ServerResponse,\n status: number,\n title: string,\n body: string,\n): void {\n const html = `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>${title}</title>\n <style>\n body { font-family: -apple-system, system-ui, sans-serif; padding: 4rem; max-width: 32rem; margin: 0 auto; color: #1a1a1a; }\n h1 { font-size: 1.5rem; margin-bottom: 1rem; }\n p { color: #555; line-height: 1.5; }\n </style>\n</head>\n<body>\n <h1>${title}</h1>\n <p>${body}</p>\n</body>\n</html>`;\n res.writeHead(status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(html);\n}\n","import open from \"open\";\n\nexport async function openBrowser(url: string): Promise<void> {\n try {\n await open(url, { wait: false });\n } catch {\n // Best-effort. Caller already prints the URL for manual fallback.\n }\n}\n","import { Entry } from \"@napi-rs/keyring\";\nimport { TiroError, ExitCode } from \"../error.ts\";\n\nconst SERVICE = \"io.tiro.cli\";\nconst ACCOUNT = \"default\";\n\nexport interface StoredToken {\n accessToken: string;\n tokenType: string;\n expiresAt: number;\n scope?: string;\n hostname: string;\n userId?: string;\n}\n\nexport function saveToken(token: StoredToken): void {\n const entry = new Entry(SERVICE, ACCOUNT);\n try {\n entry.setPassword(JSON.stringify(token));\n } catch (err) {\n throw new TiroError(\n {\n code: \"keychain_write_failed\",\n message: `Failed to write to OS keychain: ${(err as Error).message}`,\n errorType: \"internal_error\",\n suggestion:\n process.platform === \"linux\"\n ? \"Linux requires a Secret Service daemon (gnome-keyring or kwallet). Or set TIRO_TOKEN env var.\"\n : \"Check OS keychain permissions, or set TIRO_TOKEN env var.\",\n },\n ExitCode.Generic,\n );\n }\n}\n\nexport function loadToken(): StoredToken | null {\n const entry = new Entry(SERVICE, ACCOUNT);\n let raw: string | null;\n try {\n raw = entry.getPassword();\n } catch {\n return null;\n }\n if (!raw) return null;\n try {\n return JSON.parse(raw) as StoredToken;\n } catch {\n return null;\n }\n}\n\nexport function deleteToken(): boolean {\n const entry = new Entry(SERVICE, ACCOUNT);\n try {\n return entry.deletePassword();\n } catch {\n return false;\n }\n}\n","import { loadToken, type StoredToken } from \"./keychain.ts\";\nimport { authRequired } from \"../error.ts\";\n\nexport interface ResolvedToken {\n accessToken: string;\n source: \"env\" | \"keychain\";\n hostname?: string;\n expiresAt?: number;\n userId?: string;\n}\n\nexport function resolveToken(): ResolvedToken | null {\n const envToken = process.env[\"TIRO_TOKEN\"];\n if (envToken) {\n return { accessToken: envToken, source: \"env\" };\n }\n const stored = loadToken();\n if (stored) {\n return {\n accessToken: stored.accessToken,\n source: \"keychain\",\n hostname: stored.hostname,\n expiresAt: stored.expiresAt,\n ...(stored.userId !== undefined && { userId: stored.userId }),\n };\n }\n return null;\n}\n\nexport function requireToken(): ResolvedToken {\n const t = resolveToken();\n if (!t) throw authRequired();\n return t;\n}\n\nexport function decodeJwtPayload(token: string): Record<string, unknown> | null {\n const parts = token.split(\".\");\n if (parts.length !== 3) return null;\n try {\n const payload = parts[1];\n if (!payload) return null;\n const json = Buffer.from(payload, \"base64url\").toString(\"utf8\");\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport function isTokenExpired(stored: StoredToken): boolean {\n return Date.now() >= stored.expiresAt;\n}\n","import Conf from \"conf\";\n\ninterface TiroConfigSchema {\n hostname: string;\n oauthClientId: string | null;\n oauthClientIdRegisteredAt: number | null;\n defaultOutputDir: string | null;\n}\n\nconst DEFAULT_HOSTNAME = \"https://api.tiro.ooo\";\n\nconst config = new Conf<TiroConfigSchema>({\n projectName: \"tiro\",\n defaults: {\n hostname: DEFAULT_HOSTNAME,\n oauthClientId: null,\n oauthClientIdRegisteredAt: null,\n defaultOutputDir: null,\n },\n});\n\nexport function getHostname(override?: string): string {\n if (override) return stripTrailingSlash(override);\n const env = process.env[\"TIRO_HOSTNAME\"];\n if (env) return stripTrailingSlash(env);\n return stripTrailingSlash(config.get(\"hostname\"));\n}\n\nexport function setHostname(hostname: string): void {\n config.set(\"hostname\", stripTrailingSlash(hostname));\n}\n\nexport function getOauthClientId(): string | null {\n const id = config.get(\"oauthClientId\");\n const registeredAt = config.get(\"oauthClientIdRegisteredAt\");\n if (!id || !registeredAt) return null;\n // DCR clients have 30-day TTL on the backend (Redis). Treat them as expired\n // a day earlier to avoid edge-case 401s during exchange.\n const ttlMs = 29 * 24 * 60 * 60 * 1000;\n if (Date.now() - registeredAt > ttlMs) return null;\n return id;\n}\n\nexport function setOauthClientId(clientId: string): void {\n config.set(\"oauthClientId\", clientId);\n config.set(\"oauthClientIdRegisteredAt\", Date.now());\n}\n\nexport function clearOauthClientId(): void {\n config.set(\"oauthClientId\", null);\n config.set(\"oauthClientIdRegisteredAt\", null);\n}\n\nexport function getDefaultOutputDir(): string | null {\n const env = process.env[\"TIRO_OUTPUT_DIR\"];\n if (env) return env;\n return config.get(\"defaultOutputDir\");\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n\nfunction stripTrailingSlash(s: string): string {\n return s.endsWith(\"/\") ? s.slice(0, -1) : s;\n}\n","import { Command } from \"commander\";\nimport { resolveToken, decodeJwtPayload } from \"../../lib/auth/token.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { color } from \"../../lib/output/tty.ts\";\nimport { authRequired } from \"../../lib/error.ts\";\n\ninterface StatusReport {\n signedIn: boolean;\n source: \"env\" | \"keychain\";\n hostname: string | null;\n userId: string | null;\n scope: string | null;\n expiresAt: string | null;\n expired: boolean;\n tokenPrefix: string;\n}\n\ninterface StatusOptions {\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function registerAuthStatus(parent: Command): void {\n parent\n .command(\"status\")\n .description(\"Show current authenticated account and scopes\")\n .action(async (_opts: StatusOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<StatusOptions>();\n const t = resolveToken();\n if (!t) {\n throw authRequired();\n }\n\n const payload = decodeJwtPayload(t.accessToken);\n const sub = typeof payload?.[\"sub\"] === \"string\" ? (payload[\"sub\"] as string) : null;\n const exp = typeof payload?.[\"exp\"] === \"number\" ? (payload[\"exp\"] as number) * 1000 : null;\n const scope = typeof payload?.[\"scope\"] === \"string\" ? (payload[\"scope\"] as string) : null;\n\n const expMs = exp ?? t.expiresAt ?? null;\n const expired = expMs !== null && Date.now() >= expMs;\n\n const report: StatusReport = {\n signedIn: true,\n source: t.source,\n hostname: t.hostname ?? null,\n userId: t.userId ?? sub,\n scope,\n expiresAt: expMs ? new Date(expMs).toISOString() : null,\n expired,\n tokenPrefix: `${t.accessToken.slice(0, 4)}...***`,\n };\n\n if (globalOpts.json || !process.stdout.isTTY) {\n printOutput({ ok: true, data: report }, globalOpts);\n } else {\n const headIcon = expired ? color(\"!\", \"yellow\", globalOpts) : color(\"✓\", \"green\", globalOpts);\n const headText = expired ? \"Token expired\" : \"Signed in\";\n process.stdout.write(`${headIcon} ${headText}\\n`);\n process.stdout.write(` source: ${report.source}\\n`);\n if (report.hostname) process.stdout.write(` hostname: ${report.hostname}\\n`);\n if (report.userId) process.stdout.write(` user: ${report.userId}\\n`);\n if (report.scope) process.stdout.write(` scope: ${report.scope}\\n`);\n if (report.expiresAt) {\n const tag = expired ? color(\" (expired)\", \"red\", globalOpts) : \"\";\n process.stdout.write(` expires at: ${report.expiresAt}${tag}\\n`);\n }\n process.stdout.write(` token: ${report.tokenPrefix}\\n`);\n if (expired) {\n process.stdout.write(\n `\\n${color(\"→\", \"gray\", globalOpts)} Run \\`tiro auth login\\` to refresh.\\n`,\n );\n }\n }\n });\n}\n","import { Command } from \"commander\";\nimport { deleteToken } from \"../../lib/auth/keychain.ts\";\nimport { clearOauthClientId } from \"../../lib/config.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { color } from \"../../lib/output/tty.ts\";\n\ninterface LogoutOptions {\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nexport function registerAuthLogout(parent: Command): void {\n parent\n .command(\"logout\")\n .description(\"Sign out and clear the stored token\")\n .action(async (_opts: LogoutOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<LogoutOptions>();\n const removed = deleteToken();\n clearOauthClientId();\n\n if (globalOpts.json) {\n printOutput({ ok: true, data: { signedOut: true, hadToken: removed } }, globalOpts);\n } else if (!globalOpts.quiet) {\n if (removed) {\n process.stderr.write(`${color(\"✓\", \"green\", globalOpts)} Signed out\\n`);\n } else {\n process.stderr.write(`${color(\"•\", \"gray\", globalOpts)} No token was stored\\n`);\n }\n }\n });\n}\n","import { Command } from \"commander\";\nimport { registerNotesList } from \"./list.ts\";\nimport { registerNotesSearch } from \"./search.ts\";\nimport { registerNotesGet } from \"./get.ts\";\nimport { registerNotesTranscript } from \"./transcript.ts\";\n\nexport function registerNotes(program: Command): void {\n const notes = program.command(\"notes\").description(\"List, search, and download notes\");\n registerNotesList(notes);\n registerNotesSearch(notes);\n registerNotesGet(notes);\n registerNotesTranscript(notes);\n}\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport { NoteSchema, PageCursorResponseSchema } from \"../../lib/api/types.ts\";\nimport { printNdjson } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode, color } from \"../../lib/output/tty.ts\";\nimport { parseDate } from \"../../lib/util/parseDate.ts\";\nimport { isVisibleNote } from \"../../lib/util/noteFilter.ts\";\n\ninterface ListOptions {\n keyword?: string;\n folder?: string;\n since?: string;\n until?: string;\n limit?: string;\n cursor?: string;\n includeUntitled?: boolean;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst ListResponseSchema = PageCursorResponseSchema(NoteSchema);\n\nconst DEFAULT_PAGE_SIZE = 100;\nconst MAX_PAGE_SIZE = 1000;\n\nconst HELP_AFTER = `\nExamples:\n tiro notes list --since 7d\n tiro notes list --keyword \"OKR\" --since 30d --json\n tiro notes list --folder <id> --limit 50\n\nKeyword matching:\n --keyword reorders results by OpenSearch relevance (case-insensitive,\n full-text against note title and paragraph content). When --keyword is\n set, nextCursor is always null. Without --keyword, results are ordered\n by createdAt desc.\n\nNote: placeholder notes (title='Untitled' or sourceType='onboarding') are\nfiltered out by default. A page of N may return fewer than N visible notes —\nkeep paginating to fetch more, or pass --include-untitled to surface them.\n`;\n\nexport function registerNotesList(parent: Command): void {\n parent\n .command(\"list\")\n .description(\"List notes (lightweight metadata).\")\n .option(\"--keyword <text>\", 'Reorder by OpenSearch relevance for this keyword (e.g. \"OKR\")')\n .option(\"--folder <id>\", \"Restrict to a folder and its descendants\")\n .option(\n \"--since <date>\",\n \"Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)\",\n )\n .option(\"--until <date>\", \"Exclusive upper bound on createdAt\")\n .option(\n \"--limit <n>\",\n `Max results per page (default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE})`,\n )\n .option(\"--cursor <token>\", \"Continue a previous page\")\n .option(\n \"--include-untitled\",\n \"Include placeholder notes (title='Untitled' or sourceType='onboarding'). Default: hidden\",\n false,\n )\n .addHelpText(\"after\", HELP_AFTER)\n .action(async (opts: ListOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<ListOptions>();\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const params: Record<string, string | number | undefined> = {};\n if (opts.keyword) params[\"keyword\"] = opts.keyword;\n if (opts.folder) params[\"folderId\"] = opts.folder;\n if (opts.since) params[\"createdAtFrom\"] = parseDate(opts.since);\n if (opts.until) params[\"createdAtTo\"] = parseDate(opts.until);\n const size = clampLimit(opts.limit);\n if (size !== undefined) params[\"size\"] = size;\n if (opts.cursor) params[\"cursor\"] = opts.cursor;\n\n const res = await client.getJson(\"/v1/external/notes\", ListResponseSchema, params);\n const visible = opts.includeUntitled === true ? res.content : res.content.filter(isVisibleNote);\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\") {\n for (const note of visible) printNdjson(note);\n if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });\n } else {\n printPretty(visible, res.nextCursor, globalOpts);\n }\n });\n}\n\nfunction clampLimit(raw?: string): number | undefined {\n if (!raw) return undefined;\n const n = parseInt(raw, 10);\n if (!Number.isFinite(n) || n <= 0) return DEFAULT_PAGE_SIZE;\n return Math.min(n, MAX_PAGE_SIZE);\n}\n\ninterface NoteListItem {\n guid: string;\n title: string;\n createdAt: string;\n recordingDurationSeconds: number;\n webUrl: string;\n}\n\nfunction printPretty(\n notes: NoteListItem[],\n nextCursor: string | null,\n opts: { noColor?: boolean },\n): void {\n if (notes.length === 0) {\n process.stdout.write(`${color(\"(no notes)\", \"gray\", opts)}\\n`);\n return;\n }\n const titleWidth = computeTitleWidth();\n for (const n of notes) {\n const date = n.createdAt.slice(0, 10);\n const dur = formatDuration(n.recordingDurationSeconds);\n const title = truncate(n.title, titleWidth);\n process.stdout.write(\n `${color(date, \"gray\", opts)} ${color(n.guid, \"dim\", opts)} ${color(dur, \"cyan\", opts)} ${title}\\n`,\n );\n }\n if (nextCursor) {\n process.stdout.write(\n `${color(`\\n next: --cursor ${nextCursor}`, \"gray\", opts)}\\n`,\n );\n }\n}\n\nfunction computeTitleWidth(): number {\n const cols = process.stdout.columns;\n if (!cols || cols < 60) return 40;\n return Math.max(20, cols - 60);\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, Math.max(0, max - 1)) + \"…\";\n}\n\nfunction formatDuration(sec: number): string {\n if (!sec || sec <= 0) return \"—\";\n const m = Math.floor(sec / 60);\n const s = Math.floor(sec % 60);\n if (m > 0) return `${m}m${s.toString().padStart(2, \"0\")}s`;\n return `${s}s`;\n}\n","import { z } from \"zod\";\nimport { TiroError, ExitCode, type ErrorType } from \"../error.ts\";\nimport { resolveToken } from \"../auth/token.ts\";\nimport { authRequired } from \"../error.ts\";\nimport { getHostname } from \"../config.ts\";\nimport { ApiErrorSchema } from \"./types.ts\";\n\nexport interface ApiClientOptions {\n hostnameOverride?: string;\n tokenOverride?: string;\n}\n\nexport class TiroApiClient {\n constructor(\n private readonly hostname: string,\n private readonly token: string,\n ) {}\n\n async getJson<S extends z.ZodTypeAny>(\n path: string,\n schema: S,\n params?: Record<string, string | number | undefined>,\n ): Promise<z.infer<S>> {\n const url = this.buildUrl(path, params);\n const res = await this.fetch(url, { method: \"GET\" });\n return this.parseJson(res, schema, \"GET\", path);\n }\n\n async postJson<S extends z.ZodTypeAny>(\n path: string,\n schema: S,\n body: unknown,\n ): Promise<z.infer<S>> {\n const url = this.buildUrl(path);\n const res = await this.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return this.parseJson(res, schema, \"POST\", path);\n }\n\n async putJson<S extends z.ZodTypeAny>(\n path: string,\n schema: S,\n body: unknown,\n ): Promise<z.infer<S>> {\n const url = this.buildUrl(path);\n const res = await this.fetch(url, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return this.parseJson(res, schema, \"PUT\", path);\n }\n\n async deleteVoid(path: string): Promise<void> {\n const url = this.buildUrl(path);\n const res = await this.fetch(url, { method: \"DELETE\" });\n if (!res.ok) throw await mapHttpError(res, \"DELETE\", path);\n }\n\n private buildUrl(path: string, params?: Record<string, string | number | undefined>): string {\n const base = path.startsWith(\"http\") ? path : `${this.hostname}${path}`;\n const u = new URL(base);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null && v !== \"\") {\n u.searchParams.set(k, String(v));\n }\n }\n }\n return u.toString();\n }\n\n private async fetch(url: string, init: RequestInit): Promise<Response> {\n const headers = new Headers(init.headers);\n headers.set(\"Authorization\", `Bearer ${this.token}`);\n headers.set(\"Accept\", \"application/json\");\n try {\n return await fetch(url, { ...init, headers });\n } catch (err) {\n throw new TiroError(\n {\n code: \"network_error\",\n message: `Network error reaching ${this.hostname}: ${(err as Error).message}`,\n errorType: \"network_error\",\n suggestion: \"Check your network or --hostname.\",\n },\n ExitCode.Generic,\n );\n }\n }\n\n private async parseJson<S extends z.ZodTypeAny>(\n res: Response,\n schema: S,\n method: string,\n path: string,\n ): Promise<z.infer<S>> {\n if (!res.ok) throw await mapHttpError(res, method, path);\n let json: unknown;\n try {\n json = await res.json();\n } catch (err) {\n throw new TiroError(\n {\n code: \"invalid_response\",\n message: `Failed to parse JSON from ${method} ${path}: ${(err as Error).message}`,\n errorType: \"internal_error\",\n },\n ExitCode.Generic,\n );\n }\n const parsed = schema.safeParse(json);\n if (!parsed.success) {\n throw new TiroError(\n {\n code: \"schema_mismatch\",\n message: `Response shape did not match expected schema (${method} ${path}).`,\n errorType: \"internal_error\",\n suggestion: parsed.error.issues\n .slice(0, 3)\n .map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"; \"),\n },\n ExitCode.Generic,\n );\n }\n return parsed.data;\n }\n}\n\nasync function mapHttpError(res: Response, method: string, path: string): Promise<TiroError> {\n const requestId = res.headers.get(\"x-request-id\") ?? undefined;\n const exitCode = res.status === 401 ? ExitCode.AuthRequired : ExitCode.Generic;\n\n const apiError = await tryParseApiError(res);\n if (apiError) {\n return new TiroError(\n {\n code: `${apiError.error.errorType}`,\n message: apiError.error.message,\n errorType: apiError.error.errorType as ErrorType,\n httpStatus: res.status,\n ...(requestId !== undefined && { requestId }),\n ...(res.status === 401 && {\n suggestion: \"Run `tiro auth login` to refresh.\",\n }),\n },\n exitCode,\n );\n }\n\n return new TiroError(\n {\n code: \"http_error\",\n message: `${method} ${path} failed: HTTP ${res.status} ${res.statusText}`,\n errorType: httpStatusToErrorType(res.status),\n httpStatus: res.status,\n ...(requestId !== undefined && { requestId }),\n },\n exitCode,\n );\n}\n\nfunction httpStatusToErrorType(status: number): ErrorType {\n if (status === 400) return \"bad_request\";\n if (status === 401) return \"unauthorized\";\n if (status === 403) return \"forbidden\";\n if (status === 404) return \"not_found\";\n if (status === 409) return \"conflict\";\n if (status === 413) return \"payload_too_large\";\n if (status === 422) return \"unprocessable_entity\";\n if (status === 429) return \"too_many_requests\";\n return \"internal_error\";\n}\n\nasync function tryParseApiError(res: Response): Promise<{ error: { code: number; errorType: string; message: string } } | null> {\n try {\n const json = await res.clone().json();\n const parsed = ApiErrorSchema.safeParse(json);\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nexport function createApiClient(opts: ApiClientOptions = {}): TiroApiClient {\n if (opts.tokenOverride) {\n return new TiroApiClient(getHostname(opts.hostnameOverride), opts.tokenOverride);\n }\n const t = resolveToken();\n if (!t) throw authRequired();\n const hostname = getHostname(opts.hostnameOverride ?? t.hostname);\n return new TiroApiClient(hostname, t.accessToken);\n}\n","import { z } from \"zod\";\n\nexport const CollaboratorSchema = z.object({\n guid: z.string(),\n name: z.string(),\n email: z.string(),\n role: z.enum([\"OWNER\", \"EDITOR\", \"VIEWER\"]),\n});\n\nexport const ParticipantSchema = z.object({\n name: z.string().nullable().optional(),\n email: z.string().nullable().optional(),\n});\n\nexport const NoteSchema = z\n .object({\n guid: z.string(),\n title: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n sourceType: z.string(),\n recordingDurationSeconds: z.number(),\n collaborators: z.array(CollaboratorSchema).optional().default([]),\n participants: z.array(ParticipantSchema).optional().default([]),\n webUrl: z.string(),\n recordingStartAt: z.string().nullable().optional(),\n recordingEndAt: z.string().nullable().optional(),\n })\n .passthrough();\nexport type Note = z.infer<typeof NoteSchema>;\n\nexport const TextObjectSchema = z.object({\n type: z.string(),\n content: z.string(),\n});\nexport type TextObject = z.infer<typeof TextObjectSchema>;\n\nexport const SpeakerInfoSchema = z.object({\n label: z.string(),\n personName: z.string().nullable().optional(),\n});\nexport type SpeakerInfo = z.infer<typeof SpeakerInfoSchema>;\n\nexport const DiarizedSegmentSchema = z.object({\n content: z.string(),\n speaker: SpeakerInfoSchema,\n});\nexport type DiarizedSegment = z.infer<typeof DiarizedSegmentSchema>;\n\nexport const ParagraphSchema = z\n .object({\n uuid: z.string(),\n transcribeLocale: z.string().nullable().optional(),\n transcript: TextObjectSchema.nullable().optional(),\n diarizedSegments: z.array(DiarizedSegmentSchema).nullable().optional(),\n timeFrom: z.string().nullable().optional(),\n timeTo: z.string().nullable().optional(),\n locked: z.boolean().optional(),\n })\n .passthrough();\nexport type Paragraph = z.infer<typeof ParagraphSchema>;\n\nexport const McpSegmentSchema = z.object({\n content: z.string(),\n speaker: z\n .object({\n label: z.string(),\n name: z.string().nullable(),\n })\n .nullable(),\n});\nexport type McpSegment = z.infer<typeof McpSegmentSchema>;\n\nexport const McpParagraphSchema = z.object({\n timeFrom: z.string().nullable(),\n timeTo: z.string().nullable(),\n segments: z.array(McpSegmentSchema),\n});\nexport type McpParagraph = z.infer<typeof McpParagraphSchema>;\n\nexport const McpTranscriptSchema = z.object({\n noteGuid: z.string(),\n title: z.string(),\n participants: z.array(z.string()),\n createdAt: z.string(),\n recordingDurationSeconds: z.number(),\n paragraphs: z.array(McpParagraphSchema),\n});\nexport type McpTranscript = z.infer<typeof McpTranscriptSchema>;\n\nexport const PageCursorResponseSchema = <T extends z.ZodTypeAny>(item: T) =>\n z.object({\n content: z.array(item),\n nextCursor: z.string().nullable(),\n });\n\nexport const SimpleListResponseSchema = <T extends z.ZodTypeAny>(item: T) =>\n z.object({\n content: z.array(item),\n });\n\nexport const ApiErrorSchema = z.object({\n error: z.object({\n code: z.number(),\n errorType: z.string(),\n message: z.string(),\n detail: z.string().nullable().optional(),\n }),\n});\nexport type ApiError = z.infer<typeof ApiErrorSchema>;\n","import { TiroError, ExitCode } from \"../error.ts\";\n\nconst RELATIVE_RE = /^(\\d+)([smhdw])$/i;\nconst UNIT_MS: Record<string, number> = {\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n};\n\nexport function parseDate(input: string): string {\n const trimmed = input.trim();\n\n const rel = trimmed.match(RELATIVE_RE);\n if (rel) {\n const num = parseInt(rel[1] ?? \"\", 10);\n const unit = (rel[2] ?? \"\").toLowerCase();\n const factor = UNIT_MS[unit];\n if (!factor || !Number.isFinite(num)) {\n throw invalidDate(input);\n }\n return new Date(Date.now() - num * factor).toISOString();\n }\n\n const d = new Date(trimmed);\n if (Number.isNaN(d.getTime())) throw invalidDate(input);\n return d.toISOString();\n}\n\nfunction invalidDate(input: string): TiroError {\n return new TiroError(\n {\n code: \"invalid_date\",\n message: `Invalid date: \"${input}\". Use ISO-8601 (e.g. 2026-04-01T10:00:00Z) or relative (e.g. 7d, 24h, 30m).`,\n errorType: \"bad_request\",\n },\n ExitCode.Usage,\n );\n}\n","export interface FilterableNote {\n title?: string | null;\n sourceType?: string | null;\n}\n\nconst PLACEHOLDER_TITLE = \"Untitled\";\nconst PLACEHOLDER_SOURCE_TYPES = new Set<string>([\"onboarding\"]);\n\nexport function isVisibleNote(note: FilterableNote): boolean {\n if (note.title === PLACEHOLDER_TITLE) return false;\n if (note.sourceType !== null && note.sourceType !== undefined && PLACEHOLDER_SOURCE_TYPES.has(note.sourceType)) {\n return false;\n }\n return true;\n}\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport { NoteSchema, PageCursorResponseSchema } from \"../../lib/api/types.ts\";\nimport { printNdjson } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode, color } from \"../../lib/output/tty.ts\";\nimport { parseDate } from \"../../lib/util/parseDate.ts\";\nimport { isVisibleNote } from \"../../lib/util/noteFilter.ts\";\nimport { TiroError, ExitCode } from \"../../lib/error.ts\";\n\ninterface SearchOptions {\n keyword?: string;\n folder?: string;\n since?: string;\n until?: string;\n limit?: string;\n cursor?: string;\n includeUntitled?: boolean;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst SearchResponseSchema = PageCursorResponseSchema(NoteSchema).passthrough();\n\nconst DEFAULT_PAGE_SIZE = 100;\nconst MAX_PAGE_SIZE = 1000;\n\nconst HELP_AFTER = `\nExamples:\n tiro notes search \"Q3 Planning\"\n tiro notes search \"Acme Corp\" --since 7d --json\n tiro notes search \"release\" --since 2026-04-01 --until 2026-05-01\n\nKeyword matching:\n Full-text against note title + paragraph content via OpenSearch.\n Case-insensitive. Multi-word keywords are tokenized — \"OKR planning\"\n matches notes containing both terms. The deep search variant (this\n command) hydrates each result with its primary documents (one-pager,\n custom) so an MCP/LLM client can read content alongside metadata in\n one call.\n\nNote: placeholder notes (title='Untitled' or sourceType='onboarding') are\nfiltered out by default. Pass --include-untitled to surface them.\n`;\n\nexport function registerNotesSearch(parent: Command): void {\n parent\n .command(\"search [keyword]\")\n .description(\"Deep keyword search — returns notes hydrated with their primary documents.\")\n .option(\n \"--keyword <text>\",\n 'Alternative to positional keyword (e.g. --keyword \"Q3 Planning\")',\n )\n .option(\"--folder <id>\", \"Restrict hits to a folder and its descendants\")\n .option(\n \"--since <date>\",\n \"Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)\",\n )\n .option(\"--until <date>\", \"Exclusive upper bound on createdAt\")\n .option(\n \"--limit <n>\",\n `Max results per page (default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE})`,\n )\n .option(\n \"--cursor <token>\",\n \"Continue a previous page (reserved — backend currently always null)\",\n )\n .option(\n \"--include-untitled\",\n \"Include placeholder notes. Default: hidden\",\n false,\n )\n .addHelpText(\"after\", HELP_AFTER)\n .action(async (positional: string | undefined, opts: SearchOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<SearchOptions>();\n\n const keyword = (positional ?? opts.keyword ?? \"\").trim();\n if (!keyword) {\n throw new TiroError(\n {\n code: \"missing_keyword\",\n message: \"search requires a keyword (positional or --keyword).\",\n errorType: \"bad_request\",\n suggestion: 'tiro notes search \"OKR\"',\n },\n ExitCode.Usage,\n );\n }\n\n const filter: Record<string, string> = {};\n if (opts.folder) filter[\"folderId\"] = opts.folder;\n if (opts.since) filter[\"createdAtFrom\"] = parseDate(opts.since);\n if (opts.until) filter[\"createdAtTo\"] = parseDate(opts.until);\n\n const pagination: Record<string, string | number> = {};\n const size = clampLimit(opts.limit);\n if (size !== undefined) pagination[\"size\"] = size;\n if (opts.cursor) pagination[\"cursor\"] = opts.cursor;\n\n const body: Record<string, unknown> = { keyword };\n if (Object.keys(filter).length > 0) body[\"filter\"] = filter;\n if (Object.keys(pagination).length > 0) body[\"pagination\"] = pagination;\n\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const res = await client.postJson(\n \"/v1/external/notes/search\",\n SearchResponseSchema,\n body,\n );\n const visible = opts.includeUntitled === true ? res.content : res.content.filter(isVisibleNote);\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\") {\n for (const note of visible) printNdjson(note);\n if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });\n } else {\n printPretty(visible, res.nextCursor, globalOpts);\n }\n });\n}\n\nfunction clampLimit(raw?: string): number | undefined {\n if (!raw) return undefined;\n const n = parseInt(raw, 10);\n if (!Number.isFinite(n) || n <= 0) return DEFAULT_PAGE_SIZE;\n return Math.min(n, MAX_PAGE_SIZE);\n}\n\ninterface NoteListItem {\n guid: string;\n title: string;\n createdAt: string;\n}\n\nfunction printPretty(\n notes: NoteListItem[],\n nextCursor: string | null,\n opts: { noColor?: boolean },\n): void {\n if (notes.length === 0) {\n process.stdout.write(`${color(\"(no matches)\", \"gray\", opts)}\\n`);\n return;\n }\n for (const n of notes) {\n const date = n.createdAt.slice(0, 10);\n process.stdout.write(\n `${color(date, \"gray\", opts)} ${color(n.guid, \"dim\", opts)} ${n.title}\\n`,\n );\n }\n if (nextCursor) {\n process.stdout.write(\n `${color(`\\n next: --cursor ${nextCursor}`, \"gray\", opts)}\\n`,\n );\n }\n}\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport {\n NoteSchema,\n ParagraphSchema,\n SimpleListResponseSchema,\n PageCursorResponseSchema,\n type Paragraph,\n} from \"../../lib/api/types.ts\";\nimport { writeFileAtomic } from \"../../lib/output/file.ts\";\nimport { formatNote, type FileFormat } from \"../../lib/output/format.ts\";\nimport { paragraphsToMcp } from \"../../lib/output/transcript.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode, color } from \"../../lib/output/tty.ts\";\nimport { TiroError, ExitCode } from \"../../lib/error.ts\";\n\ninterface GetOptions {\n output?: string;\n format?: string;\n include?: string;\n force?: boolean;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst ALLOWED_INCLUDES = new Set([\"transcript\"]);\n\nconst ParagraphsListSchema = SimpleListResponseSchema(ParagraphSchema);\nconst ParagraphsCursorSchema = PageCursorResponseSchema(ParagraphSchema);\n\nexport function registerNotesGet(parent: Command): void {\n parent\n .command(\"get <guid>\")\n .description(\"Get a single note. Outputs to stdout, or saves to a file with --output.\")\n .option(\"--output <path>\", \"Write to file (stdout becomes a single metadata line)\")\n .option(\n \"--format <md|json|txt>\",\n \"Output format (default: md for TTY, json when piped)\",\n )\n .option(\n \"--include <items>\",\n \"Comma-separated extras (v0.2 supports: transcript)\",\n \"\",\n )\n .option(\"--force\", \"Overwrite existing file at --output path\")\n .addHelpText(\"after\", `\nExamples:\n tiro notes get <guid> # markdown to stdout\n tiro notes get <guid> --include transcript # add speaker-attributed paragraphs\n tiro notes get <guid> --output ./meeting.md --include transcript\n tiro notes get <guid> --format json # JSON to stdout\n\nTip for agents: prefer --output <path>. The actual content goes to disk\nand stdout collapses to a single metadata line, keeping your context\nwindow light.\n`)\n .action(async (guid: string, opts: GetOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GetOptions>();\n\n const includes = parseIncludes(opts.include);\n validateIncludes(includes);\n const format = pickFormat(opts.format, opts.output);\n\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const note = await client.getJson(`/v1/external/notes/${guid}`, NoteSchema);\n\n let paragraphs: Paragraph[] | undefined;\n if (includes.has(\"transcript\") || format === \"txt\") {\n paragraphs = await fetchAllParagraphs(client, guid);\n }\n\n const content = formatNote(note, format, {\n includeTranscript: includes.has(\"transcript\"),\n ...(paragraphs !== undefined && { paragraphs }),\n });\n\n if (opts.output) {\n const result = await writeFileAtomic(opts.output, content, {\n ...(opts.force === true && { force: true }),\n });\n printOutput(\n {\n ok: true,\n data: {\n saved: result.path,\n size: result.size,\n format,\n guid: note.guid,\n title: note.title,\n },\n },\n globalOpts,\n );\n return;\n }\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\" && format !== \"json\") {\n printOutput(\n {\n ok: true,\n data: {\n ...note,\n ...(paragraphs && { transcript: { paragraphs: paragraphsToMcp(paragraphs) } }),\n },\n },\n globalOpts,\n );\n } else if (format === \"json\") {\n process.stdout.write(content);\n } else {\n if (process.stdout.isTTY && format === \"txt\") {\n process.stdout.write(`${color(`# ${note.title}`, \"bold\", globalOpts)}\\n\\n`);\n }\n process.stdout.write(content);\n }\n });\n}\n\nasync function fetchAllParagraphs(\n client: ReturnType<typeof createApiClient>,\n guid: string,\n): Promise<Paragraph[]> {\n const first = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema.or(ParagraphsListSchema),\n );\n const all: Paragraph[] = [...first.content];\n if (\"nextCursor\" in first) {\n let cursor = first.nextCursor;\n while (cursor) {\n const next = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema,\n { cursor },\n );\n all.push(...next.content);\n cursor = next.nextCursor;\n }\n }\n return all;\n}\n\nfunction parseIncludes(raw?: string): Set<string> {\n if (!raw) return new Set();\n return new Set(\n raw\n .split(\",\")\n .map((s) => s.trim().toLowerCase())\n .filter((s) => s.length > 0),\n );\n}\n\nfunction validateIncludes(includes: Set<string>): void {\n for (const inc of includes) {\n if (!ALLOWED_INCLUDES.has(inc)) {\n throw new TiroError(\n {\n code: \"invalid_include\",\n message: `Invalid --include \"${inc}\". v0.2.0 supports: transcript.`,\n errorType: \"bad_request\",\n suggestion: \"Use --include transcript\",\n },\n ExitCode.Usage,\n );\n }\n }\n}\n\nfunction pickFormat(format: string | undefined, output: string | undefined): FileFormat {\n const allowed: FileFormat[] = [\"md\", \"json\", \"txt\"];\n if (format) {\n const f = format.toLowerCase() as FileFormat;\n if (!allowed.includes(f)) {\n throw new TiroError(\n {\n code: \"invalid_format\",\n message: `Invalid --format \"${format}\". Allowed: md, json, txt.`,\n errorType: \"bad_request\",\n },\n ExitCode.Usage,\n );\n }\n return f;\n }\n if (output) {\n if (output.endsWith(\".json\")) return \"json\";\n if (output.endsWith(\".txt\")) return \"txt\";\n return \"md\";\n }\n return process.stdout.isTTY ? \"md\" : \"json\";\n}\n","import { mkdir, rename, stat, writeFile, access } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { TiroError, ExitCode } from \"../error.ts\";\n\nexport interface WriteResult {\n path: string;\n size: number;\n}\n\nexport async function writeFileAtomic(\n filepath: string,\n content: string,\n opts: { force?: boolean } = {},\n): Promise<WriteResult> {\n const absPath = resolve(filepath);\n await mkdir(dirname(absPath), { recursive: true });\n\n if (!opts.force) {\n const exists = await fileExists(absPath);\n if (exists) {\n throw new TiroError(\n {\n code: \"file_exists\",\n message: `File already exists: ${absPath}`,\n errorType: \"conflict\",\n suggestion: \"Use --force to overwrite, or pick a different --output.\",\n },\n ExitCode.Generic,\n );\n }\n }\n\n const tmp = `${absPath}.tmp.${process.pid}.${Date.now()}`;\n await writeFile(tmp, content, \"utf8\");\n await rename(tmp, absPath);\n const s = await stat(absPath);\n return { path: absPath, size: s.size };\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n","import type {\n McpParagraph,\n McpSegment,\n McpTranscript,\n Note,\n Paragraph,\n} from \"../api/types.ts\";\n\nexport function buildMcpTranscript(note: Note, paragraphs: Paragraph[]): McpTranscript {\n return {\n noteGuid: note.guid,\n title: note.title,\n participants:\n note.participants\n ?.map((p) => p.name || p.email || \"\")\n .filter((s): s is string => typeof s === \"string\" && s.length > 0) ?? [],\n createdAt: note.createdAt,\n recordingDurationSeconds: note.recordingDurationSeconds,\n paragraphs: paragraphsToMcp(paragraphs),\n };\n}\n\nexport function paragraphsToMcp(paragraphs: Paragraph[]): McpParagraph[] {\n return paragraphs\n .map((p) => ({\n timeFrom: p.timeFrom ?? null,\n timeTo: p.timeTo ?? null,\n segments: paragraphToSegments(p),\n }))\n .filter((p) => p.segments.length > 0);\n}\n\nfunction paragraphToSegments(p: Paragraph): McpSegment[] {\n const ds = p.diarizedSegments;\n if (ds && ds.length > 0) {\n return ds\n .map((s) => ({\n content: stripHtml(s.content),\n speaker: {\n label: s.speaker.label,\n name: s.speaker.personName ? stripHtml(s.speaker.personName) : null,\n },\n }))\n .filter((s) => s.content.length > 0);\n }\n const plain = stripHtml(p.transcript?.content ?? \"\");\n return plain ? [{ content: plain, speaker: null }] : [];\n}\n\nexport function renderTranscriptJson(t: McpTranscript): string {\n return `${JSON.stringify(t, null, 2)}\\n`;\n}\n\nexport function renderTranscriptMarkdown(t: McpTranscript): string {\n const anchor = anchorTime(t);\n const lines: string[] = [];\n lines.push(`# ${t.title}`, \"\");\n\n if (t.participants.length > 0) {\n lines.push(`**Participants**: ${t.participants.join(\", \")}`, \"\");\n }\n\n lines.push(\"## Transcript\", \"\");\n for (const p of t.paragraphs) {\n const ts = elapsed(p.timeFrom, anchor);\n for (const s of p.segments) {\n const who = s.speaker?.name ?? s.speaker?.label ?? \"Unknown\";\n const tag = ts ? `${who}, ${ts}` : who;\n lines.push(`**[${tag}]** ${s.content}`);\n }\n lines.push(\"\");\n }\n\n return `${lines.join(\"\\n\").trimEnd()}\\n`;\n}\n\nexport function renderTranscriptText(t: McpTranscript): string {\n const lines: string[] = [];\n for (const p of t.paragraphs) {\n for (const s of p.segments) {\n const who = s.speaker?.name ?? s.speaker?.label ?? \"Unknown\";\n lines.push(`[${who}] ${s.content}`);\n }\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction anchorTime(t: McpTranscript): string | null {\n for (const p of t.paragraphs) {\n if (p.timeFrom) return p.timeFrom;\n }\n return null;\n}\n\nfunction elapsed(currentIso: string | null, anchorIso: string | null): string {\n if (!currentIso || !anchorIso) return \"\";\n const cur = Date.parse(currentIso);\n const anc = Date.parse(anchorIso);\n if (!Number.isFinite(cur) || !Number.isFinite(anc)) return \"\";\n const seconds = Math.max(0, Math.floor((cur - anc) / 1000));\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = seconds % 60;\n if (h > 0) return `${pad(h)}:${pad(m)}:${pad(s)}`;\n return `${pad(m)}:${pad(s)}`;\n}\n\nfunction pad(n: number): string {\n return n.toString().padStart(2, \"0\");\n}\n\nfunction stripHtml(s: string): string {\n return s\n .replace(/<[^>]*>/g, \"\")\n .replace(/&nbsp;/g, \" \")\n .replace(/&amp;/g, \"&\")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .trim();\n}\n","import type { Note, Paragraph } from \"../api/types.ts\";\nimport {\n buildMcpTranscript,\n paragraphsToMcp,\n renderTranscriptJson,\n renderTranscriptMarkdown,\n renderTranscriptText,\n} from \"./transcript.ts\";\n\nexport type FileFormat = \"md\" | \"json\" | \"txt\";\n\nexport interface FormatOptions {\n includeTranscript?: boolean;\n paragraphs?: Paragraph[];\n}\n\nexport function formatNote(\n note: Note,\n format: FileFormat,\n opts: FormatOptions = {},\n): string {\n switch (format) {\n case \"md\":\n return formatMarkdown(note, opts);\n case \"json\":\n return formatJson(note, opts);\n case \"txt\":\n return formatText(note, opts);\n }\n}\n\nfunction formatMarkdown(note: Note, opts: FormatOptions): string {\n const fm = [\n \"---\",\n `guid: ${escapeYaml(note.guid)}`,\n `title: ${escapeYaml(note.title)}`,\n `createdAt: ${note.createdAt}`,\n `updatedAt: ${note.updatedAt}`,\n `sourceType: ${note.sourceType}`,\n `recordingDurationSeconds: ${note.recordingDurationSeconds}`,\n `webUrl: ${note.webUrl}`,\n ];\n if (note.recordingStartAt) fm.push(`recordingStartAt: ${note.recordingStartAt}`);\n if (note.recordingEndAt) fm.push(`recordingEndAt: ${note.recordingEndAt}`);\n fm.push(\"---\", \"\");\n\n const parts: string[] = [fm.join(\"\\n\"), `# ${note.title}`, \"\"];\n\n if (note.participants && note.participants.length > 0) {\n parts.push(\"## Participants\", \"\");\n for (const p of note.participants) {\n const name = p.name ?? \"(no name)\";\n const email = p.email ? ` <${p.email}>` : \"\";\n parts.push(`- ${name}${email}`);\n }\n parts.push(\"\");\n }\n\n if (opts.includeTranscript && opts.paragraphs && opts.paragraphs.length > 0) {\n const mcp = buildMcpTranscript(note, opts.paragraphs);\n const transcriptBody = renderTranscriptMarkdown(mcp);\n const startsWithHeader = transcriptBody.startsWith(`# ${note.title}`);\n const trimmed = startsWithHeader\n ? transcriptBody.slice(transcriptBody.indexOf(\"\\n\") + 1)\n : transcriptBody;\n parts.push(trimmed.replace(/^\\s*\\n+/, \"\"));\n }\n\n return `${parts.join(\"\\n\").trimEnd()}\\n`;\n}\n\nfunction formatJson(note: Note, opts: FormatOptions): string {\n const out: Record<string, unknown> = { ...note };\n if (opts.includeTranscript && opts.paragraphs) {\n out[\"transcript\"] = { paragraphs: paragraphsToMcp(opts.paragraphs) };\n }\n return `${JSON.stringify(out, null, 2)}\\n`;\n}\n\nfunction formatText(note: Note, opts: FormatOptions): string {\n if (!opts.paragraphs || opts.paragraphs.length === 0) {\n return `${note.title}\\n${note.webUrl}\\n`;\n }\n const mcp = buildMcpTranscript(note, opts.paragraphs);\n return renderTranscriptText(mcp);\n}\n\nfunction escapeYaml(s: string): string {\n if (/[:#\\n\"']/.test(s)) {\n return JSON.stringify(s);\n }\n return s;\n}\n\nexport {\n buildMcpTranscript,\n renderTranscriptJson,\n renderTranscriptMarkdown,\n renderTranscriptText,\n};\n","import { Command } from \"commander\";\nimport { createApiClient } from \"../../lib/api/client.ts\";\nimport {\n ParagraphSchema,\n PageCursorResponseSchema,\n SimpleListResponseSchema,\n NoteSchema,\n type Paragraph,\n} from \"../../lib/api/types.ts\";\nimport { writeFileAtomic } from \"../../lib/output/file.ts\";\nimport {\n buildMcpTranscript,\n renderTranscriptJson,\n renderTranscriptMarkdown,\n renderTranscriptText,\n} from \"../../lib/output/transcript.ts\";\nimport { type FileFormat } from \"../../lib/output/format.ts\";\nimport { printOutput } from \"../../lib/output/print.ts\";\nimport { resolveOutputMode } from \"../../lib/output/tty.ts\";\nimport { TiroError, ExitCode } from \"../../lib/error.ts\";\n\ninterface TranscriptOptions {\n output?: string;\n format?: string;\n force?: boolean;\n hostname?: string;\n json?: boolean;\n pretty?: boolean;\n noColor?: boolean;\n quiet?: boolean;\n}\n\nconst ParagraphsListSchema = SimpleListResponseSchema(ParagraphSchema);\nconst ParagraphsCursorSchema = PageCursorResponseSchema(ParagraphSchema);\n\nexport function registerNotesTranscript(parent: Command): void {\n parent\n .command(\"transcript <guid>\")\n .description(\n \"Get the full transcript of a note as speaker-attributed paragraphs.\\n\" +\n \"JSON output matches MCP get_note_transcript shape exactly.\",\n )\n .option(\"--output <path>\", \"Write to file (stdout = single metadata line)\")\n .option(\n \"--format <md|json|txt>\",\n \"Output format (default: md if TTY, txt when piped; json mirrors MCP)\",\n )\n .option(\"--force\", \"Overwrite existing file at --output path\")\n .addHelpText(\"after\", `\nExamples:\n tiro notes transcript <guid> # md in TTY, txt in pipe\n tiro notes transcript <guid> --format md --output ./t.md\n tiro notes transcript <guid> --format json # MCP-shape JSON\n tiro notes transcript <guid> --format txt --output ./embed.txt\n\nThe --format json output is byte-for-byte identical to MCP's\nget_note_transcript so agents can swap surfaces without changing parsers.\n`)\n .action(async (guid: string, opts: TranscriptOptions, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<TranscriptOptions>();\n const format = pickFormat(opts.format, opts.output, globalOpts);\n\n const client = createApiClient({\n ...(globalOpts.hostname !== undefined && { hostnameOverride: globalOpts.hostname }),\n });\n\n const note = await client.getJson(`/v1/external/notes/${guid}`, NoteSchema);\n const paragraphs = await fetchAllParagraphs(client, guid);\n const mcp = buildMcpTranscript(note, paragraphs);\n\n const content =\n format === \"json\"\n ? renderTranscriptJson(mcp)\n : format === \"md\"\n ? renderTranscriptMarkdown(mcp)\n : renderTranscriptText(mcp);\n\n if (opts.output) {\n const result = await writeFileAtomic(opts.output, content, {\n ...(opts.force === true && { force: true }),\n });\n printOutput(\n {\n ok: true,\n data: {\n saved: result.path,\n size: result.size,\n format,\n guid: note.guid,\n paragraphCount: mcp.paragraphs.length,\n segmentCount: mcp.paragraphs.reduce((sum, p) => sum + p.segments.length, 0),\n },\n },\n globalOpts,\n );\n return;\n }\n\n const mode = resolveOutputMode(globalOpts);\n if (mode === \"json\" && format !== \"json\") {\n printOutput({ ok: true, data: mcp }, globalOpts);\n } else {\n process.stdout.write(content);\n }\n });\n}\n\nasync function fetchAllParagraphs(\n client: ReturnType<typeof createApiClient>,\n guid: string,\n): Promise<Paragraph[]> {\n const first = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema.or(ParagraphsListSchema),\n );\n const all: Paragraph[] = [...first.content];\n if (\"nextCursor\" in first) {\n let cursor = first.nextCursor;\n while (cursor) {\n const next = await client.getJson(\n `/v1/external/notes/${guid}/paragraphs`,\n ParagraphsCursorSchema,\n { cursor },\n );\n all.push(...next.content);\n cursor = next.nextCursor;\n }\n }\n return all;\n}\n\nfunction pickFormat(\n format: string | undefined,\n output: string | undefined,\n globalOpts: { json?: boolean; pretty?: boolean },\n): FileFormat {\n const allowed: FileFormat[] = [\"md\", \"json\", \"txt\"];\n if (format) {\n const f = format.toLowerCase() as FileFormat;\n if (!allowed.includes(f)) {\n throw new TiroError(\n {\n code: \"invalid_format\",\n message: `Invalid --format \"${format}\". Allowed: md, json, txt.`,\n errorType: \"bad_request\",\n },\n ExitCode.Usage,\n );\n }\n return f;\n }\n if (output) {\n if (output.endsWith(\".json\")) return \"json\";\n if (output.endsWith(\".md\")) return \"md\";\n if (output.endsWith(\".txt\")) return \"txt\";\n return \"md\";\n }\n if (globalOpts.json) return \"json\";\n if (globalOpts.pretty) return \"md\";\n return process.stdout.isTTY ? \"md\" : \"txt\";\n}\n","// update-notifier@7 ships no type definitions. We declare a minimal local\n// surface for the bits we use — runtime is the real authority.\n\nimport updateNotifier from \"update-notifier\";\nimport { readFile } from \"node:fs/promises\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, resolve } from \"node:path\";\n\ninterface UpdateInfo {\n current: string;\n latest: string;\n type?: string;\n name?: string;\n}\n\ninterface NotifyOptions {\n isGlobal?: boolean;\n defer?: boolean;\n message?: string;\n boxenOptions?: Record<string, unknown>;\n}\n\nexport interface MinimalNotifier {\n update?: UpdateInfo | null | undefined;\n notify(options?: NotifyOptions): unknown;\n}\n\ninterface NotifierFactory {\n (options: {\n pkg: { name: string; version: string };\n updateCheckInterval?: number;\n shouldNotifyInNpmScript?: boolean;\n }): MinimalNotifier;\n}\n\nconst HERE = dirname(fileURLToPath(import.meta.url));\nconst CANDIDATE_PATHS = [\n resolve(HERE, \"../../package.json\"),\n resolve(HERE, \"../../../package.json\"),\n];\n\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\n\ninterface CliPackage {\n name: string;\n version: string;\n}\n\nexport async function startUpdateCheck(): Promise<MinimalNotifier | null> {\n if (process.env[\"NO_UPDATE_NOTIFIER\"] === \"1\") return null;\n if (process.env[\"CI\"]) return null;\n if (process.stdout.isTTY !== true) return null;\n\n const pkg = await loadPkg();\n if (!pkg) return null;\n\n try {\n const factory = updateNotifier as unknown as NotifierFactory;\n return factory({\n pkg,\n updateCheckInterval: ONE_DAY_MS,\n shouldNotifyInNpmScript: false,\n });\n } catch {\n return null;\n }\n}\n\nexport function emitUpdateBanner(notifier: MinimalNotifier | null): void {\n if (!notifier) return;\n if (!notifier.update) return;\n\n notifier.notify({\n isGlobal: true,\n defer: false,\n message:\n \"Update available {currentVersion} \\u2192 {latestVersion}\\n\" +\n \"Run npm install -g {packageName} to update\\n\\n\" +\n \"Changelog: https://www.npmjs.com/package/{packageName}?activeTab=versions\",\n });\n}\n\nasync function loadPkg(): Promise<CliPackage | null> {\n for (const path of CANDIDATE_PATHS) {\n try {\n const raw = await readFile(path, \"utf8\");\n const parsed = JSON.parse(raw) as Partial<CliPackage>;\n if (\n typeof parsed.name === \"string\" &&\n typeof parsed.version === \"string\" &&\n parsed.name.length > 0 &&\n parsed.version.length > 0\n ) {\n return { name: parsed.name, version: parsed.version };\n }\n } catch {\n // try next candidate\n }\n }\n return null;\n}\n"],"mappings":"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","names":["Command","resolve","z","DEFAULT_PAGE_SIZE","MAX_PAGE_SIZE","HELP_AFTER","clampLimit","printPretty","dirname","resolve","resolve","dirname","ParagraphsListSchema","ParagraphsCursorSchema","pickFormat","fetchAllParagraphs","fileURLToPath","dirname","resolve","HERE","CANDIDATE_PATHS","Command"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theplato/tiro-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Tiro AI notes & transcripts — agent-first command line",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,6 +45,7 @@
45
45
  "commander": "^12.1.0",
46
46
  "conf": "^13.0.1",
47
47
  "open": "^10.1.0",
48
+ "update-notifier": "^7.3.1",
48
49
  "zod": "^3.23.8"
49
50
  },
50
51
  "devDependencies": {