@theplato/tiro-cli 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +65 -5
  2. package/dist/bin/tiro.js +177 -1939
  3. package/package.json +2 -2
package/dist/bin/tiro.js CHANGED
@@ -1,285 +1,14 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/bin/tiro.ts
4
- import { Command as Command13 } from "commander";
5
-
6
- // src/lib/version.ts
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();
29
-
30
- // src/lib/error.ts
31
- var ExitCode = {
32
- Ok: 0,
33
- Generic: 1,
34
- Usage: 2,
35
- AuthRequired: 4,
36
- ExUsage: 64,
37
- ExDataErr: 65,
38
- ExConfig: 78
39
- };
40
- var TiroError = class extends Error {
41
- code;
42
- suggestion;
43
- errorType;
44
- httpStatus;
45
- requestId;
46
- exitCode;
47
- constructor(payload, exitCode = ExitCode.Generic) {
48
- super(payload.message);
49
- this.name = "TiroError";
50
- this.code = payload.code;
51
- this.suggestion = payload.suggestion;
52
- this.errorType = payload.errorType;
53
- this.httpStatus = payload.httpStatus;
54
- this.requestId = payload.requestId;
55
- this.exitCode = exitCode;
56
- }
57
- toJSON() {
58
- return {
59
- ok: false,
60
- error: {
61
- code: this.code,
62
- message: this.message,
63
- ...this.suggestion !== void 0 && { suggestion: this.suggestion },
64
- ...this.errorType !== void 0 && { errorType: this.errorType },
65
- ...this.httpStatus !== void 0 && { httpStatus: this.httpStatus },
66
- ...this.requestId !== void 0 && { requestId: this.requestId }
67
- }
68
- };
69
- }
70
- };
71
- function authRequired() {
72
- return new TiroError(
73
- {
74
- code: "auth_required",
75
- message: "Not authenticated. Run `tiro auth login` to sign in, or set TIRO_TOKEN env var.",
76
- suggestion: "tiro auth login",
77
- errorType: "auth_required"
78
- },
79
- ExitCode.AuthRequired
80
- );
81
- }
82
-
83
- // src/lib/output/tty.ts
84
- function resolveOutputMode(opts) {
85
- if (opts.json) return "json";
86
- if (opts.pretty) return "pretty";
87
- return process.stdout.isTTY ? "pretty" : "json";
88
- }
89
- function colorEnabled(opts) {
90
- if (opts.noColor) return false;
91
- if (process.env["NO_COLOR"]) return false;
92
- if (process.env["FORCE_COLOR"]) return true;
93
- return process.stdout.isTTY === true;
94
- }
95
- var ANSI = {
96
- reset: "\x1B[0m",
97
- bold: "\x1B[1m",
98
- dim: "\x1B[2m",
99
- red: "\x1B[31m",
100
- green: "\x1B[32m",
101
- yellow: "\x1B[33m",
102
- blue: "\x1B[34m",
103
- magenta: "\x1B[35m",
104
- cyan: "\x1B[36m",
105
- gray: "\x1B[90m"
106
- };
107
- function color(text, style, opts = {}) {
108
- if (!colorEnabled(opts)) return text;
109
- return `${ANSI[style]}${text}${ANSI.reset}`;
110
- }
111
-
112
- // src/lib/output/print.ts
113
- function printOutput(value, opts = {}) {
114
- if (opts.quiet) return;
115
- const mode = resolveOutputMode(opts);
116
- if (mode === "json") {
117
- process.stdout.write(`${JSON.stringify(value)}
118
- `);
119
- } else {
120
- process.stdout.write(`${JSON.stringify(value, null, 2)}
121
- `);
122
- }
123
- }
124
- function printError(value) {
125
- process.stderr.write(`${JSON.stringify(value)}
126
- `);
127
- }
128
- function printNdjson(item) {
129
- process.stdout.write(`${JSON.stringify(item)}
130
- `);
131
- }
132
-
133
- // src/commands/auth/index.ts
134
- import "commander";
135
-
136
- // src/commands/auth/login.ts
137
- import "commander";
138
-
139
- // src/lib/auth/flow.ts
140
- import { z } from "zod";
141
-
142
- // src/lib/auth/pkce.ts
143
- import { createHash, randomBytes, timingSafeEqual } from "crypto";
144
- function generatePkce() {
145
- const codeVerifier = base64url(randomBytes(32));
146
- const codeChallenge = base64url(createHash("sha256").update(codeVerifier).digest());
147
- return { codeVerifier, codeChallenge, method: "S256" };
148
- }
149
- function generateState() {
150
- return base64url(randomBytes(24));
151
- }
152
- function verifyState(received, expected) {
153
- const a = Buffer.from(received, "utf8");
154
- const b = Buffer.from(expected, "utf8");
155
- if (a.length !== b.length) return false;
156
- return timingSafeEqual(a, b);
157
- }
158
- function base64url(buf) {
159
- return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
160
- }
161
-
162
- // src/lib/auth/loopback.ts
163
- import http from "http";
164
-
165
- // src/lib/auth/assets.generated.ts
166
- var TIRO_LOGO_BROWN_DATA_URI = "data:image/png;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA/78dOBAAAAAAELQ/9SIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAP3ZeKxkxamrQAAAABJRU5ErkJggg==";
167
-
168
- // src/lib/auth/loopback.ts
169
- async function startLoopbackServer() {
170
- let pendingResolve = null;
171
- let pendingReject = null;
172
- const settle = (fn, arg) => {
173
- pendingResolve = null;
174
- pendingReject = null;
175
- fn(arg);
176
- };
177
- let consumed = false;
178
- const server = http.createServer((req, res) => {
179
- res.setHeader("Connection", "close");
180
- res.setHeader("Cache-Control", "no-store");
181
- if (!req.url) {
182
- res.writeHead(400).end();
183
- return;
184
- }
185
- if (req.method !== "GET") {
186
- res.writeHead(405, { "Content-Type": "text/plain", Allow: "GET" }).end("Method not allowed");
187
- return;
188
- }
189
- const url = new URL(req.url, `http://127.0.0.1`);
190
- if (url.pathname !== "/callback") {
191
- res.writeHead(404, { "Content-Type": "text/plain" }).end("Not found");
192
- return;
193
- }
194
- if (consumed) {
195
- res.writeHead(410, { "Content-Type": "text/plain" }).end("Callback already consumed");
196
- return;
197
- }
198
- const code = url.searchParams.get("code");
199
- const state = url.searchParams.get("state");
200
- const error = url.searchParams.get("error");
201
- const errorDesc = url.searchParams.get("error_description") ?? "";
202
- if (error) {
203
- consumed = true;
204
- const detail = errorDesc ? ` \u2014 ${errorDesc}` : "";
205
- respondError(res, 500, `OAuth error: ${error}${detail}`);
206
- if (pendingReject) settle(pendingReject, new Error(`OAuth error: ${error}${detail}`));
207
- return;
208
- }
209
- if (!code || !state) {
210
- respondError(res, 400, "Missing `code` or `state` in callback URL.");
211
- if (pendingReject) settle(pendingReject, new Error("Missing code or state"));
212
- return;
213
- }
214
- consumed = true;
215
- respondSuccess(res);
216
- if (pendingResolve) settle(pendingResolve, { code, state });
217
- });
218
- await new Promise((resolve4) => {
219
- server.listen(0, "127.0.0.1", () => resolve4());
220
- });
221
- const address = server.address();
222
- const port = address.port;
223
- const redirectUri = `http://127.0.0.1:${port}/callback`;
224
- return {
225
- redirectUri,
226
- port,
227
- waitForCallback(timeoutMs) {
228
- return new Promise((resolve4, reject) => {
229
- const timer = setTimeout(() => {
230
- pendingResolve = null;
231
- pendingReject = null;
232
- reject(new Error(`Timed out waiting for OAuth callback (${timeoutMs}ms)`));
233
- }, timeoutMs);
234
- pendingResolve = (r) => {
235
- clearTimeout(timer);
236
- resolve4(r);
237
- };
238
- pendingReject = (e) => {
239
- clearTimeout(timer);
240
- reject(e);
241
- };
242
- });
243
- },
244
- close() {
245
- server.close();
246
- }
247
- };
248
- }
249
- function escapeHtml(s) {
250
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
251
- }
252
- function respondSuccess(res) {
253
- const html = renderPage({
254
- kind: "success",
255
- title: "You're signed in",
256
- body: "You can close this tab and return to your terminal."
257
- });
258
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
259
- res.end(html);
260
- }
261
- function respondError(res, status, body) {
262
- const html = renderPage({
263
- kind: "error",
264
- title: "Login failed",
265
- body
266
- });
267
- res.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
268
- res.end(html);
269
- }
270
- function renderPage(p) {
271
- const safeTitle = escapeHtml(p.title);
272
- const safeBody = escapeHtml(p.body);
273
- const titleColor = p.kind === "error" ? "var(--error)" : "var(--brown-800)";
274
- const logoOpacity = p.kind === "error" ? "0.4" : "1";
275
- const closeScript = p.kind === "success" ? `<script>setTimeout(function(){try{window.close();}catch(e){}}, 2000);</script>` : "";
276
- const hint = p.kind === "success" ? `<p class="hint">Closing this tab automatically&hellip;</p>` : "";
277
- return `<!doctype html>
2
+ import{Command as Kr}from"commander";import{readFileSync as MA}from"fs";import{fileURLToPath as NA}from"url";import{dirname as GA,resolve as me}from"path";var ge=GA(NA(import.meta.url)),VA=[me(ge,"../../package.json"),me(ge,"../../../package.json")];function UA(){for(let e of VA)try{let A=MA(e,"utf8"),t=JSON.parse(A);if(typeof t.version=="string"&&t.version.length>0)return t.version}catch{}return"0.0.0-unknown"}var fe=UA();var u={Ok:0,Generic:1,Usage:2,AuthRequired:4,ExUsage:64,ExDataErr:65,ExConfig:78},f=class extends Error{code;suggestion;errorType;httpStatus;requestId;details;exitCode;constructor(A,t=u.Generic){super(A.message),this.name="TiroError",this.code=A.code,this.suggestion=A.suggestion,this.errorType=A.errorType,this.httpStatus=A.httpStatus,this.requestId=A.requestId,this.details=A.details,this.exitCode=t}toJSON(){return{ok:!1,error:{code:this.code,message:this.message,...this.suggestion!==void 0&&{suggestion:this.suggestion},...this.errorType!==void 0&&{errorType:this.errorType},...this.httpStatus!==void 0&&{httpStatus:this.httpStatus},...this.requestId!==void 0&&{requestId:this.requestId},...this.details!==void 0&&{details:this.details}}}}};function W(){return new f({code:"auth_required",message:"Not authenticated. Run `tiro auth login` to sign in, or set TIRO_TOKEN env var.",suggestion:"tiro auth login",errorType:"auth_required"},u.AuthRequired)}function y(e){return e.json?"json":e.pretty||process.stdout.isTTY?"pretty":"json"}function jA(e){return e.noColor||process.env.NO_COLOR?!1:process.env.FORCE_COLOR?!0:process.stdout.isTTY===!0}var he={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",gray:"\x1B[90m"};function a(e,A,t={}){return jA(t)?`${he[A]}${e}${he.reset}`:e}function v(e,A={}){if(A.quiet)return;y(A)==="json"?process.stdout.write(`${JSON.stringify(e)}
3
+ `):process.stdout.write(`${JSON.stringify(e,null,2)}
4
+ `)}function te(e){process.stderr.write(`${JSON.stringify(e)}
5
+ `)}function C(e){process.stdout.write(`${JSON.stringify(e)}
6
+ `)}import"commander";import"commander";import{z as B}from"zod";import{createHash as QA,randomBytes as we,timingSafeEqual as zA}from"crypto";function be(){let e=re(we(32)),A=re(QA("sha256").update(e).digest());return{codeVerifier:e,codeChallenge:A,method:"S256"}}function ye(){return re(we(24))}function ke(e,A){let t=Buffer.from(e,"utf8"),r=Buffer.from(A,"utf8");return t.length!==r.length?!1:zA(t,r)}function re(e){return e.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}import YA from"http";var Ce="data:image/png;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA/78dOBAAAAAAELQ/9SIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAP3ZeKxkxamrQAAAABJRU5ErkJggg==";async function xe(){let e=null,A=null,t=(d,p)=>{e=null,A=null,d(p)},r=!1,n=YA.createServer((d,p)=>{if(p.setHeader("Connection","close"),p.setHeader("Cache-Control","no-store"),!d.url){p.writeHead(400).end();return}if(d.method!=="GET"){p.writeHead(405,{"Content-Type":"text/plain",Allow:"GET"}).end("Method not allowed");return}let l=new URL(d.url,"http://127.0.0.1");if(l.pathname!=="/callback"){p.writeHead(404,{"Content-Type":"text/plain"}).end("Not found");return}if(r){p.writeHead(410,{"Content-Type":"text/plain"}).end("Callback already consumed");return}let w=l.searchParams.get("code"),b=l.searchParams.get("state"),h=l.searchParams.get("error"),T=l.searchParams.get("error_description")??"";if(h){r=!0;let H=T?` \u2014 ${T}`:"";Te(p,500,`OAuth error: ${h}${H}`),A&&t(A,new Error(`OAuth error: ${h}${H}`));return}if(!w||!b){Te(p,400,"Missing `code` or `state` in callback URL."),A&&t(A,new Error("Missing code or state"));return}r=!0,KA(p),e&&t(e,{code:w,state:b})});await new Promise(d=>{n.listen(0,"127.0.0.1",()=>d())});let s=n.address().port;return{redirectUri:`http://127.0.0.1:${s}/callback`,port:s,waitForCallback(d){return new Promise((p,l)=>{let w=setTimeout(()=>{e=null,A=null,l(new Error(`Timed out waiting for OAuth callback (${d}ms)`))},d);e=b=>{clearTimeout(w),p(b)},A=b=>{clearTimeout(w),l(b)}})},close(){n.close()}}}function ve(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function KA(e){let A=Be({kind:"success",title:"You're signed in",body:"You can close this tab and return to your terminal."});e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(A)}function Te(e,A,t){let r=Be({kind:"error",title:"Login failed",body:t});e.writeHead(A,{"Content-Type":"text/html; charset=utf-8"}),e.end(r)}function Be(e){let A=ve(e.title),t=ve(e.body),r=e.kind==="error"?"var(--error)":"var(--brown-800)",n=e.kind==="error"?"0.4":"1",i=e.kind==="success"?"<script>setTimeout(function(){try{window.close();}catch(e){}}, 2000);</script>":"",s=e.kind==="success"?'<p class="hint">Closing this tab automatically&hellip;</p>':"";return`<!doctype html>
278
7
  <html lang="en">
279
8
  <head>
280
9
  <meta charset="utf-8">
281
10
  <meta name="viewport" content="width=device-width, initial-scale=1">
282
- <title>Tiro \u2014 ${safeTitle}</title>
11
+ <title>Tiro \u2014 ${A}</title>
283
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
284
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
285
14
  <link href="https://fonts.googleapis.com/css2?family=Averia+Serif+Libre:wght@300;400;700&display=swap" rel="stylesheet">
@@ -319,14 +48,14 @@ function renderPage(p) {
319
48
  height: auto;
320
49
  margin-bottom: 1.5rem;
321
50
  object-fit: contain;
322
- opacity: ${logoOpacity};
51
+ opacity: ${n};
323
52
  }
324
53
  h1 {
325
54
  font-family: 'Averia Serif Libre', Georgia, 'Times New Roman', serif;
326
55
  font-size: 36px;
327
56
  line-height: 42px;
328
57
  font-weight: 400;
329
- color: ${titleColor};
58
+ color: ${r};
330
59
  }
331
60
  .body {
332
61
  margin-top: 1.5rem;
@@ -355,843 +84,35 @@ function renderPage(p) {
355
84
  <body>
356
85
  <div class="top-spacer"></div>
357
86
  <main>
358
- <img class="logo" src="${TIRO_LOGO_BROWN_DATA_URI}" alt="Tiro">
359
- <h1>${safeTitle}</h1>
360
- <p class="body">${safeBody}</p>
361
- ${hint}
87
+ <img class="logo" src="${Ce}" alt="Tiro">
88
+ <h1>${A}</h1>
89
+ <p class="body">${t}</p>
90
+ ${s}
362
91
  </main>
363
92
  <footer>&copy; 2026 <a href="https://tiro.ooo">The Plato Inc.</a> &mdash; All rights reserved.</footer>
364
- ${closeScript}
93
+ ${i}
365
94
  </body>
366
- </html>`;
367
- }
368
-
369
- // src/lib/auth/browser.ts
370
- import open from "open";
371
- async function openBrowser(url) {
372
- try {
373
- await open(url, { wait: false });
374
- } catch {
375
- }
376
- }
377
-
378
- // src/lib/auth/keychain.ts
379
- import { Entry } from "@napi-rs/keyring";
380
- var SERVICE = "io.tiro.cli";
381
- var ACCOUNT = "default";
382
- function saveToken(token) {
383
- const entry = new Entry(SERVICE, ACCOUNT);
384
- try {
385
- entry.setPassword(JSON.stringify(token));
386
- } catch (err) {
387
- throw new TiroError(
388
- {
389
- code: "keychain_write_failed",
390
- message: `Failed to write to OS keychain: ${err.message}`,
391
- errorType: "internal_error",
392
- suggestion: process.platform === "linux" ? "Linux requires a Secret Service daemon (gnome-keyring or kwallet). Or set TIRO_TOKEN env var." : "Check OS keychain permissions, or set TIRO_TOKEN env var."
393
- },
394
- ExitCode.Generic
395
- );
396
- }
397
- }
398
- function loadToken() {
399
- const entry = new Entry(SERVICE, ACCOUNT);
400
- let raw;
401
- try {
402
- raw = entry.getPassword();
403
- } catch {
404
- return null;
405
- }
406
- if (!raw) return null;
407
- try {
408
- return JSON.parse(raw);
409
- } catch {
410
- return null;
411
- }
412
- }
413
- function deleteToken() {
414
- const entry = new Entry(SERVICE, ACCOUNT);
415
- try {
416
- return entry.deletePassword();
417
- } catch {
418
- return false;
419
- }
420
- }
421
-
422
- // src/lib/auth/token.ts
423
- function resolveToken() {
424
- const envToken = process.env["TIRO_TOKEN"];
425
- if (envToken) {
426
- return { accessToken: envToken, source: "env" };
427
- }
428
- const stored = loadToken();
429
- if (stored) {
430
- return {
431
- accessToken: stored.accessToken,
432
- source: "keychain",
433
- hostname: stored.hostname,
434
- expiresAt: stored.expiresAt,
435
- ...stored.userId !== void 0 && { userId: stored.userId }
436
- };
437
- }
438
- return null;
439
- }
440
- function decodeJwtPayload(token) {
441
- const parts = token.split(".");
442
- if (parts.length !== 3) return null;
443
- try {
444
- const payload = parts[1];
445
- if (!payload) return null;
446
- const json = Buffer.from(payload, "base64url").toString("utf8");
447
- return JSON.parse(json);
448
- } catch {
449
- return null;
450
- }
451
- }
452
-
453
- // src/lib/config.ts
454
- import Conf from "conf";
455
- var DEFAULT_HOSTNAME = "https://api.tiro.ooo";
456
- var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
457
- var config = new Conf({
458
- projectName: "tiro",
459
- defaults: {
460
- hostname: DEFAULT_HOSTNAME,
461
- oauthClientId: null,
462
- oauthClientIdRegisteredAt: null,
463
- oauthClientHostname: null,
464
- defaultOutputDir: null
465
- }
466
- });
467
- function validateHostname(input) {
468
- const trimmed = input.trim();
469
- if (trimmed === "") {
470
- throw hostnameError("empty hostname", input);
471
- }
472
- let url;
473
- try {
474
- url = new URL(trimmed);
475
- } catch {
476
- throw hostnameError("not a valid URL", input);
477
- }
478
- if (url.protocol === "https:") {
479
- } else if (url.protocol === "http:" && isLoopback(url.hostname)) {
480
- } else {
481
- throw hostnameError(
482
- `disallowed scheme "${url.protocol}" \u2014 only https:// or http://localhost is permitted`,
483
- input
484
- );
485
- }
486
- if (url.username !== "" || url.password !== "") {
487
- throw hostnameError("URL must not embed credentials", input);
488
- }
489
- if (url.search !== "" || url.hash !== "") {
490
- throw hostnameError("URL must not include query or fragment", input);
491
- }
492
- if (url.pathname !== "" && url.pathname !== "/") {
493
- throw hostnameError("URL must be host root (no path segment)", input);
494
- }
495
- const origin = url.origin;
496
- return stripTrailingSlash(origin);
497
- }
498
- function isLoopback(host) {
499
- if (host.startsWith("[") && host.endsWith("]")) {
500
- host = host.slice(1, -1);
501
- }
502
- return LOOPBACK_HOSTS.has(host);
503
- }
504
- function hostnameError(reason, input) {
505
- return new TiroError(
506
- {
507
- code: "invalid_hostname",
508
- message: `Refusing to use hostname "${input}": ${reason}.`,
509
- errorType: "bad_request",
510
- suggestion: "Use https://<host> (or http://localhost for local dev). If TIRO_HOSTNAME is set in your environment, unset it."
511
- },
512
- ExitCode.Usage
513
- );
514
- }
515
- function getHostname(override) {
516
- if (override !== void 0) return validateHostname(override);
517
- const env = process.env["TIRO_HOSTNAME"];
518
- if (env) return validateHostname(env);
519
- return validateHostname(config.get("hostname"));
520
- }
521
- function getOauthClientId(hostname) {
522
- const id = config.get("oauthClientId");
523
- const registeredAt = config.get("oauthClientIdRegisteredAt");
524
- const cachedHostname = config.get("oauthClientHostname");
525
- if (!id || !registeredAt) return null;
526
- if (cachedHostname !== hostname) return null;
527
- const ttlMs = 29 * 24 * 60 * 60 * 1e3;
528
- if (Date.now() - registeredAt > ttlMs) return null;
529
- return id;
530
- }
531
- function setOauthClientId(clientId, hostname) {
532
- config.set("oauthClientId", clientId);
533
- config.set("oauthClientIdRegisteredAt", Date.now());
534
- config.set("oauthClientHostname", hostname);
535
- }
536
- function clearOauthClientId() {
537
- config.set("oauthClientId", null);
538
- config.set("oauthClientIdRegisteredAt", null);
539
- config.set("oauthClientHostname", null);
540
- }
541
- function stripTrailingSlash(s) {
542
- return s.endsWith("/") ? s.slice(0, -1) : s;
543
- }
544
-
545
- // src/lib/auth/flow.ts
546
- var RegisterResponseSchema = z.object({
547
- client_id: z.string(),
548
- client_secret: z.string().optional()
549
- });
550
- var TokenResponseSchema = z.object({
551
- access_token: z.string(),
552
- token_type: z.string(),
553
- expires_in: z.number().optional(),
554
- scope: z.string().optional()
555
- });
556
- var CALLBACK_TIMEOUT_MS = 5 * 60 * 1e3;
557
- var DEFAULT_SCOPE = "mcp:notes:read";
558
- async function performLogin(options = {}) {
559
- const hostname = getHostname(options.hostname);
560
- const onPrompt = options.onPrompt ?? ((msg) => process.stderr.write(`${msg}
561
- `));
562
- const loopback = await startLoopbackServer();
563
- try {
564
- const clientId = await ensureOauthClient(hostname, loopback.redirectUri);
565
- const { codeVerifier, codeChallenge } = generatePkce();
566
- const state = generateState();
567
- const authorizeUrl = buildAuthorizeUrl({
568
- hostname,
569
- clientId,
570
- redirectUri: loopback.redirectUri,
571
- state,
572
- codeChallenge,
573
- scope: options.scope ?? DEFAULT_SCOPE
574
- });
575
- if (options.noBrowser) {
576
- onPrompt(`Open this URL in your browser:
577
- ${authorizeUrl}`);
578
- } else {
579
- onPrompt(`Opening browser for sign-in...`);
580
- onPrompt(`If the browser does not open, visit:
581
- ${authorizeUrl}`);
582
- await openBrowser(authorizeUrl);
583
- }
584
- const callback = await loopback.waitForCallback(CALLBACK_TIMEOUT_MS);
585
- if (!verifyState(callback.state, state)) {
586
- throw new TiroError(
587
- {
588
- code: "auth_state_mismatch",
589
- message: "OAuth state mismatch \u2014 possible CSRF. Aborting.",
590
- errorType: "unauthorized"
591
- },
592
- ExitCode.Generic
593
- );
594
- }
595
- const tokenRes = await exchangeToken({
596
- hostname,
597
- clientId,
598
- code: callback.code,
599
- redirectUri: loopback.redirectUri,
600
- codeVerifier
601
- });
602
- const expiresAt = computeExpiry(tokenRes.expires_in);
603
- const payload = decodeJwtPayload(tokenRes.access_token);
604
- const userId = typeof payload?.["sub"] === "string" ? payload["sub"] : void 0;
605
- const stored = {
606
- accessToken: tokenRes.access_token,
607
- tokenType: tokenRes.token_type,
608
- expiresAt,
609
- hostname,
610
- ...tokenRes.scope !== void 0 && { scope: tokenRes.scope },
611
- ...userId !== void 0 && { userId }
612
- };
613
- saveToken(stored);
614
- return { hostname, userId, expiresAt };
615
- } finally {
616
- loopback.close();
617
- }
618
- }
619
- async function ensureOauthClient(hostname, redirectUri) {
620
- const cached = getOauthClientId(hostname);
621
- if (cached) return cached;
622
- const url = `${hostname}/v1/mcp/oauth/register`;
623
- let res;
624
- try {
625
- res = await fetch(url, {
626
- method: "POST",
627
- headers: { "Content-Type": "application/json" },
628
- body: JSON.stringify({
629
- client_name: "tiro-cli",
630
- redirect_uris: [redirectUri],
631
- grant_types: ["authorization_code"],
632
- response_types: ["code"],
633
- token_endpoint_auth_method: "none",
634
- scope: DEFAULT_SCOPE
635
- })
636
- });
637
- } catch (err) {
638
- throw new TiroError(
639
- {
640
- code: "network_error",
641
- message: `Failed to reach ${hostname}: ${err.message}`,
642
- errorType: "network_error",
643
- suggestion: "Check your network connection or --hostname."
644
- },
645
- ExitCode.Generic
646
- );
647
- }
648
- if (!res.ok) {
649
- const detail = await safeText(res);
650
- throw new TiroError(
651
- {
652
- code: "oauth_register_failed",
653
- message: `Dynamic Client Registration failed: HTTP ${res.status}`,
654
- errorType: "internal_error",
655
- httpStatus: res.status,
656
- ...detail !== "" && { suggestion: detail.slice(0, 200) }
657
- },
658
- ExitCode.Generic
659
- );
660
- }
661
- const json = await res.json();
662
- const parsed = RegisterResponseSchema.safeParse(json);
663
- if (!parsed.success) {
664
- throw new TiroError(
665
- {
666
- code: "oauth_register_invalid",
667
- message: "Registration response did not match expected shape.",
668
- errorType: "internal_error"
669
- },
670
- ExitCode.Generic
671
- );
672
- }
673
- setOauthClientId(parsed.data.client_id, hostname);
674
- return parsed.data.client_id;
675
- }
676
- function buildAuthorizeUrl(input) {
677
- const u = new URL(`${input.hostname}/v1/mcp/oauth/authorize`);
678
- u.searchParams.set("response_type", "code");
679
- u.searchParams.set("client_id", input.clientId);
680
- u.searchParams.set("redirect_uri", input.redirectUri);
681
- u.searchParams.set("state", input.state);
682
- u.searchParams.set("code_challenge", input.codeChallenge);
683
- u.searchParams.set("code_challenge_method", "S256");
684
- u.searchParams.set("scope", input.scope);
685
- return u.toString();
686
- }
687
- async function exchangeToken(input) {
688
- const url = `${input.hostname}/v1/mcp/oauth/token`;
689
- const body = new URLSearchParams({
690
- grant_type: "authorization_code",
691
- code: input.code,
692
- redirect_uri: input.redirectUri,
693
- client_id: input.clientId,
694
- code_verifier: input.codeVerifier
695
- });
696
- let res;
697
- try {
698
- res = await fetch(url, {
699
- method: "POST",
700
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
701
- body: body.toString()
702
- });
703
- } catch (err) {
704
- throw new TiroError(
705
- {
706
- code: "network_error",
707
- message: `Failed to reach ${input.hostname}: ${err.message}`,
708
- errorType: "network_error"
709
- },
710
- ExitCode.Generic
711
- );
712
- }
713
- if (!res.ok) {
714
- if (res.status === 400 || res.status === 401) {
715
- clearOauthClientId();
716
- }
717
- const detail = await safeText(res);
718
- throw new TiroError(
719
- {
720
- code: "oauth_token_failed",
721
- message: `Token exchange failed: HTTP ${res.status}`,
722
- errorType: "unauthorized",
723
- httpStatus: res.status,
724
- ...detail !== "" && { suggestion: detail.slice(0, 200) }
725
- },
726
- ExitCode.AuthRequired
727
- );
728
- }
729
- const json = await res.json();
730
- const parsed = TokenResponseSchema.safeParse(json);
731
- if (!parsed.success) {
732
- throw new TiroError(
733
- {
734
- code: "oauth_token_invalid",
735
- message: "Token response did not match expected shape.",
736
- errorType: "internal_error"
737
- },
738
- ExitCode.Generic
739
- );
740
- }
741
- return parsed.data;
742
- }
743
- function computeExpiry(expiresIn) {
744
- const fallbackSeconds = 180 * 24 * 60 * 60;
745
- const seconds = expiresIn ?? fallbackSeconds;
746
- return Date.now() + seconds * 1e3;
747
- }
748
- async function safeText(res) {
749
- try {
750
- return await res.text();
751
- } catch {
752
- return "";
753
- }
754
- }
755
-
756
- // src/commands/auth/login.ts
757
- function registerAuthLogin(parent) {
758
- parent.command("login").description("Sign in to Tiro via OAuth (browser-based, PKCE)").option("--hostname <url>", "API base URL (overrides config / TIRO_HOSTNAME)").option("--no-browser", "Print the URL instead of opening a browser").action(async (opts, cmd) => {
759
- const globalOpts = cmd.optsWithGlobals();
760
- const result = await performLogin({
761
- ...opts.hostname !== void 0 && { hostname: opts.hostname },
762
- noBrowser: opts.noBrowser === true,
763
- onPrompt: (msg) => {
764
- if (globalOpts.quiet) return;
765
- process.stderr.write(`${color(msg, "cyan", globalOpts)}
766
- `);
767
- }
768
- });
769
- const hostname = getHostname(opts.hostname);
770
- const expiresIso = new Date(result.expiresAt).toISOString();
771
- if (globalOpts.json) {
772
- printOutput(
773
- {
774
- ok: true,
775
- data: {
776
- signedIn: true,
777
- hostname,
778
- userId: result.userId ?? null,
779
- expiresAt: expiresIso
780
- }
781
- },
782
- globalOpts
783
- );
784
- } else if (!globalOpts.quiet) {
785
- process.stderr.write(`${color("\u2713", "green", globalOpts)} Signed in to ${hostname}
786
- `);
787
- if (result.userId) {
788
- process.stderr.write(` user: ${result.userId}
789
- `);
790
- }
791
- process.stderr.write(` token expires: ${expiresIso}
792
- `);
793
- }
794
- });
795
- }
796
-
797
- // src/commands/auth/status.ts
798
- import "commander";
799
- function registerAuthStatus(parent) {
800
- parent.command("status").description("Show current authenticated account and scopes").action(async (_opts, cmd) => {
801
- const globalOpts = cmd.optsWithGlobals();
802
- const t = resolveToken();
803
- if (!t) {
804
- throw authRequired();
805
- }
806
- const payload = decodeJwtPayload(t.accessToken);
807
- const sub = typeof payload?.["sub"] === "string" ? payload["sub"] : null;
808
- const exp = typeof payload?.["exp"] === "number" ? payload["exp"] * 1e3 : null;
809
- const scope = typeof payload?.["scope"] === "string" ? payload["scope"] : null;
810
- const expMs = exp ?? t.expiresAt ?? null;
811
- const expired = expMs !== null && Date.now() >= expMs;
812
- const report = {
813
- signedIn: true,
814
- source: t.source,
815
- hostname: t.hostname ?? null,
816
- userId: t.userId ?? sub,
817
- scope,
818
- expiresAt: expMs ? new Date(expMs).toISOString() : null,
819
- expired,
820
- tokenPrefix: `${t.accessToken.slice(0, 4)}...***`
821
- };
822
- if (globalOpts.json || !process.stdout.isTTY) {
823
- printOutput({ ok: true, data: report }, globalOpts);
824
- } else {
825
- const headIcon = expired ? color("!", "yellow", globalOpts) : color("\u2713", "green", globalOpts);
826
- const headText = expired ? "Token expired" : "Signed in";
827
- process.stdout.write(`${headIcon} ${headText}
828
- `);
829
- process.stdout.write(` source: ${report.source}
830
- `);
831
- if (report.hostname) process.stdout.write(` hostname: ${report.hostname}
832
- `);
833
- if (report.userId) process.stdout.write(` user: ${report.userId}
834
- `);
835
- if (report.scope) process.stdout.write(` scope: ${report.scope}
836
- `);
837
- if (report.expiresAt) {
838
- const tag = expired ? color(" (expired)", "red", globalOpts) : "";
839
- process.stdout.write(` expires at: ${report.expiresAt}${tag}
840
- `);
841
- }
842
- process.stdout.write(` token: ${report.tokenPrefix}
843
- `);
844
- if (expired) {
845
- process.stdout.write(
846
- `
847
- ${color("\u2192", "gray", globalOpts)} Run \`tiro auth login\` to refresh.
848
- `
849
- );
850
- }
851
- }
852
- });
853
- }
854
-
855
- // src/commands/auth/logout.ts
856
- import "commander";
857
- function registerAuthLogout(parent) {
858
- parent.command("logout").description("Sign out and clear the stored token").action(async (_opts, cmd) => {
859
- const globalOpts = cmd.optsWithGlobals();
860
- const removed = deleteToken();
861
- clearOauthClientId();
862
- if (globalOpts.json) {
863
- printOutput({ ok: true, data: { signedOut: true, hadToken: removed } }, globalOpts);
864
- } else if (!globalOpts.quiet) {
865
- if (removed) {
866
- process.stderr.write(`${color("\u2713", "green", globalOpts)} Signed out
867
- `);
868
- } else {
869
- process.stderr.write(`${color("\u2022", "gray", globalOpts)} No token was stored
870
- `);
871
- }
872
- }
873
- });
874
- }
875
-
876
- // src/commands/auth/index.ts
877
- function registerAuth(program) {
878
- const auth = program.command("auth").description("Manage authentication");
879
- registerAuthLogin(auth);
880
- registerAuthStatus(auth);
881
- registerAuthLogout(auth);
882
- }
883
-
884
- // src/commands/notes/index.ts
885
- import "commander";
886
-
887
- // src/commands/notes/list.ts
888
- import "commander";
889
-
890
- // src/lib/api/client.ts
891
- import "zod";
892
-
893
- // src/lib/api/types.ts
894
- import { z as z2 } from "zod";
895
- var CollaboratorSchema = z2.object({
896
- guid: z2.string(),
897
- name: z2.string(),
898
- email: z2.string(),
899
- role: z2.enum(["OWNER", "EDITOR", "VIEWER"])
900
- });
901
- var ParticipantSchema = z2.object({
902
- name: z2.string().nullable().optional(),
903
- email: z2.string().nullable().optional()
904
- });
905
- var NoteSchema = z2.object({
906
- guid: z2.string(),
907
- title: z2.string(),
908
- createdAt: z2.string(),
909
- updatedAt: z2.string(),
910
- sourceType: z2.string(),
911
- recordingDurationSeconds: z2.number(),
912
- collaborators: z2.array(CollaboratorSchema).optional().default([]),
913
- participants: z2.array(ParticipantSchema).optional().default([]),
914
- webUrl: z2.string(),
915
- recordingStartAt: z2.string().nullable().optional(),
916
- recordingEndAt: z2.string().nullable().optional()
917
- }).passthrough();
918
- var TextObjectSchema = z2.object({
919
- type: z2.string(),
920
- content: z2.string()
921
- });
922
- var SpeakerInfoSchema = z2.object({
923
- label: z2.string(),
924
- personName: z2.string().nullable().optional()
925
- });
926
- var DiarizedSegmentSchema = z2.object({
927
- content: z2.string(),
928
- speaker: SpeakerInfoSchema
929
- });
930
- var ParagraphSchema = z2.object({
931
- uuid: z2.string(),
932
- transcribeLocale: z2.string().nullable().optional(),
933
- transcript: TextObjectSchema.nullable().optional(),
934
- diarizedSegments: z2.array(DiarizedSegmentSchema).nullable().optional(),
935
- timeFrom: z2.string().nullable().optional(),
936
- timeTo: z2.string().nullable().optional(),
937
- locked: z2.boolean().optional()
938
- }).passthrough();
939
- var McpSegmentSchema = z2.object({
940
- content: z2.string(),
941
- speaker: z2.object({
942
- label: z2.string(),
943
- name: z2.string().nullable()
944
- }).nullable()
945
- });
946
- var McpParagraphSchema = z2.object({
947
- timeFrom: z2.string().nullable(),
948
- timeTo: z2.string().nullable(),
949
- segments: z2.array(McpSegmentSchema)
950
- });
951
- var McpTranscriptSchema = z2.object({
952
- noteGuid: z2.string(),
953
- title: z2.string(),
954
- participants: z2.array(z2.string()),
955
- createdAt: z2.string(),
956
- recordingDurationSeconds: z2.number(),
957
- paragraphs: z2.array(McpParagraphSchema)
958
- });
959
- var PageCursorResponseSchema = (item) => z2.object({
960
- content: z2.array(item),
961
- nextCursor: z2.string().nullable()
962
- });
963
- var SimpleListResponseSchema = (item) => z2.object({
964
- content: z2.array(item)
965
- });
966
- var ApiErrorSchema = z2.object({
967
- error: z2.object({
968
- code: z2.number(),
969
- errorType: z2.string(),
970
- message: z2.string(),
971
- detail: z2.string().nullable().optional()
972
- })
973
- });
974
-
975
- // src/lib/api/client.ts
976
- var TiroApiClient = class {
977
- constructor(hostname, token) {
978
- this.hostname = hostname;
979
- this.token = token;
980
- }
981
- hostname;
982
- token;
983
- async getJson(path, schema, params) {
984
- const url = this.buildUrl(path, params);
985
- const res = await this.fetch(url, { method: "GET" });
986
- return this.parseJson(res, schema, "GET", path);
987
- }
988
- async postJson(path, schema, body) {
989
- const url = this.buildUrl(path);
990
- const res = await this.fetch(url, {
991
- method: "POST",
992
- headers: { "Content-Type": "application/json" },
993
- body: JSON.stringify(body)
994
- });
995
- return this.parseJson(res, schema, "POST", path);
996
- }
997
- async putJson(path, schema, body) {
998
- const url = this.buildUrl(path);
999
- const res = await this.fetch(url, {
1000
- method: "PUT",
1001
- headers: { "Content-Type": "application/json" },
1002
- body: JSON.stringify(body)
1003
- });
1004
- return this.parseJson(res, schema, "PUT", path);
1005
- }
1006
- async deleteVoid(path) {
1007
- const url = this.buildUrl(path);
1008
- const res = await this.fetch(url, { method: "DELETE" });
1009
- if (!res.ok) throw await mapHttpError(res, "DELETE", path);
1010
- }
1011
- buildUrl(path, params) {
1012
- return buildApiUrl(this.hostname, path, params);
1013
- }
1014
- async fetch(url, init) {
1015
- const headers = new Headers(init.headers);
1016
- headers.set("Authorization", `Bearer ${this.token}`);
1017
- headers.set("Accept", "application/json");
1018
- try {
1019
- return await fetch(url, { ...init, headers });
1020
- } catch (err) {
1021
- throw new TiroError(
1022
- {
1023
- code: "network_error",
1024
- message: `Network error reaching ${this.hostname}: ${err.message}`,
1025
- errorType: "network_error",
1026
- suggestion: "Check your network or --hostname."
1027
- },
1028
- ExitCode.Generic
1029
- );
1030
- }
1031
- }
1032
- async parseJson(res, schema, method, path) {
1033
- if (!res.ok) throw await mapHttpError(res, method, path);
1034
- let json;
1035
- try {
1036
- json = await res.json();
1037
- } catch (err) {
1038
- throw new TiroError(
1039
- {
1040
- code: "invalid_response",
1041
- message: `Failed to parse JSON from ${method} ${path}: ${err.message}`,
1042
- errorType: "internal_error"
1043
- },
1044
- ExitCode.Generic
1045
- );
1046
- }
1047
- const parsed = schema.safeParse(json);
1048
- if (!parsed.success) {
1049
- throw new TiroError(
1050
- {
1051
- code: "schema_mismatch",
1052
- message: `Response shape did not match expected schema (${method} ${path}).`,
1053
- errorType: "internal_error",
1054
- suggestion: parsed.error.issues.slice(0, 3).map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")
1055
- },
1056
- ExitCode.Generic
1057
- );
1058
- }
1059
- return parsed.data;
1060
- }
1061
- };
1062
- async function mapHttpError(res, method, path) {
1063
- const requestId = res.headers.get("x-request-id") ?? void 0;
1064
- const exitCode = res.status === 401 ? ExitCode.AuthRequired : ExitCode.Generic;
1065
- const apiError = await tryParseApiError(res);
1066
- if (apiError) {
1067
- return new TiroError(
1068
- {
1069
- code: `${apiError.error.errorType}`,
1070
- message: apiError.error.message,
1071
- errorType: apiError.error.errorType,
1072
- httpStatus: res.status,
1073
- ...requestId !== void 0 && { requestId },
1074
- ...res.status === 401 && {
1075
- suggestion: "Run `tiro auth login` to refresh."
1076
- }
1077
- },
1078
- exitCode
1079
- );
1080
- }
1081
- return new TiroError(
1082
- {
1083
- code: "http_error",
1084
- message: `${method} ${path} failed: HTTP ${res.status} ${res.statusText}`,
1085
- errorType: httpStatusToErrorType(res.status),
1086
- httpStatus: res.status,
1087
- ...requestId !== void 0 && { requestId }
1088
- },
1089
- exitCode
1090
- );
1091
- }
1092
- function httpStatusToErrorType(status) {
1093
- if (status === 400) return "bad_request";
1094
- if (status === 401) return "unauthorized";
1095
- if (status === 403) return "forbidden";
1096
- if (status === 404) return "not_found";
1097
- if (status === 409) return "conflict";
1098
- if (status === 413) return "payload_too_large";
1099
- if (status === 422) return "unprocessable_entity";
1100
- if (status === 429) return "too_many_requests";
1101
- return "internal_error";
1102
- }
1103
- async function tryParseApiError(res) {
1104
- try {
1105
- const json = await res.clone().json();
1106
- const parsed = ApiErrorSchema.safeParse(json);
1107
- return parsed.success ? parsed.data : null;
1108
- } catch {
1109
- return null;
1110
- }
1111
- }
1112
- function buildApiUrl(hostname, path, params) {
1113
- if (!path.startsWith("/") || path.startsWith("//") || path.startsWith("/\\")) {
1114
- throw new TiroError(
1115
- {
1116
- code: "internal_error",
1117
- message: `API path must start with a single "/": got ${JSON.stringify(path)}`,
1118
- errorType: "internal_error"
1119
- },
1120
- ExitCode.Generic
1121
- );
1122
- }
1123
- const u = new URL(`${hostname}${path}`);
1124
- if (params) {
1125
- for (const [k, v] of Object.entries(params)) {
1126
- if (v !== void 0 && v !== null && v !== "") {
1127
- u.searchParams.set(k, String(v));
1128
- }
1129
- }
1130
- }
1131
- return u.toString();
1132
- }
1133
- function createApiClient(opts = {}) {
1134
- if (opts.tokenOverride) {
1135
- return new TiroApiClient(getHostname(opts.hostnameOverride), opts.tokenOverride);
1136
- }
1137
- const t = resolveToken();
1138
- if (!t) throw authRequired();
1139
- const hostname = getHostname(opts.hostnameOverride ?? t.hostname);
1140
- return new TiroApiClient(hostname, t.accessToken);
1141
- }
1142
-
1143
- // src/lib/util/parseDate.ts
1144
- var RELATIVE_RE = /^(\d+)([smhdw])$/i;
1145
- var UNIT_MS = {
1146
- s: 1e3,
1147
- m: 6e4,
1148
- h: 36e5,
1149
- d: 864e5,
1150
- w: 6048e5
1151
- };
1152
- function parseDate(input) {
1153
- const trimmed = input.trim();
1154
- const rel = trimmed.match(RELATIVE_RE);
1155
- if (rel) {
1156
- const num = parseInt(rel[1] ?? "", 10);
1157
- const unit = (rel[2] ?? "").toLowerCase();
1158
- const factor = UNIT_MS[unit];
1159
- if (!factor || !Number.isFinite(num)) {
1160
- throw invalidDate(input);
1161
- }
1162
- return new Date(Date.now() - num * factor).toISOString();
1163
- }
1164
- const d = new Date(trimmed);
1165
- if (Number.isNaN(d.getTime())) throw invalidDate(input);
1166
- return d.toISOString();
1167
- }
1168
- function invalidDate(input) {
1169
- return new TiroError(
1170
- {
1171
- code: "invalid_date",
1172
- message: `Invalid date: "${input}". Use ISO-8601 (e.g. 2026-04-01T10:00:00Z) or relative (e.g. 7d, 24h, 30m).`,
1173
- errorType: "bad_request"
1174
- },
1175
- ExitCode.Usage
1176
- );
1177
- }
1178
-
1179
- // src/lib/util/noteFilter.ts
1180
- var PLACEHOLDER_TITLE = "Untitled";
1181
- var PLACEHOLDER_SOURCE_TYPES = /* @__PURE__ */ new Set(["onboarding"]);
1182
- function isVisibleNote(note) {
1183
- if (note.title === PLACEHOLDER_TITLE) return false;
1184
- if (note.sourceType !== null && note.sourceType !== void 0 && PLACEHOLDER_SOURCE_TYPES.has(note.sourceType)) {
1185
- return false;
1186
- }
1187
- return true;
1188
- }
1189
-
1190
- // src/commands/notes/list.ts
1191
- var ListResponseSchema = PageCursorResponseSchema(NoteSchema);
1192
- var DEFAULT_PAGE_SIZE = 100;
1193
- var MAX_PAGE_SIZE = 1e3;
1194
- var HELP_AFTER = `
95
+ </html>`}import ZA from"open";async function Le(e){try{await ZA(e,{wait:!1})}catch{}}import{Entry as oe}from"@napi-rs/keyring";var ne="io.tiro.cli",ie="default";function Re(e){let A=new oe(ne,ie);try{A.setPassword(JSON.stringify(e))}catch(t){throw new f({code:"keychain_write_failed",message:`Failed to write to OS keychain: ${t.message}`,errorType:"internal_error",suggestion:process.platform==="linux"?"Linux requires a Secret Service daemon (gnome-keyring or kwallet). Or set TIRO_TOKEN env var.":"Check OS keychain permissions, or set TIRO_TOKEN env var."},u.Generic)}}function Ee(){let e=new oe(ne,ie),A;try{A=e.getPassword()}catch{return null}if(!A)return null;try{return JSON.parse(A)}catch{return null}}function Ie(){let e=new oe(ne,ie);try{return e.deletePassword()}catch{return!1}}function Q(){let e=process.env.TIRO_TOKEN;if(e)return{accessToken:e,source:"env"};let A=Ee();return A?{accessToken:A.accessToken,source:"keychain",hostname:A.hostname,expiresAt:A.expiresAt,...A.userId!==void 0&&{userId:A.userId}}:null}function z(e){let A=e.split(".");if(A.length!==3)return null;try{let t=A[1];if(!t)return null;let r=Buffer.from(t,"base64url").toString("utf8");return JSON.parse(r)}catch{return null}}import JA from"conf";var $A="https://api.tiro.ooo",_A=new Set(["localhost","127.0.0.1","[::1]","::1"]),x=new JA({projectName:"tiro",defaults:{hostname:$A,oauthClientId:null,oauthClientIdRegisteredAt:null,oauthClientHostname:null,oauthClientRedirectUri:null,defaultOutputDir:null}});function se(e){let A=e.trim();if(A==="")throw X("empty hostname",e);let t;try{t=new URL(A)}catch{throw X("not a valid URL",e)}if(t.protocol!=="https:"){if(!(t.protocol==="http:"&&et(t.hostname)))throw X(`disallowed scheme "${t.protocol}" \u2014 only https:// or http://localhost is permitted`,e)}if(t.username!==""||t.password!=="")throw X("URL must not embed credentials",e);if(t.search!==""||t.hash!=="")throw X("URL must not include query or fragment",e);if(t.pathname!==""&&t.pathname!=="/")throw X("URL must be host root (no path segment)",e);let r=t.origin;return tt(r)}function et(e){return e.startsWith("[")&&e.endsWith("]")&&(e=e.slice(1,-1)),_A.has(e)}function X(e,A){return new f({code:"invalid_hostname",message:`Refusing to use hostname "${A}": ${e}.`,errorType:"bad_request",suggestion:"Use https://<host> (or http://localhost for local dev). If TIRO_HOSTNAME is set in your environment, unset it."},u.Usage)}function O(e){if(e!==void 0)return se(e);let A=process.env.TIRO_HOSTNAME;return se(A||x.get("hostname"))}function Oe(e,A){let t=x.get("oauthClientId"),r=x.get("oauthClientIdRegisteredAt"),n=x.get("oauthClientHostname"),i=x.get("oauthClientRedirectUri");if(!t||!r||n!==e||!i||!At(i,A))return null;let s=696*60*60*1e3;return Date.now()-r>s?null:t}function Xe(e,A,t){x.set("oauthClientId",e),x.set("oauthClientIdRegisteredAt",Date.now()),x.set("oauthClientHostname",A),x.set("oauthClientRedirectUri",t)}function Y(){x.set("oauthClientId",null),x.set("oauthClientIdRegisteredAt",null),x.set("oauthClientHostname",null),x.set("oauthClientRedirectUri",null)}function At(e,A){let t,r;try{t=new URL(e),r=new URL(A)}catch{return!1}return t.protocol===r.protocol&&t.hostname===r.hostname&&t.pathname===r.pathname}function tt(e){return e.endsWith("/")?e.slice(0,-1):e}var rt=B.object({client_id:B.string(),client_secret:B.string().optional()}),ot=B.object({access_token:B.string(),token_type:B.string(),expires_in:B.number().optional(),scope:B.string().optional()}),nt=300*1e3,Fe="mcp:notes:read";async function Se(e={}){let A=O(e.hostname),t=e.onPrompt??(n=>process.stderr.write(`${n}
96
+ `)),r=await xe();try{let n=await it(A,r.redirectUri),{codeVerifier:i,codeChallenge:s}=be(),c=ye(),d=st({hostname:A,clientId:n,redirectUri:r.redirectUri,state:c,codeChallenge:s,scope:e.scope??Fe});e.noBrowser?t(`Open this URL in your browser:
97
+ ${d}`):(t("Opening browser for sign-in..."),t(`If the browser does not open, visit:
98
+ ${d}`),await Le(d));let p=await r.waitForCallback(nt);if(!ke(p.state,c))throw new f({code:"auth_state_mismatch",message:"OAuth state mismatch \u2014 possible CSRF. Aborting.",errorType:"unauthorized"},u.Generic);let l=await at({hostname:A,clientId:n,code:p.code,redirectUri:r.redirectUri,codeVerifier:i}),w=ct(l.expires_in),b=z(l.access_token),h=typeof b?.sub=="string"?b.sub:void 0,T={accessToken:l.access_token,tokenType:l.token_type,expiresAt:w,hostname:A,...l.scope!==void 0&&{scope:l.scope},...h!==void 0&&{userId:h}};return Re(T),{hostname:A,userId:h,expiresAt:w}}finally{r.close()}}async function it(e,A){let t=Oe(e,A);if(t)return t;let r=`${e}/v1/mcp/oauth/register`,n;try{n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:"tiro-cli",redirect_uris:[A],grant_types:["authorization_code"],response_types:["code"],token_endpoint_auth_method:"none",scope:Fe})})}catch(c){throw new f({code:"network_error",message:`Failed to reach ${e}: ${c.message}`,errorType:"network_error",suggestion:"Check your network connection or --hostname."},u.Generic)}if(!n.ok){let c=await De(n);throw new f({code:"oauth_register_failed",message:`Dynamic Client Registration failed: HTTP ${n.status}`,errorType:"internal_error",httpStatus:n.status,...c!==""&&{suggestion:c.slice(0,200)}},u.Generic)}let i=await n.json(),s=rt.safeParse(i);if(!s.success)throw new f({code:"oauth_register_invalid",message:"Registration response did not match expected shape.",errorType:"internal_error"},u.Generic);return Xe(s.data.client_id,e,A),s.data.client_id}function st(e){let A=new URL(`${e.hostname}/v1/mcp/oauth/authorize`);return A.searchParams.set("response_type","code"),A.searchParams.set("client_id",e.clientId),A.searchParams.set("redirect_uri",e.redirectUri),A.searchParams.set("state",e.state),A.searchParams.set("code_challenge",e.codeChallenge),A.searchParams.set("code_challenge_method","S256"),A.searchParams.set("scope",e.scope),A.toString()}async function at(e){let A=`${e.hostname}/v1/mcp/oauth/token`,t=new URLSearchParams({grant_type:"authorization_code",code:e.code,redirect_uri:e.redirectUri,client_id:e.clientId,code_verifier:e.codeVerifier}),r;try{r=await fetch(A,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()})}catch(s){throw new f({code:"network_error",message:`Failed to reach ${e.hostname}: ${s.message}`,errorType:"network_error"},u.Generic)}if(!r.ok){(r.status===400||r.status===401)&&Y();let s=await De(r);throw new f({code:"oauth_token_failed",message:`Token exchange failed: HTTP ${r.status}`,errorType:"unauthorized",httpStatus:r.status,...s!==""&&{suggestion:s.slice(0,200)}},u.AuthRequired)}let n=await r.json(),i=ot.safeParse(n);if(!i.success)throw new f({code:"oauth_token_invalid",message:"Token response did not match expected shape.",errorType:"internal_error"},u.Generic);return i.data}function ct(e){let t=e??15552e3;return Date.now()+t*1e3}async function De(e){try{return await e.text()}catch{return""}}function Pe(e){e.command("login").description("Sign in to Tiro via OAuth (browser-based, PKCE)").option("--hostname <url>","API base URL (overrides config / TIRO_HOSTNAME)").option("--no-browser","Print the URL instead of opening a browser").action(async(A,t)=>{let r=t.optsWithGlobals(),n=await Se({...A.hostname!==void 0&&{hostname:A.hostname},noBrowser:A.noBrowser===!0,onPrompt:c=>{r.quiet||process.stderr.write(`${a(c,"cyan",r)}
99
+ `)}}),i=O(A.hostname),s=new Date(n.expiresAt).toISOString();r.json?v({ok:!0,data:{signedIn:!0,hostname:i,userId:n.userId??null,expiresAt:s}},r):r.quiet||(process.stderr.write(`${a("\u2713","green",r)} Signed in to ${i}
100
+ `),n.userId&&process.stderr.write(` user: ${n.userId}
101
+ `),process.stderr.write(` token expires: ${s}
102
+ `))})}import"commander";import"zod";import{z as o}from"zod";var pt=o.object({guid:o.string(),name:o.string(),email:o.string(),role:o.enum(["OWNER","EDITOR","VIEWER"])}),dt=o.object({name:o.string().nullable().optional(),email:o.string().nullable().optional()}),L=o.object({guid:o.string(),title:o.string(),createdAt:o.string(),updatedAt:o.string(),sourceType:o.string(),recordingDurationSeconds:o.number(),collaborators:o.array(pt).optional().default([]),participants:o.array(dt).optional().default([]),webUrl:o.string(),recordingStartAt:o.string().nullable().optional(),recordingEndAt:o.string().nullable().optional()}).passthrough(),lt=o.object({type:o.string(),content:o.string()}),ut=o.object({label:o.string(),personName:o.string().nullable().optional()}),mt=o.object({content:o.string(),speaker:ut}),F=o.object({uuid:o.string(),transcribeLocale:o.string().nullable().optional(),transcript:lt.nullable().optional(),diarizedSegments:o.array(mt).nullable().optional(),timeFrom:o.string().nullable().optional(),timeTo:o.string().nullable().optional(),locked:o.boolean().optional()}).passthrough(),gt=o.object({content:o.string(),speaker:o.object({label:o.string(),name:o.string().nullable()}).nullable()}),ft=o.object({timeFrom:o.string().nullable(),timeTo:o.string().nullable(),segments:o.array(gt)}),tn=o.object({noteGuid:o.string(),title:o.string(),participants:o.array(o.string()),createdAt:o.string(),recordingDurationSeconds:o.number(),paragraphs:o.array(ft)}),R=e=>o.object({content:o.array(e),nextCursor:o.string().nullable()}),S=e=>o.object({content:o.array(e)}),qe=o.object({error:o.object({code:o.number(),errorType:o.string(),message:o.string(),detail:o.string().nullable().optional()})}),He=o.object({guid:o.string()}).passthrough(),ht=o.object({guid:o.string(),name:o.string(),isWikiEnabled:o.boolean()}).passthrough(),We=o.object({workspaces:o.array(ht)}).passthrough(),Me=o.object({workspaceGuid:o.string().nullable(),userId:o.number().nullable().optional(),apiKeyName:o.string().nullable().optional()}).passthrough(),wt=o.object({guid:o.string(),wikiId:o.number(),canonicalName:o.string(),pageType:o.string(),entitySubtype:o.string().nullable().optional(),score:o.number()}).passthrough(),Ne=o.object({items:o.array(wt)}).passthrough(),Ge=o.object({guid:o.string(),noteId:o.number(),paragraphId:o.number().nullable().optional(),paragraphUuid:o.string().nullable().optional(),kind:o.string(),sourceUserId:o.number(),extractedText:o.string(),confidence:o.number().nullable().optional(),createdAt:o.string()}).passthrough(),bt=o.object({guid:o.string(),alias:o.string(),source:o.string(),sourceMentionGuid:o.string().nullable().optional(),sourceUserId:o.number().nullable().optional(),createdAt:o.string()}).passthrough(),yt=o.object({guid:o.string(),sourcePageGuid:o.string(),sourcePageName:o.string().nullable().optional(),targetPageGuid:o.string(),targetPageName:o.string().nullable().optional(),linkType:o.string(),linkTypeDisplayKo:o.string().optional(),linkTypeDisplayEn:o.string().optional(),isDirectional:o.boolean(),source:o.string().optional(),creatorUserId:o.number().nullable().optional(),createdAt:o.string().optional(),updatedAt:o.string().optional()}).passthrough(),Ve=o.object({guid:o.string(),wikiId:o.number(),canonicalName:o.string(),description:o.string().nullable().optional(),descriptionStatus:o.string().nullable().optional(),regenerationAvailable:o.boolean().nullable().optional(),pageType:o.string(),entitySubtype:o.string().nullable().optional(),extractionStatus:o.string(),mentionCountVisible:o.number(),mentions:o.array(Ge),aliases:o.array(bt),links:o.array(yt),lastUpdatedVisible:o.string().nullable().optional(),createdAt:o.string(),updatedAt:o.string()}).passthrough(),Ue=o.object({items:o.array(Ge),nextCursorCreatedAt:o.string().nullable(),nextCursorId:o.number().nullable()}).passthrough(),kt=o.object({guid:o.string(),canonicalName:o.string(),pageType:o.string(),entitySubtype:o.string().nullable().optional(),extractionStatus:o.string(),mentionCountVisible:o.number()}).passthrough(),Ct=o.object({guid:o.string(),sourcePageGuid:o.string(),targetPageGuid:o.string(),linkType:o.string(),linkTypeDisplayKo:o.string().optional(),linkTypeDisplayEn:o.string().optional(),isDirectional:o.boolean()}).passthrough(),M=o.object({nodes:o.array(kt),edges:o.array(Ct)}).passthrough(),je=o.object({error_code:o.enum(["WIKI_PLAN_REQUIRED","WIKI_NOT_ACTIVATED"]),message:o.string(),current_plan:o.string().nullable().optional(),required_plans:o.array(o.string()).nullable().optional(),action_url:o.string().nullable().optional()}).passthrough(),Qe=o.object({id:o.string(),workspaceGuid:o.string(),title:o.string(),description:o.string(),color:o.string(),sharingType:o.string(),parentId:o.string().nullable().optional(),isTeamFolder:o.boolean(),createdAt:o.string(),updatedAt:o.string()}).passthrough(),ae=o.lazy(()=>o.object({id:o.string(),title:o.string(),parentId:o.string().nullable().optional(),depth:o.number(),isAccessible:o.boolean(),children:o.array(ae)})),ze=o.object({id:o.number(),entry:o.string(),createdAt:o.string()}).passthrough();var K=class{constructor(A,t){this.hostname=A;this.token=t}hostname;token;async getJson(A,t,r){let n=this.buildUrl(A,r),i=await this.fetch(n,{method:"GET"});return this.parseJson(i,t,"GET",A)}async postJson(A,t,r){let n=this.buildUrl(A),i=await this.fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});return this.parseJson(i,t,"POST",A)}async putJson(A,t,r){let n=this.buildUrl(A),i=await this.fetch(n,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});return this.parseJson(i,t,"PUT",A)}async deleteVoid(A){let t=this.buildUrl(A),r=await this.fetch(t,{method:"DELETE"});if(!r.ok)throw await Ye(r,"DELETE",A)}buildUrl(A,t){return Lt(this.hostname,A,t)}async fetch(A,t){let r=new Headers(t.headers);r.set("Authorization",`Bearer ${this.token}`),r.set("Accept","application/json");try{return await fetch(A,{...t,headers:r})}catch(n){throw new f({code:"network_error",message:`Network error reaching ${this.hostname}: ${n.message}`,errorType:"network_error",suggestion:"Check your network or --hostname."},u.Generic)}}async parseJson(A,t,r,n){if(!A.ok)throw await Ye(A,r,n);let i;try{i=await A.json()}catch(c){throw new f({code:"invalid_response",message:`Failed to parse JSON from ${r} ${n}: ${c.message}`,errorType:"internal_error"},u.Generic)}let s=t.safeParse(i);if(!s.success)throw new f({code:"schema_mismatch",message:`Response shape did not match expected schema (${r} ${n}).`,errorType:"internal_error",suggestion:s.error.issues.slice(0,3).map(c=>`${c.path.join(".")||"(root)"}: ${c.message}`).join("; ")},u.Generic);return s.data}};async function Ye(e,A,t){let r=e.headers.get("x-request-id")??void 0,n=e.status===401?u.AuthRequired:u.Generic;if(e.status===402){let s=await xt(e);if(s)return Bt(s,r)}let i=await Tt(e);return i?new f({code:`${i.error.errorType}`,message:i.error.message,errorType:i.error.errorType,httpStatus:e.status,...r!==void 0&&{requestId:r},...e.status===401&&{suggestion:"Run `tiro auth login` to refresh."}},n):new f({code:"http_error",message:`${A} ${t} failed: HTTP ${e.status} ${e.statusText}`,errorType:vt(e.status),httpStatus:e.status,...r!==void 0&&{requestId:r}},n)}function vt(e){return e===400?"bad_request":e===401?"unauthorized":e===402?"payment_required":e===403?"forbidden":e===404?"not_found":e===409?"conflict":e===413?"payload_too_large":e===422?"unprocessable_entity":e===429?"too_many_requests":"internal_error"}async function Tt(e){try{let A=await e.clone().json(),t=qe.safeParse(A);return t.success?t.data:null}catch{return null}}async function xt(e){try{let A=await e.clone().json(),t=je.safeParse(A);return t.success?t.data:null}catch{return null}}function Bt(e,A){let t=e.action_url??null;return new f({code:e.error_code,message:e.message,errorType:"payment_required",httpStatus:402,...t?{suggestion:`Upgrade: ${t}`}:{},...A!==void 0&&{requestId:A},details:{...e}},u.Generic)}function Lt(e,A,t){if(!A.startsWith("/")||A.startsWith("//")||A.startsWith("/\\"))throw new f({code:"internal_error",message:`API path must start with a single "/": got ${JSON.stringify(A)}`,errorType:"internal_error"},u.Generic);let r=new URL(`${e}${A}`);if(t)for(let[n,i]of Object.entries(t))i!=null&&i!==""&&r.searchParams.set(n,String(i));return r.toString()}function k(e={}){if(e.tokenOverride)return new K(O(e.hostnameOverride),e.tokenOverride);let A=Q();if(!A)throw W();let t=O(e.hostnameOverride??A.hostname);return new K(t,A.accessToken)}var Ke=new WeakMap;async function E(e){let A=Ke.get(e);if(A)return A;let t=e.getJson("/v1/external/workspaces/me",He).then(r=>r.guid);return Ke.set(e,t),t}async function Ze(e){return(await e.getJson("/v1/external/workspaces",We)).workspaces}async function ce(e){return e.getJson("/v1/external/auth/me",Me)}async function N(e,A){return A||(await ce(e)).workspaceGuid}var Z="Credential is not bound to a workspace; listing across all your workspaces. Pass --workspace <guid> (see `tiro wiki workspaces`) or use a workspace-scoped API key to target one.";async function D(e,A){let t=await N(e,A);if(!t)throw new f({code:"workspace_required",message:"This command targets a single workspace, but your credential is not bound to one.",errorType:"bad_request",suggestion:"Pass --workspace <guid> (run `tiro wiki workspaces` for guids) or use a workspace-scoped API key."},u.Usage);return t}function Je(e){e.command("status").description("Show current authenticated account and scopes").action(async(A,t)=>{let r=t.optsWithGlobals(),n=Q();if(!n)throw W();let i=z(n.accessToken),s=typeof i?.sub=="string"?i.sub:null,c=typeof i?.exp=="number"?i.exp*1e3:null,d=typeof i?.scope=="string"?i.scope:null,p=c??n.expiresAt??null,l=p!==null&&Date.now()>=p,w=null,b=!1;if(!l)try{let T=k({tokenOverride:n.accessToken,hostnameOverride:r.hostname??n.hostname??void 0});w=(await ce(T)).workspaceGuid,b=!0}catch{}let h={signedIn:!0,source:n.source,hostname:n.hostname??null,userId:n.userId??s,scope:d,...b&&{workspace:w},expiresAt:p?new Date(p).toISOString():null,expired:l,tokenPrefix:`${n.accessToken.slice(0,4)}...***`};if(r.json||!process.stdout.isTTY)v({ok:!0,data:h},r);else{let T=l?a("!","yellow",r):a("\u2713","green",r),H=l?"Token expired":"Signed in";if(process.stdout.write(`${T} ${H}
103
+ `),process.stdout.write(` source: ${h.source}
104
+ `),h.hostname&&process.stdout.write(` hostname: ${h.hostname}
105
+ `),h.userId&&process.stdout.write(` user: ${h.userId}
106
+ `),h.scope&&process.stdout.write(` scope: ${h.scope}
107
+ `),b?process.stdout.write(` workspace: ${w??a("(unbound \u2014 across all workspaces)","gray",r)}
108
+ `):l||process.stdout.write(` workspace: ${a("(unable to verify)","yellow",r)}
109
+ `),h.expiresAt){let Ae=l?a(" (expired)","red",r):"";process.stdout.write(` expires at: ${h.expiresAt}${Ae}
110
+ `)}process.stdout.write(` token: ${h.tokenPrefix}
111
+ `),l&&process.stdout.write(`
112
+ ${a("\u2192","gray",r)} Run \`tiro auth login\` to refresh.
113
+ `)}})}import"commander";function $e(e){e.command("logout").description("Sign out and clear the stored token").action(async(A,t)=>{let r=t.optsWithGlobals(),n=Ie();Y(),r.json?v({ok:!0,data:{signedOut:!0,hadToken:n}},r):r.quiet||(n?process.stderr.write(`${a("\u2713","green",r)} Signed out
114
+ `):process.stderr.write(`${a("\u2022","gray",r)} No token was stored
115
+ `))})}function _e(e){let A=e.command("auth").description("Manage authentication");Pe(A),Je(A),$e(A)}import"commander";import"commander";var Rt=/^(\d+)([smhdw])$/i,Et={s:1e3,m:6e4,h:36e5,d:864e5,w:6048e5};function I(e){let A=e.trim(),t=A.match(Rt);if(t){let n=parseInt(t[1]??"",10),i=(t[2]??"").toLowerCase(),s=Et[i];if(!s||!Number.isFinite(n))throw eA(e);return new Date(Date.now()-n*s).toISOString()}let r=new Date(A);if(Number.isNaN(r.getTime()))throw eA(e);return r.toISOString()}function eA(e){return new f({code:"invalid_date",message:`Invalid date: "${e}". Use ISO-8601 (e.g. 2026-04-01T10:00:00Z) or relative (e.g. 7d, 24h, 30m).`,errorType:"bad_request"},u.Usage)}var It="Untitled",Ot=new Set(["onboarding"]);function J(e){return!(e.title===It||e.sourceType!==null&&e.sourceType!==void 0&&Ot.has(e.sourceType))}var Xt=R(L),AA=100,tA=200,Ft=`
1195
116
  Examples:
1196
117
  tiro notes list --since 7d
1197
118
  tiro notes list --keyword "OKR" --since 30d --json
@@ -1207,101 +128,12 @@ Keyword matching:
1207
128
  Note: placeholder notes (title='Untitled' or sourceType='onboarding') are
1208
129
  filtered out by default. A page of N may return fewer than N visible notes \u2014
1209
130
  keep paginating to fetch more, or pass --include-untitled to surface them.
1210
- `;
1211
- function registerNotesList(parent) {
1212
- parent.command("list").description("List notes (lightweight metadata).").option("--keyword <text>", 'Reorder by full-text relevance for this keyword (e.g. "OKR")').option("--folder <id>", "Restrict to a folder and its descendants").option(
1213
- "--since <date>",
1214
- "Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)"
1215
- ).option("--until <date>", "Exclusive upper bound on createdAt").option(
1216
- "--limit <n>",
1217
- `Max results per page (default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE})`
1218
- ).option("--cursor <token>", "Continue a previous page").option(
1219
- "--include-untitled",
1220
- "Include placeholder notes (title='Untitled' or sourceType='onboarding'). Default: hidden",
1221
- false
1222
- ).addHelpText("after", HELP_AFTER).action(async (opts, cmd) => {
1223
- const globalOpts = cmd.optsWithGlobals();
1224
- const client = createApiClient({
1225
- ...globalOpts.hostname !== void 0 && { hostnameOverride: globalOpts.hostname }
1226
- });
1227
- const params = {};
1228
- if (opts.keyword) params["keyword"] = opts.keyword;
1229
- if (opts.folder) params["folderId"] = opts.folder;
1230
- if (opts.since) params["createdAtFrom"] = parseDate(opts.since);
1231
- if (opts.until) params["createdAtTo"] = parseDate(opts.until);
1232
- const size = clampLimit(opts.limit);
1233
- if (size !== void 0) params["size"] = size;
1234
- if (opts.cursor) params["cursor"] = opts.cursor;
1235
- const res = await client.getJson("/v1/external/notes", ListResponseSchema, params);
1236
- const visible = opts.includeUntitled === true ? res.content : res.content.filter(isVisibleNote);
1237
- const mode = resolveOutputMode(globalOpts);
1238
- if (mode === "json") {
1239
- for (const note of visible) printNdjson(note);
1240
- if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });
1241
- } else {
1242
- printPretty(visible, res.nextCursor, globalOpts);
1243
- }
1244
- });
1245
- }
1246
- function clampLimit(raw) {
1247
- if (!raw) return void 0;
1248
- const n = parseInt(raw, 10);
1249
- if (!Number.isFinite(n) || n <= 0) return DEFAULT_PAGE_SIZE;
1250
- return Math.min(n, MAX_PAGE_SIZE);
1251
- }
1252
- function printPretty(notes, nextCursor, opts) {
1253
- if (notes.length === 0) {
1254
- process.stdout.write(`${color("(no notes)", "gray", opts)}
1255
- `);
1256
- return;
1257
- }
1258
- const titleWidth = computeTitleWidth();
1259
- for (const n of notes) {
1260
- const date = n.createdAt.slice(0, 10);
1261
- const dur = formatDuration(n.recordingDurationSeconds);
1262
- const title = truncate(n.title, titleWidth);
1263
- process.stdout.write(
1264
- `${color(date, "gray", opts)} ${color(n.guid, "dim", opts)} ${color(dur, "cyan", opts)} ${title}
1265
- `
1266
- );
1267
- }
1268
- if (nextCursor) {
1269
- process.stdout.write(
1270
- `${color(`
1271
- next: --cursor ${nextCursor}`, "gray", opts)}
1272
- `
1273
- );
1274
- }
1275
- }
1276
- function computeTitleWidth() {
1277
- const cols = process.stdout.columns;
1278
- if (!cols || cols < 60) return 40;
1279
- return Math.max(20, cols - 60);
1280
- }
1281
- function truncate(s, max) {
1282
- if (s.length <= max) return s;
1283
- return s.slice(0, Math.max(0, max - 1)) + "\u2026";
1284
- }
1285
- function formatDuration(sec) {
1286
- if (!sec || sec <= 0) return "\u2014";
1287
- const m = Math.floor(sec / 60);
1288
- const s = Math.floor(sec % 60);
1289
- if (m > 0) return `${m}m${s.toString().padStart(2, "0")}s`;
1290
- return `${s}s`;
1291
- }
1292
-
1293
- // src/commands/notes/search.ts
1294
- import "commander";
1295
- import { z as z4 } from "zod";
1296
- var SearchResponseSchema = z4.object({
1297
- notes: z4.array(NoteSchema),
1298
- nextCursor: z4.string().nullable(),
1299
- degraded: z4.boolean().optional(),
1300
- degradedReason: z4.string().nullable().optional()
1301
- }).passthrough();
1302
- var DEFAULT_PAGE_SIZE2 = 100;
1303
- var MAX_PAGE_SIZE2 = 1e3;
1304
- var HELP_AFTER2 = `
131
+ `;function rA(e){e.command("list").description("List notes (lightweight metadata).").option("--keyword <text>",'Reorder by full-text relevance for this keyword (e.g. "OKR")').option("--folder <id>","Restrict to a folder and its descendants").option("--since <date>","Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)").option("--until <date>","Exclusive upper bound on createdAt").option("--limit <n>",`Max results per page (default ${AA}, max ${tA})`).option("--cursor <token>","Continue a previous page").option("--workspace <guid>","List within one workspace (see `tiro wiki workspaces`). Default: the workspace your API key is bound to, else across all your workspaces").option("--include-untitled","Include placeholder notes (title='Untitled' or sourceType='onboarding'). Default: hidden",!1).addHelpText("after",Ft).action(async(A,t)=>{let r=t.optsWithGlobals(),n=k({...r.hostname!==void 0&&{hostnameOverride:r.hostname}}),i={};A.keyword&&(i.keyword=A.keyword),A.folder&&(i.folderId=A.folder),A.since&&(i.createdAtFrom=I(A.since)),A.until&&(i.createdAtTo=I(A.until));let s=St(A.limit);s!==void 0&&(i.size=s),A.cursor&&(i.cursor=A.cursor);let c=await N(n,A.workspace);!c&&r.quiet!==!0&&process.stderr.write(`${a("\u26A0","yellow",r)} ${Z}
132
+ `);let d=c?`/v1/external/workspaces/${encodeURIComponent(c)}/notes`:"/v1/external/notes",p=await n.getJson(d,Xt,i),l=A.includeUntitled===!0?p.content:p.content.filter(J);if(y(r)==="json"){for(let b of l)C(b);p.nextCursor&&C({_cursor:p.nextCursor})}else Dt(l,p.nextCursor,r)})}function St(e){if(!e)return;let A=parseInt(e,10);return!Number.isFinite(A)||A<=0?AA:Math.min(A,tA)}function Dt(e,A,t){if(e.length===0){process.stdout.write(`${a("(no notes)","gray",t)}
133
+ `);return}let r=Pt();for(let n of e){let i=n.createdAt.slice(0,10),s=Ht(n.recordingDurationSeconds),c=qt(n.title,r);process.stdout.write(`${a(i,"gray",t)} ${a(n.guid,"dim",t)} ${a(s,"cyan",t)} ${c}
134
+ `)}A&&process.stdout.write(`${a(`
135
+ next: --cursor ${A}`,"gray",t)}
136
+ `)}function Pt(){let e=process.stdout.columns;return!e||e<60?40:Math.max(20,e-60)}function qt(e,A){return e.length<=A?e:e.slice(0,Math.max(0,A-1))+"\u2026"}function Ht(e){if(!e||e<=0)return"\u2014";let A=Math.floor(e/60),t=Math.floor(e%60);return A>0?`${A}m${t.toString().padStart(2,"0")}s`:`${t}s`}import"commander";import{z as G}from"zod";var Wt=G.object({notes:G.array(L),nextCursor:G.string().nullable(),degraded:G.boolean().optional(),degradedReason:G.string().nullable().optional()}).passthrough(),oA=100,nA=200,Mt=`
1305
137
  Examples:
1306
138
  tiro notes search "Q3 Planning"
1307
139
  tiro notes search "Acme Corp" --since 7d --json
@@ -1321,344 +153,25 @@ Ordering:
1321
153
 
1322
154
  Note: placeholder notes (title='Untitled' or sourceType='onboarding') are
1323
155
  filtered out by default. Pass --include-untitled to surface them.
1324
- `;
1325
- function registerNotesSearch(parent) {
1326
- parent.command("search [keyword]").description("Deep keyword search \u2014 returns notes hydrated with their primary documents.").option(
1327
- "--keyword <text>",
1328
- 'Alternative to positional keyword (e.g. --keyword "Q3 Planning")'
1329
- ).option("--folder <id>", "Restrict hits to a folder and its descendants").option(
1330
- "--since <date>",
1331
- "Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)"
1332
- ).option("--until <date>", "Exclusive upper bound on createdAt").option(
1333
- "--limit <n>",
1334
- `Max results per page (default ${DEFAULT_PAGE_SIZE2}, max ${MAX_PAGE_SIZE2})`
1335
- ).option(
1336
- "--cursor <token>",
1337
- "Continue a previous page (reserved \u2014 backend currently always null)"
1338
- ).option(
1339
- "--include-untitled",
1340
- "Include placeholder notes. Default: hidden",
1341
- false
1342
- ).addHelpText("after", HELP_AFTER2).action(async (positional, opts, cmd) => {
1343
- const globalOpts = cmd.optsWithGlobals();
1344
- const keyword = (positional ?? opts.keyword ?? "").trim();
1345
- if (!keyword) {
1346
- throw new TiroError(
1347
- {
1348
- code: "missing_keyword",
1349
- message: "search requires a keyword (positional or --keyword).",
1350
- errorType: "bad_request",
1351
- suggestion: 'tiro notes search "OKR"'
1352
- },
1353
- ExitCode.Usage
1354
- );
1355
- }
1356
- const filter = {};
1357
- if (opts.folder) filter["folderId"] = opts.folder;
1358
- if (opts.since) filter["createdAtFrom"] = parseDate(opts.since);
1359
- if (opts.until) filter["createdAtTo"] = parseDate(opts.until);
1360
- const pagination = {};
1361
- const size = clampLimit2(opts.limit);
1362
- if (size !== void 0) pagination["size"] = size;
1363
- if (opts.cursor) pagination["cursor"] = opts.cursor;
1364
- const body = { keyword };
1365
- if (Object.keys(filter).length > 0) body["filter"] = filter;
1366
- if (Object.keys(pagination).length > 0) body["pagination"] = pagination;
1367
- const client = createApiClient({
1368
- ...globalOpts.hostname !== void 0 && { hostnameOverride: globalOpts.hostname }
1369
- });
1370
- const res = await client.postJson(
1371
- "/v1/external/notes/search",
1372
- SearchResponseSchema,
1373
- body
1374
- );
1375
- const visible = opts.includeUntitled === true ? res.notes : res.notes.filter(isVisibleNote);
1376
- const mode = resolveOutputMode(globalOpts);
1377
- if (mode === "json") {
1378
- for (const note of visible) printNdjson(note);
1379
- if (res.nextCursor) printNdjson({ _cursor: res.nextCursor });
1380
- if (res.degraded === true) {
1381
- printNdjson({ _degraded: true, _degradedReason: res.degradedReason ?? null });
1382
- }
1383
- } else {
1384
- printPretty2(visible, res.nextCursor, globalOpts);
1385
- if (res.degraded === true && globalOpts.quiet !== true) {
1386
- process.stderr.write(
1387
- `${color("\u26A0", "yellow", globalOpts)} search results are partial${res.degradedReason ? ` (${res.degradedReason})` : ""}
1388
- `
1389
- );
1390
- }
1391
- }
1392
- });
1393
- }
1394
- function clampLimit2(raw) {
1395
- if (!raw) return void 0;
1396
- const n = parseInt(raw, 10);
1397
- if (!Number.isFinite(n) || n <= 0) return DEFAULT_PAGE_SIZE2;
1398
- return Math.min(n, MAX_PAGE_SIZE2);
1399
- }
1400
- function printPretty2(notes, nextCursor, opts) {
1401
- if (notes.length === 0) {
1402
- process.stdout.write(`${color("(no matches)", "gray", opts)}
1403
- `);
1404
- return;
1405
- }
1406
- for (const n of notes) {
1407
- const date = n.createdAt.slice(0, 10);
1408
- process.stdout.write(
1409
- `${color(date, "gray", opts)} ${color(n.guid, "dim", opts)} ${n.title}
1410
- `
1411
- );
1412
- }
1413
- if (nextCursor) {
1414
- process.stdout.write(
1415
- `${color(`
1416
- next: --cursor ${nextCursor}`, "gray", opts)}
1417
- `
1418
- );
1419
- }
1420
- }
1421
-
1422
- // src/commands/notes/get.ts
1423
- import "commander";
1424
-
1425
- // src/lib/output/file.ts
1426
- import { mkdir, rename, stat, writeFile, access } from "fs/promises";
1427
- import { dirname as dirname2, resolve as resolve2, sep } from "path";
1428
- function assertSafeOutputPath(input) {
1429
- if (input.trim() === "") {
1430
- throw outputError("output path is empty", input);
1431
- }
1432
- const segments = input.split(/[\\/]/);
1433
- for (const seg of segments) {
1434
- if (seg === "..") {
1435
- throw outputError("path traversal segment '..' is not allowed", input);
1436
- }
1437
- }
1438
- }
1439
- function outputError(reason, input) {
1440
- return new TiroError(
1441
- {
1442
- code: "unsafe_output_path",
1443
- message: `Refusing to write to ${JSON.stringify(input)}: ${reason}.`,
1444
- errorType: "bad_request",
1445
- suggestion: "Use a path without '..' segments, or pass --force if you really mean it."
1446
- },
1447
- ExitCode.Usage
1448
- );
1449
- }
1450
- async function writeFileAtomic(filepath, content, opts = {}) {
1451
- if (!opts.force) {
1452
- assertSafeOutputPath(filepath);
1453
- }
1454
- const absPath = resolve2(filepath);
1455
- await mkdir(dirname2(absPath), { recursive: true });
1456
- if (!opts.force) {
1457
- const exists = await fileExists(absPath);
1458
- if (exists) {
1459
- throw new TiroError(
1460
- {
1461
- code: "file_exists",
1462
- message: `File already exists: ${absPath}`,
1463
- errorType: "conflict",
1464
- suggestion: "Use --force to overwrite, or pick a different --output."
1465
- },
1466
- ExitCode.Generic
1467
- );
1468
- }
1469
- }
1470
- const tmp = `${absPath}.tmp.${process.pid}.${Date.now()}`;
1471
- await writeFile(tmp, content, "utf8");
1472
- await rename(tmp, absPath);
1473
- const s = await stat(absPath);
1474
- return { path: absPath, size: s.size };
1475
- }
1476
- async function fileExists(p) {
1477
- try {
1478
- await access(p);
1479
- return true;
1480
- } catch {
1481
- return false;
1482
- }
1483
- }
1484
-
1485
- // src/lib/output/transcript.ts
1486
- function buildMcpTranscript(note, paragraphs) {
1487
- return {
1488
- noteGuid: note.guid,
1489
- title: note.title,
1490
- participants: note.participants?.map((p) => p.name || p.email || "").filter((s) => typeof s === "string" && s.length > 0) ?? [],
1491
- createdAt: note.createdAt,
1492
- recordingDurationSeconds: note.recordingDurationSeconds,
1493
- paragraphs: paragraphsToMcp(paragraphs)
1494
- };
1495
- }
1496
- function paragraphsToMcp(paragraphs) {
1497
- return paragraphs.map((p) => ({
1498
- timeFrom: p.timeFrom ?? null,
1499
- timeTo: p.timeTo ?? null,
1500
- segments: paragraphToSegments(p)
1501
- })).filter((p) => p.segments.length > 0);
1502
- }
1503
- function paragraphToSegments(p) {
1504
- const ds = p.diarizedSegments;
1505
- if (ds && ds.length > 0) {
1506
- return ds.map((s) => ({
1507
- content: stripHtml(s.content),
1508
- speaker: {
1509
- label: s.speaker.label,
1510
- name: s.speaker.personName ? stripHtml(s.speaker.personName) : null
1511
- }
1512
- })).filter((s) => s.content.length > 0);
1513
- }
1514
- const plain = stripHtml(p.transcript?.content ?? "");
1515
- return plain ? [{ content: plain, speaker: null }] : [];
1516
- }
1517
- function renderTranscriptJson(t) {
1518
- return `${JSON.stringify(t, null, 2)}
1519
- `;
1520
- }
1521
- function renderTranscriptMarkdown(t, opts = {}) {
1522
- const showTs = opts.timestamps !== false;
1523
- const anchor = showTs ? anchorTime(t) : null;
1524
- const lines = [];
1525
- lines.push(`# ${t.title}`, "");
1526
- if (t.participants.length > 0) {
1527
- lines.push(`**Participants**: ${t.participants.join(", ")}`, "");
1528
- }
1529
- lines.push("## Transcript", "");
1530
- for (const p of t.paragraphs) {
1531
- if (showTs) {
1532
- const ts = elapsed(p.timeFrom, anchor);
1533
- if (ts) lines.push(`### ${ts}`, "");
1534
- }
1535
- for (const s of p.segments) {
1536
- const who = s.speaker?.name ?? s.speaker?.label ?? "Unknown";
1537
- lines.push(`**${who}**: ${s.content}`);
1538
- }
1539
- lines.push("");
1540
- }
1541
- return `${lines.join("\n").trimEnd()}
1542
- `;
1543
- }
1544
- function renderTranscriptText(t) {
1545
- const lines = [];
1546
- for (const p of t.paragraphs) {
1547
- for (const s of p.segments) {
1548
- const who = s.speaker?.name ?? s.speaker?.label ?? "Unknown";
1549
- lines.push(`[${who}] ${s.content}`);
1550
- }
1551
- }
1552
- return `${lines.join("\n")}
1553
- `;
1554
- }
1555
- function anchorTime(t) {
1556
- for (const p of t.paragraphs) {
1557
- if (p.timeFrom) return p.timeFrom;
1558
- }
1559
- return null;
1560
- }
1561
- function elapsed(currentIso, anchorIso) {
1562
- if (!currentIso || !anchorIso) return "";
1563
- const cur = Date.parse(currentIso);
1564
- const anc = Date.parse(anchorIso);
1565
- if (!Number.isFinite(cur) || !Number.isFinite(anc)) return "";
1566
- const seconds = Math.max(0, Math.floor((cur - anc) / 1e3));
1567
- const h = Math.floor(seconds / 3600);
1568
- const m = Math.floor(seconds % 3600 / 60);
1569
- const s = seconds % 60;
1570
- if (h > 0) return `${pad(h)}:${pad(m)}:${pad(s)}`;
1571
- return `${pad(m)}:${pad(s)}`;
1572
- }
1573
- function pad(n) {
1574
- return n.toString().padStart(2, "0");
1575
- }
1576
- function stripHtml(s) {
1577
- return s.replace(/<[^>]*>/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").trim();
1578
- }
1579
-
1580
- // src/lib/output/format.ts
1581
- function formatNote(note, format, opts = {}) {
1582
- switch (format) {
1583
- case "md":
1584
- return formatMarkdown(note, opts);
1585
- case "json":
1586
- return formatJson(note, opts);
1587
- case "txt":
1588
- return formatText(note, opts);
1589
- }
1590
- }
1591
- function formatMarkdown(note, opts) {
1592
- const fm = [
1593
- "---",
1594
- `guid: ${escapeYaml(note.guid)}`,
1595
- `title: ${escapeYaml(note.title)}`,
1596
- `createdAt: ${note.createdAt}`,
1597
- `updatedAt: ${note.updatedAt}`,
1598
- `sourceType: ${note.sourceType}`,
1599
- `recordingDurationSeconds: ${note.recordingDurationSeconds}`,
1600
- `webUrl: ${note.webUrl}`
1601
- ];
1602
- if (note.recordingStartAt) fm.push(`recordingStartAt: ${note.recordingStartAt}`);
1603
- if (note.recordingEndAt) fm.push(`recordingEndAt: ${note.recordingEndAt}`);
1604
- fm.push("---", "");
1605
- const parts = [fm.join("\n"), `# ${note.title}`, ""];
1606
- if (note.participants && note.participants.length > 0) {
1607
- parts.push("## Participants", "");
1608
- for (const p of note.participants) {
1609
- const name = p.name ?? "(no name)";
1610
- const email = p.email ? ` <${p.email}>` : "";
1611
- parts.push(`- ${name}${email}`);
1612
- }
1613
- parts.push("");
1614
- }
1615
- if (opts.includeTranscript && opts.paragraphs && opts.paragraphs.length > 0) {
1616
- const mcp = buildMcpTranscript(note, opts.paragraphs);
1617
- const transcriptBody = renderTranscriptMarkdown(mcp);
1618
- const startsWithHeader = transcriptBody.startsWith(`# ${note.title}`);
1619
- const trimmed = startsWithHeader ? transcriptBody.slice(transcriptBody.indexOf("\n") + 1) : transcriptBody;
1620
- parts.push(trimmed.replace(/^\s*\n+/, ""));
1621
- }
1622
- return `${parts.join("\n").trimEnd()}
1623
- `;
1624
- }
1625
- function formatJson(note, opts) {
1626
- const out = { ...note };
1627
- if (opts.includeTranscript && opts.paragraphs) {
1628
- out["transcript"] = { paragraphs: paragraphsToMcp(opts.paragraphs) };
1629
- }
1630
- return `${JSON.stringify(out, null, 2)}
1631
- `;
1632
- }
1633
- function formatText(note, opts) {
1634
- if (!opts.paragraphs || opts.paragraphs.length === 0) {
1635
- return `${note.title}
1636
- ${note.webUrl}
1637
- `;
1638
- }
1639
- const mcp = buildMcpTranscript(note, opts.paragraphs);
1640
- return renderTranscriptText(mcp);
1641
- }
1642
- function escapeYaml(s) {
1643
- if (/[:#\n"']/.test(s)) {
1644
- return JSON.stringify(s);
1645
- }
1646
- return s;
1647
- }
1648
-
1649
- // src/commands/notes/get.ts
1650
- var ALLOWED_INCLUDES = /* @__PURE__ */ new Set(["transcript"]);
1651
- var ParagraphsListSchema = SimpleListResponseSchema(ParagraphSchema);
1652
- var ParagraphsCursorSchema = PageCursorResponseSchema(ParagraphSchema);
1653
- function registerNotesGet(parent) {
1654
- 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(
1655
- "--format <md|json|txt>",
1656
- "Output format (default: md for TTY, json when piped)"
1657
- ).option(
1658
- "--include <items>",
1659
- "Comma-separated extras (v0.2 supports: transcript)",
1660
- ""
1661
- ).option("--force", "Overwrite existing file at --output path").addHelpText("after", `
156
+ `;function iA(e){e.command("search [keyword]").description("Deep keyword search \u2014 returns notes hydrated with their primary documents.").option("--keyword <text>",'Alternative to positional keyword (e.g. --keyword "Q3 Planning")').option("--folder <id>","Restrict hits to a folder and its descendants").option("--since <date>","Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)").option("--until <date>","Exclusive upper bound on createdAt").option("--limit <n>",`Max results per page (default ${oA}, max ${nA})`).option("--cursor <token>","Continue a previous page (reserved \u2014 backend currently always null)").option("--workspace <guid>","Search within one workspace (see `tiro wiki workspaces`). Default: the workspace your API key is bound to, else across all your workspaces").option("--include-untitled","Include placeholder notes. Default: hidden",!1).addHelpText("after",Mt).action(async(A,t,r)=>{let n=r.optsWithGlobals(),i=(A??t.keyword??"").trim();if(!i)throw new f({code:"missing_keyword",message:"search requires a keyword (positional or --keyword).",errorType:"bad_request",suggestion:'tiro notes search "OKR"'},u.Usage);let s={};t.folder&&(s.folderId=t.folder),t.since&&(s.createdAtFrom=I(t.since)),t.until&&(s.createdAtTo=I(t.until));let c={},d=Nt(t.limit);d!==void 0&&(c.size=d),t.cursor&&(c.cursor=t.cursor);let p={keyword:i};Object.keys(s).length>0&&(p.filter=s),Object.keys(c).length>0&&(p.pagination=c);let l=k({...n.hostname!==void 0&&{hostnameOverride:n.hostname}}),w=await N(l,t.workspace);!w&&n.quiet!==!0&&process.stderr.write(`${a("\u26A0","yellow",n)} ${Z}
157
+ `);let b=w?`/v1/external/workspaces/${encodeURIComponent(w)}/notes/search`:"/v1/external/notes/search",h=await l.postJson(b,Wt,p),T=t.includeUntitled===!0?h.notes:h.notes.filter(J);if(y(n)==="json"){for(let Ae of T)C(Ae);h.nextCursor&&C({_cursor:h.nextCursor}),h.degraded===!0&&C({_degraded:!0,_degradedReason:h.degradedReason??null})}else Gt(T,h.nextCursor,n),h.degraded===!0&&n.quiet!==!0&&process.stderr.write(`${a("\u26A0","yellow",n)} search results are partial${h.degradedReason?` (${h.degradedReason})`:""}
158
+ `)})}function Nt(e){if(!e)return;let A=parseInt(e,10);return!Number.isFinite(A)||A<=0?oA:Math.min(A,nA)}function Gt(e,A,t){if(e.length===0){process.stdout.write(`${a("(no matches)","gray",t)}
159
+ `);return}for(let r of e){let n=r.createdAt.slice(0,10);process.stdout.write(`${a(n,"gray",t)} ${a(r.guid,"dim",t)} ${r.title}
160
+ `)}A&&process.stdout.write(`${a(`
161
+ next: --cursor ${A}`,"gray",t)}
162
+ `)}import"commander";import{mkdir as Vt,rename as Ut,stat as jt,writeFile as Qt,access as zt}from"fs/promises";import{dirname as Yt,resolve as Kt,sep as ki}from"path";function Zt(e){if(e.trim()==="")throw sA("output path is empty",e);let A=e.split(/[\\/]/);for(let t of A)if(t==="..")throw sA("path traversal segment '..' is not allowed",e)}function sA(e,A){return new f({code:"unsafe_output_path",message:`Refusing to write to ${JSON.stringify(A)}: ${e}.`,errorType:"bad_request",suggestion:"Use a path without '..' segments, or pass --force if you really mean it."},u.Usage)}async function $(e,A,t={}){t.force||Zt(e);let r=Kt(e);if(await Vt(Yt(r),{recursive:!0}),!t.force&&await Jt(r))throw new f({code:"file_exists",message:`File already exists: ${r}`,errorType:"conflict",suggestion:"Use --force to overwrite, or pick a different --output."},u.Generic);let n=`${r}.tmp.${process.pid}.${Date.now()}`;await Qt(n,A,"utf8"),await Ut(n,r);let i=await jt(r);return{path:r,size:i.size}}async function Jt(e){try{return await zt(e),!0}catch{return!1}}function U(e,A){return{noteGuid:e.guid,title:e.title,participants:e.participants?.map(t=>t.name||t.email||"").filter(t=>typeof t=="string"&&t.length>0)??[],createdAt:e.createdAt,recordingDurationSeconds:e.recordingDurationSeconds,paragraphs:j(A)}}function j(e){return e.map(A=>({timeFrom:A.timeFrom??null,timeTo:A.timeTo??null,segments:$t(A)})).filter(A=>A.segments.length>0)}function $t(e){let A=e.diarizedSegments;if(A&&A.length>0)return A.map(r=>({content:pe(r.content),speaker:{label:r.speaker.label,name:r.speaker.personName?pe(r.speaker.personName):null}})).filter(r=>r.content.length>0);let t=pe(e.transcript?.content??"");return t?[{content:t,speaker:null}]:[]}function de(e){return`${JSON.stringify(e,null,2)}
163
+ `}function _(e,A={}){let t=A.timestamps!==!1,r=t?_t(e):null,n=[];n.push(`# ${e.title}`,""),e.participants.length>0&&n.push(`**Participants**: ${e.participants.join(", ")}`,""),n.push("## Transcript","");for(let i of e.paragraphs){if(t){let s=er(i.timeFrom,r);s&&n.push(`### ${s}`,"")}for(let s of i.segments){let c=s.speaker?.name??s.speaker?.label??"Unknown";n.push(`**${c}**: ${s.content}`)}n.push("")}return`${n.join(`
164
+ `).trimEnd()}
165
+ `}function ee(e){let A=[];for(let t of e.paragraphs)for(let r of t.segments){let n=r.speaker?.name??r.speaker?.label??"Unknown";A.push(`[${n}] ${r.content}`)}return`${A.join(`
166
+ `)}
167
+ `}function _t(e){for(let A of e.paragraphs)if(A.timeFrom)return A.timeFrom;return null}function er(e,A){if(!e||!A)return"";let t=Date.parse(e),r=Date.parse(A);if(!Number.isFinite(t)||!Number.isFinite(r))return"";let n=Math.max(0,Math.floor((t-r)/1e3)),i=Math.floor(n/3600),s=Math.floor(n%3600/60),c=n%60;return i>0?`${V(i)}:${V(s)}:${V(c)}`:`${V(s)}:${V(c)}`}function V(e){return e.toString().padStart(2,"0")}function pe(e){return e.replace(/<[^>]*>/g,"").replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").trim()}function cA(e,A,t={}){switch(A){case"md":return Ar(e,t);case"json":return tr(e,t);case"txt":return rr(e,t)}}function Ar(e,A){let t=["---",`guid: ${aA(e.guid)}`,`title: ${aA(e.title)}`,`createdAt: ${e.createdAt}`,`updatedAt: ${e.updatedAt}`,`sourceType: ${e.sourceType}`,`recordingDurationSeconds: ${e.recordingDurationSeconds}`,`webUrl: ${e.webUrl}`];e.recordingStartAt&&t.push(`recordingStartAt: ${e.recordingStartAt}`),e.recordingEndAt&&t.push(`recordingEndAt: ${e.recordingEndAt}`),t.push("---","");let r=[t.join(`
168
+ `),`# ${e.title}`,""];if(e.participants&&e.participants.length>0){r.push("## Participants","");for(let n of e.participants){let i=n.name??"(no name)",s=n.email?` <${n.email}>`:"";r.push(`- ${i}${s}`)}r.push("")}if(A.includeTranscript&&A.paragraphs&&A.paragraphs.length>0){let n=U(e,A.paragraphs),i=_(n),c=i.startsWith(`# ${e.title}`)?i.slice(i.indexOf(`
169
+ `)+1):i;r.push(c.replace(/^\s*\n+/,""))}return`${r.join(`
170
+ `).trimEnd()}
171
+ `}function tr(e,A){let t={...e};return A.includeTranscript&&A.paragraphs&&(t.transcript={paragraphs:j(A.paragraphs)}),`${JSON.stringify(t,null,2)}
172
+ `}function rr(e,A){if(!A.paragraphs||A.paragraphs.length===0)return`${e.title}
173
+ ${e.webUrl}
174
+ `;let t=U(e,A.paragraphs);return ee(t)}function aA(e){return/[:#\n"']/.test(e)?JSON.stringify(e):e}var or=new Set(["transcript"]),nr=S(F),pA=R(F);function dA(e){e.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("--format <md|json|txt>","Output format (default: md for TTY, json when piped)").option("--include <items>","Comma-separated extras (v0.2 supports: transcript)","").option("--force","Overwrite existing file at --output path").addHelpText("after",`
1662
175
  Examples:
1663
176
  tiro notes get <guid> # markdown to stdout
1664
177
  tiro notes get <guid> --include transcript # add speaker-attributed paragraphs
@@ -1668,142 +181,10 @@ Examples:
1668
181
  Tip for agents: prefer --output <path>. The actual content goes to disk
1669
182
  and stdout collapses to a single metadata line, keeping your context
1670
183
  window light.
1671
- `).action(async (guid, opts, cmd) => {
1672
- const globalOpts = cmd.optsWithGlobals();
1673
- const includes = parseIncludes(opts.include);
1674
- validateIncludes(includes);
1675
- const format = pickFormat(opts.format, opts.output);
1676
- const client = createApiClient({
1677
- ...globalOpts.hostname !== void 0 && { hostnameOverride: globalOpts.hostname }
1678
- });
1679
- const note = await client.getJson(`/v1/external/notes/${guid}`, NoteSchema);
1680
- let paragraphs;
1681
- if (includes.has("transcript") || format === "txt") {
1682
- paragraphs = await fetchAllParagraphs(client, guid);
1683
- }
1684
- const content = formatNote(note, format, {
1685
- includeTranscript: includes.has("transcript"),
1686
- ...paragraphs !== void 0 && { paragraphs }
1687
- });
1688
- if (opts.output) {
1689
- const result = await writeFileAtomic(opts.output, content, {
1690
- ...opts.force === true && { force: true }
1691
- });
1692
- printOutput(
1693
- {
1694
- ok: true,
1695
- data: {
1696
- saved: result.path,
1697
- size: result.size,
1698
- format,
1699
- guid: note.guid,
1700
- title: note.title
1701
- }
1702
- },
1703
- globalOpts
1704
- );
1705
- return;
1706
- }
1707
- const mode = resolveOutputMode(globalOpts);
1708
- if (mode === "json" && format !== "json") {
1709
- printOutput(
1710
- {
1711
- ok: true,
1712
- data: {
1713
- ...note,
1714
- ...paragraphs && { transcript: { paragraphs: paragraphsToMcp(paragraphs) } }
1715
- }
1716
- },
1717
- globalOpts
1718
- );
1719
- } else if (format === "json") {
1720
- process.stdout.write(content);
1721
- } else {
1722
- if (process.stdout.isTTY && format === "txt") {
1723
- process.stdout.write(`${color(`# ${note.title}`, "bold", globalOpts)}
1724
-
1725
- `);
1726
- }
1727
- process.stdout.write(content);
1728
- }
1729
- });
1730
- }
1731
- async function fetchAllParagraphs(client, guid) {
1732
- const first = await client.getJson(
1733
- `/v1/external/notes/${guid}/paragraphs`,
1734
- ParagraphsCursorSchema.or(ParagraphsListSchema)
1735
- );
1736
- const all = [...first.content];
1737
- if ("nextCursor" in first) {
1738
- let cursor = first.nextCursor;
1739
- while (cursor) {
1740
- const next = await client.getJson(
1741
- `/v1/external/notes/${guid}/paragraphs`,
1742
- ParagraphsCursorSchema,
1743
- { cursor }
1744
- );
1745
- all.push(...next.content);
1746
- cursor = next.nextCursor;
1747
- }
1748
- }
1749
- return all;
1750
- }
1751
- function parseIncludes(raw) {
1752
- if (!raw) return /* @__PURE__ */ new Set();
1753
- return new Set(
1754
- raw.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0)
1755
- );
1756
- }
1757
- function validateIncludes(includes) {
1758
- for (const inc of includes) {
1759
- if (!ALLOWED_INCLUDES.has(inc)) {
1760
- throw new TiroError(
1761
- {
1762
- code: "invalid_include",
1763
- message: `Invalid --include "${inc}". v0.2.0 supports: transcript.`,
1764
- errorType: "bad_request",
1765
- suggestion: "Use --include transcript"
1766
- },
1767
- ExitCode.Usage
1768
- );
1769
- }
1770
- }
1771
- }
1772
- function pickFormat(format, output) {
1773
- const allowed = ["md", "json", "txt"];
1774
- if (format) {
1775
- const f = format.toLowerCase();
1776
- if (!allowed.includes(f)) {
1777
- throw new TiroError(
1778
- {
1779
- code: "invalid_format",
1780
- message: `Invalid --format "${format}". Allowed: md, json, txt.`,
1781
- errorType: "bad_request"
1782
- },
1783
- ExitCode.Usage
1784
- );
1785
- }
1786
- return f;
1787
- }
1788
- if (output) {
1789
- if (output.endsWith(".json")) return "json";
1790
- if (output.endsWith(".txt")) return "txt";
1791
- return "md";
1792
- }
1793
- return process.stdout.isTTY ? "md" : "json";
1794
- }
184
+ `).action(async(A,t,r)=>{let n=r.optsWithGlobals(),i=sr(t.include);ar(i);let s=cr(t.format,t.output),c=k({...n.hostname!==void 0&&{hostnameOverride:n.hostname}}),d=await c.getJson(`/v1/external/notes/${A}`,L),p;(i.has("transcript")||s==="txt")&&(p=await ir(c,A));let l=cA(d,s,{includeTranscript:i.has("transcript"),...p!==void 0&&{paragraphs:p}});if(t.output){let b=await $(t.output,l,{...t.force===!0&&{force:!0}});v({ok:!0,data:{saved:b.path,size:b.size,format:s,guid:d.guid,title:d.title}},n);return}y(n)==="json"&&s!=="json"?v({ok:!0,data:{...d,...p&&{transcript:{paragraphs:j(p)}}}},n):(s==="json"||process.stdout.isTTY&&s==="txt"&&process.stdout.write(`${a(`# ${d.title}`,"bold",n)}
1795
185
 
1796
- // src/commands/notes/transcript.ts
1797
- import "commander";
1798
- var ParagraphsListSchema2 = SimpleListResponseSchema(ParagraphSchema);
1799
- var ParagraphsCursorSchema2 = PageCursorResponseSchema(ParagraphSchema);
1800
- function registerNotesTranscript(parent) {
1801
- parent.command("transcript <guid>").description(
1802
- "Get the full transcript of a note as speaker-attributed paragraphs.\nJSON output matches MCP get_note_transcript shape exactly."
1803
- ).option("--output <path>", "Write to file (stdout = single metadata line)").option(
1804
- "--format <md|json|txt>",
1805
- "Output format (default: md if TTY, txt when piped; json mirrors MCP)"
1806
- ).option("--force", "Overwrite existing file at --output path").option("--no-timestamps", "Omit paragraph timestamp headers (md format only)").addHelpText("after", `
186
+ `),process.stdout.write(l))})}async function ir(e,A){let t=await e.getJson(`/v1/external/notes/${A}/paragraphs`,pA.or(nr)),r=[...t.content];if("nextCursor"in t){let n=t.nextCursor;for(;n;){let i=await e.getJson(`/v1/external/notes/${A}/paragraphs`,pA,{cursor:n});r.push(...i.content),n=i.nextCursor}}return r}function sr(e){return e?new Set(e.split(",").map(A=>A.trim().toLowerCase()).filter(A=>A.length>0)):new Set}function ar(e){for(let A of e)if(!or.has(A))throw new f({code:"invalid_include",message:`Invalid --include "${A}". v0.2.0 supports: transcript.`,errorType:"bad_request",suggestion:"Use --include transcript"},u.Usage)}function cr(e,A){let t=["md","json","txt"];if(e){let r=e.toLowerCase();if(!t.includes(r))throw new f({code:"invalid_format",message:`Invalid --format "${e}". Allowed: md, json, txt.`,errorType:"bad_request"},u.Usage);return r}return A?A.endsWith(".json")?"json":A.endsWith(".txt")?"txt":"md":process.stdout.isTTY?"md":"json"}import"commander";var pr=S(F),lA=R(F);function uA(e){e.command("transcript <guid>").description(`Get the full transcript of a note as speaker-attributed paragraphs.
187
+ JSON output matches MCP get_note_transcript shape exactly.`).option("--output <path>","Write to file (stdout = single metadata line)").option("--format <md|json|txt>","Output format (default: md if TTY, txt when piped; json mirrors MCP)").option("--force","Overwrite existing file at --output path").option("--no-timestamps","Omit paragraph timestamp headers (md format only)").addHelpText("after",`
1807
188
  Examples:
1808
189
  tiro notes transcript <guid> # md in TTY, txt in pipe
1809
190
  tiro notes transcript <guid> --format md --output ./t.md
@@ -1813,215 +194,119 @@ Examples:
1813
194
 
1814
195
  The --format json output is byte-for-byte identical to MCP's
1815
196
  get_note_transcript so agents can swap surfaces without changing parsers.
1816
- `).action(async (guid, opts, cmd) => {
1817
- const globalOpts = cmd.optsWithGlobals();
1818
- const format = pickFormat2(opts.format, opts.output, globalOpts);
1819
- const client = createApiClient({
1820
- ...globalOpts.hostname !== void 0 && { hostnameOverride: globalOpts.hostname }
1821
- });
1822
- const note = await client.getJson(`/v1/external/notes/${guid}`, NoteSchema);
1823
- const paragraphs = await fetchAllParagraphs2(client, guid);
1824
- const mcp = buildMcpTranscript(note, paragraphs);
1825
- const content = format === "json" ? renderTranscriptJson(mcp) : format === "md" ? renderTranscriptMarkdown(mcp, { timestamps: opts.timestamps !== false }) : renderTranscriptText(mcp);
1826
- if (opts.output) {
1827
- const result = await writeFileAtomic(opts.output, content, {
1828
- ...opts.force === true && { force: true }
1829
- });
1830
- printOutput(
1831
- {
1832
- ok: true,
1833
- data: {
1834
- saved: result.path,
1835
- size: result.size,
1836
- format,
1837
- guid: note.guid,
1838
- paragraphCount: mcp.paragraphs.length,
1839
- segmentCount: mcp.paragraphs.reduce((sum, p) => sum + p.segments.length, 0)
1840
- }
1841
- },
1842
- globalOpts
1843
- );
1844
- return;
1845
- }
1846
- const mode = resolveOutputMode(globalOpts);
1847
- if (mode === "json" && format !== "json") {
1848
- printOutput({ ok: true, data: mcp }, globalOpts);
1849
- } else {
1850
- process.stdout.write(content);
1851
- }
1852
- });
1853
- }
1854
- async function fetchAllParagraphs2(client, guid) {
1855
- const first = await client.getJson(
1856
- `/v1/external/notes/${guid}/paragraphs`,
1857
- ParagraphsCursorSchema2.or(ParagraphsListSchema2)
1858
- );
1859
- const all = [...first.content];
1860
- if ("nextCursor" in first) {
1861
- let cursor = first.nextCursor;
1862
- while (cursor) {
1863
- const next = await client.getJson(
1864
- `/v1/external/notes/${guid}/paragraphs`,
1865
- ParagraphsCursorSchema2,
1866
- { cursor }
1867
- );
1868
- all.push(...next.content);
1869
- cursor = next.nextCursor;
1870
- }
1871
- }
1872
- return all;
1873
- }
1874
- function pickFormat2(format, output, globalOpts) {
1875
- const allowed = ["md", "json", "txt"];
1876
- if (format) {
1877
- const f = format.toLowerCase();
1878
- if (!allowed.includes(f)) {
1879
- throw new TiroError(
1880
- {
1881
- code: "invalid_format",
1882
- message: `Invalid --format "${format}". Allowed: md, json, txt.`,
1883
- errorType: "bad_request"
1884
- },
1885
- ExitCode.Usage
1886
- );
1887
- }
1888
- return f;
1889
- }
1890
- if (output) {
1891
- if (output.endsWith(".json")) return "json";
1892
- if (output.endsWith(".md")) return "md";
1893
- if (output.endsWith(".txt")) return "txt";
1894
- return "md";
1895
- }
1896
- if (globalOpts.json) return "json";
1897
- if (globalOpts.pretty) return "md";
1898
- return process.stdout.isTTY ? "md" : "txt";
1899
- }
197
+ `).action(async(A,t,r)=>{let n=r.optsWithGlobals(),i=lr(t.format,t.output,n),s=k({...n.hostname!==void 0&&{hostnameOverride:n.hostname}}),c=await s.getJson(`/v1/external/notes/${A}`,L),d=await dr(s,A),p=U(c,d),l=i==="json"?de(p):i==="md"?_(p,{timestamps:t.timestamps!==!1}):ee(p);if(t.output){let b=await $(t.output,l,{...t.force===!0&&{force:!0}});v({ok:!0,data:{saved:b.path,size:b.size,format:i,guid:c.guid,paragraphCount:p.paragraphs.length,segmentCount:p.paragraphs.reduce((h,T)=>h+T.segments.length,0)}},n);return}y(n)==="json"&&i!=="json"?v({ok:!0,data:p},n):process.stdout.write(l)})}async function dr(e,A){let t=await e.getJson(`/v1/external/notes/${A}/paragraphs`,lA.or(pr)),r=[...t.content];if("nextCursor"in t){let n=t.nextCursor;for(;n;){let i=await e.getJson(`/v1/external/notes/${A}/paragraphs`,lA,{cursor:n});r.push(...i.content),n=i.nextCursor}}return r}function lr(e,A,t){let r=["md","json","txt"];if(e){let n=e.toLowerCase();if(!r.includes(n))throw new f({code:"invalid_format",message:`Invalid --format "${e}". Allowed: md, json, txt.`,errorType:"bad_request"},u.Usage);return n}return A?A.endsWith(".json")?"json":A.endsWith(".md")?"md":A.endsWith(".txt")?"txt":"md":t.json?"json":t.pretty||process.stdout.isTTY?"md":"txt"}function mA(e){let A=e.command("notes").description("List, search, and download notes");rA(A),iA(A),dA(A),uA(A)}import"commander";import"commander";import{z as ur}from"zod";var mr=ur.array(Qe),gr=`
198
+ Examples:
199
+ tiro folders list
200
+ tiro folders list --workspace <guid> --json
201
+
202
+ Lists the folders in a workspace (flat). sharingType is PRIVATE / ALL_MEMBER_VIEWER
203
+ / ALL_MEMBER_EDITOR / LIMITED. Pass a folder id to 'tiro notes list --folder <id>'.
204
+ The workspace resolves from --workspace, else your API key's bound workspace; an
205
+ unbound credential must pass --workspace (run 'tiro wiki workspaces' for guids).
206
+ `;function gA(e){e.command("list").description("List folders in a workspace.").option("--workspace <guid>","Workspace to list folders from (see `tiro wiki workspaces`). Default: your API key's bound workspace").addHelpText("after",gr).action(async(A,t)=>{let r=t.optsWithGlobals(),n=k({...r.hostname!==void 0&&{hostnameOverride:r.hostname}}),i=await D(n,A.workspace),s=await n.getJson(`/v1/external/workspaces/${encodeURIComponent(i)}/folders`,mr);if(y(r)==="json")for(let d of s)C(d);else fr(s,r)})}function fr(e,A){if(e.length===0){process.stdout.write(`${a("(no folders)","gray",A)}
207
+ `);return}for(let t of e)process.stdout.write(`${a(t.id,"dim",A)} ${a(t.sharingType,"gray",A)} ${t.title}
208
+ `)}import"commander";var hr=S(ae),wr=`
209
+ Examples:
210
+ tiro folders tree
211
+ tiro folders tree --workspace <guid> --json
212
+
213
+ Returns the folder hierarchy for a workspace. In JSON mode each root folder is one
214
+ NDJSON line with nested children; in pretty mode the tree is indented by depth.
215
+ `;function fA(e){e.command("tree").description("Show the folder hierarchy of a workspace.").option("--workspace <guid>","Workspace to read the tree from (see `tiro wiki workspaces`). Default: your API key's bound workspace").addHelpText("after",wr).action(async(A,t)=>{let r=t.optsWithGlobals(),n=k({...r.hostname!==void 0&&{hostnameOverride:r.hostname}}),i=await D(n,A.workspace),s=await n.getJson(`/v1/external/workspaces/${encodeURIComponent(i)}/folders/tree`,hr);if(y(r)==="json")for(let d of s.content)C(d);else br(s.content,r)})}function br(e,A){if(e.length===0){process.stdout.write(`${a("(no folders)","gray",A)}
216
+ `);return}for(let t of e)hA(t,A)}function hA(e,A){let t=" ".repeat(e.depth),r=e.isAccessible?e.title:a(`${e.title} (no access)`,"gray",A);process.stdout.write(`${t}${a(e.id,"dim",A)} ${r}
217
+ `);for(let n of e.children)hA(n,A)}function wA(e){let A=e.command("folders").description("List workspace folders (flat or as a tree) to scope note queries");gA(A),fA(A)}import"commander";import"commander";var yr=R(ze),bA=1e3,kr=`
218
+ Examples:
219
+ tiro word-memories list
220
+ tiro word-memories list --workspace <guid> --json
221
+
222
+ Lists a workspace's custom word memories (vocabulary that biases transcription).
223
+ The workspace resolves from --workspace, else your API key's bound workspace; an
224
+ unbound credential must pass --workspace (run 'tiro wiki workspaces' for guids).
225
+ `;function yA(e){e.command("list").description("List a workspace's custom word memories.").option("--workspace <guid>","Workspace to list from (see `tiro wiki workspaces`). Default: your API key's bound workspace").option("--limit <n>",`Max results per page (max ${bA})`).option("--cursor <token>","Continue a previous page").addHelpText("after",kr).action(async(A,t)=>{let r=t.optsWithGlobals(),n=k({...r.hostname!==void 0&&{hostnameOverride:r.hostname}}),i=await D(n,A.workspace),s={},c=Cr(A.limit);c!==void 0&&(s.size=c),A.cursor&&(s.cursor=A.cursor);let d=await n.getJson(`/v1/external/workspaces/${encodeURIComponent(i)}/word-memories`,yr,s);if(y(r)==="json"){for(let l of d.content)C(l);d.nextCursor&&C({_cursor:d.nextCursor})}else vr(d.content,d.nextCursor,r)})}function Cr(e){if(!e)return;let A=parseInt(e,10);if(!(!Number.isFinite(A)||A<=0))return Math.min(A,bA)}function vr(e,A,t){if(e.length===0){process.stdout.write(`${a("(no word memories)","gray",t)}
226
+ `);return}for(let r of e)process.stdout.write(`${a(String(r.id),"dim",t)} ${r.entry}
227
+ `);A&&process.stdout.write(`${a(`
228
+ next: --cursor ${A}`,"gray",t)}
229
+ `)}function kA(e){let A=e.command("word-memories").description("List a workspace's custom word memories (transcription vocabulary)");yA(A)}import"commander";import"commander";var vA=100,CA=500,Tr=`
230
+ Examples:
231
+ tiro wiki search "onboarding"
232
+ tiro wiki search "payment gateway" --size 50 --json
233
+ tiro wiki search "billing" --workspace <guid>
234
+
235
+ The workspace defaults to the one implicit in your API key. Pass --workspace
236
+ to target a specific workspace (get guids from 'tiro wiki workspaces').
237
+ Results are ranked wiki pages (pageGuid, name, type, relevance). Pass a
238
+ pageGuid to 'tiro wiki page', 'tiro wiki mentions', or 'tiro wiki graph'.
239
+ `;function TA(e){e.command("search <query>").description("Search the workspace wiki for pages matching a keyword.").option("--size <n>",`Max results (default: backend default, max ${vA})`).option("--workspace <guid>","Target a specific workspace (from `tiro wiki workspaces`); defaults to your default workspace").addHelpText("after",Tr).action(async(A,t,r)=>{let n=r.optsWithGlobals(),i=A.trim();if(!i)throw new f({code:"missing_query",message:"wiki search requires a query.",errorType:"bad_request",suggestion:'tiro wiki search "onboarding"'},u.Usage);let s=k({...n.hostname!==void 0&&{hostnameOverride:n.hostname}}),c=t.workspace??await E(s),p={q:i.length>CA?i.slice(0,CA):i},l=xr(t.size);l!==void 0&&(p.size=l);let w=await s.getJson(`/v1/external/workspaces/${encodeURIComponent(c)}/wiki/search/pages`,Ne,p);if(y(n)==="json")for(let h of w.items)C(h);else Br(w.items,n)})}function xr(e){if(!e)return;let A=parseInt(e,10);if(!(!Number.isFinite(A)||A<=0))return Math.min(A,vA)}function Br(e,A){if(e.length===0){process.stdout.write(`${a("(no matches)","gray",A)}
240
+ `);return}for(let t of e){let r=t.score.toFixed(2);process.stdout.write(`${a(r,"cyan",A)} ${a(t.guid,"dim",A)} ${a(t.pageType,"gray",A)} ${t.canonicalName}
241
+ `)}}import"commander";var Lr=`
242
+ Examples:
243
+ tiro wiki page <pageGuid>
244
+ tiro wiki page <pageGuid> --json
245
+ tiro wiki page <pageGuid> --workspace <guid>
1900
246
 
1901
- // src/commands/notes/index.ts
1902
- function registerNotes(program) {
1903
- const notes = program.command("notes").description("List, search, and download notes");
1904
- registerNotesList(notes);
1905
- registerNotesSearch(notes);
1906
- registerNotesGet(notes);
1907
- registerNotesTranscript(notes);
1908
- }
247
+ Returns the page body (per-user description) plus metadata, mentions,
248
+ aliases, and links. The workspace defaults to the one implicit in your API
249
+ key; pass --workspace to target a specific workspace (from 'tiro wiki workspaces').
250
+ `;function xA(e){e.command("page <pageGuid>").description("Get a single wiki page: body, metadata, mentions, aliases, and links.").option("--workspace <guid>","Target a specific workspace (from `tiro wiki workspaces`); defaults to your default workspace").addHelpText("after",Lr).action(async(A,t,r)=>{let n=r.optsWithGlobals(),i=k({...n.hostname!==void 0&&{hostnameOverride:n.hostname}}),s=t.workspace??await E(i),c=await i.getJson(`/v1/external/workspaces/${encodeURIComponent(s)}/wiki/pages/${encodeURIComponent(A)}`,Ve);y(n)==="json"?v({ok:!0,data:c},n):Rr(c,n)})}function Rr(e,A){let t=process.stdout.write.bind(process.stdout);if(t(`${a(e.canonicalName,"bold",A)} ${a(`(${e.pageType})`,"gray",A)}
251
+ `),t(`${a(e.guid,"dim",A)}
1909
252
 
1910
- // src/commands/mcp/index.ts
1911
- import "commander";
253
+ `),e.description)t(`${e.description}
1912
254
 
1913
- // src/commands/mcp/info.ts
1914
- import "commander";
1915
- function registerMcpInfo(parent) {
1916
- parent.command("info").description("Show Tiro MCP endpoint and connection instructions").action((_opts, cmd) => {
1917
- const globalOpts = cmd.optsWithGlobals();
1918
- printOutput(
1919
- {
1920
- ok: true,
1921
- data: {
1922
- name: HOSTED_MCP_NAME,
1923
- transport: "http",
1924
- url: HOSTED_MCP_URL,
1925
- docs: HOSTED_MCP_DOCS,
1926
- install: {
1927
- claudeCode: `claude mcp add --transport http ${HOSTED_MCP_NAME} ${HOSTED_MCP_URL}`
1928
- }
1929
- }
1930
- },
1931
- globalOpts
1932
- );
1933
- });
1934
- }
255
+ `);else{let r=e.descriptionStatus??"none";t(`${a(`(no description \u2014 status: ${r})`,"gray",A)}
1935
256
 
1936
- // src/commands/mcp/install.ts
1937
- import "commander";
1938
- function registerMcpInstall(parent) {
1939
- parent.command("install").description("Print the one-line command to add Tiro MCP to Claude Code").option(
1940
- "--print",
1941
- "Print the raw `claude mcp add ...` command to stdout (default behavior)"
1942
- ).action((opts, cmd) => {
1943
- const globalOpts = cmd.optsWithGlobals();
1944
- const command = `claude mcp add --transport http ${HOSTED_MCP_NAME} ${HOSTED_MCP_URL}`;
1945
- if (globalOpts.json) {
1946
- printOutput(
1947
- { ok: true, data: { command, name: HOSTED_MCP_NAME, url: HOSTED_MCP_URL } },
1948
- globalOpts
1949
- );
1950
- return;
1951
- }
1952
- if (process.stdout.isTTY && opts.print !== true) {
1953
- process.stderr.write(
1954
- "Run this in your terminal to register Tiro MCP with Claude Code:\n\n"
1955
- );
1956
- }
1957
- process.stdout.write(`${command}
1958
- `);
1959
- });
1960
- }
257
+ `)}t(`${a("mentions","gray",A)} ${e.mentionCountVisible} ${a("aliases","gray",A)} ${e.aliases.length} ${a("links","gray",A)} ${e.links.length}
258
+ `)}import"commander";var BA=200,Er=`
259
+ Examples:
260
+ tiro wiki mentions <pageGuid>
261
+ tiro wiki mentions <pageGuid> --limit 100 --json
262
+ tiro wiki mentions <pageGuid> --workspace <guid>
263
+
264
+ Lists the note paragraphs that reference a wiki page. In JSON mode a trailing
265
+ {_cursor: ...} object is emitted when more pages are available; pass the
266
+ cursor token back via --cursor to fetch the next page. The workspace defaults
267
+ to the one implicit in your API key; pass --workspace to target a specific
268
+ workspace (from 'tiro wiki workspaces').
269
+ `;function LA(e){e.command("mentions <pageGuid>").description("List the note mentions that reference a single wiki page.").option("--limit <n>",`Max mentions per page (max ${BA})`).option("--cursor <token>","Continue from a previous page's cursor token.").option("--workspace <guid>","Target a specific workspace (from `tiro wiki workspaces`); defaults to your default workspace").addHelpText("after",Er).action(async(A,t,r)=>{let n=r.optsWithGlobals(),i=k({...n.hostname!==void 0&&{hostnameOverride:n.hostname}}),s=t.workspace??await E(i),c={},d=Ir(t.limit);d!==void 0&&(c.limit=d),t.cursor&&(c.cursor=t.cursor);let p=await i.getJson(`/v1/external/workspaces/${encodeURIComponent(s)}/wiki/pages/${encodeURIComponent(A)}/mentions`,Ue,c);if(y(n)==="json"){for(let b of p.items)C(b);let w=Or(p.nextCursorCreatedAt,p.nextCursorId);w&&C({_cursor:w})}else Xr(p.items,n)})}function Ir(e){if(!e)return;let A=parseInt(e,10);if(!(!Number.isFinite(A)||A<=0))return Math.min(A,BA)}function Or(e,A){if(e===null||A===null)return null;let t=Date.parse(e);return Number.isNaN(t)?null:`${t}_${A}`}function Xr(e,A){if(e.length===0){process.stdout.write(`${a("(no mentions)","gray",A)}
270
+ `);return}for(let t of e){let r=t.createdAt.slice(0,10);process.stdout.write(`${a(r,"gray",A)} ${a(t.kind,"cyan",A)} ${t.extractedText}
271
+ `)}}import"commander";var le=["seed","expand","around","links"],RA=500,Fr=50,Sr=`
272
+ Modes (--mode, default: around):
273
+ around Neighborhood around <pageGuid> (--radius hops, default 2)
274
+ expand Outward expansion from <pageGuid> (--depth hops, default 1)
275
+ links Links among <pageGuid> + each --page <guid> (repeatable)
276
+ seed Overview seed graph (no <pageGuid> required; --query, --type, --since)
1961
277
 
1962
- // src/commands/mcp/index.ts
1963
- var HOSTED_MCP_URL = "https://mcp.tiro.ooo/mcp";
1964
- var HOSTED_MCP_NAME = "tiro";
1965
- var HOSTED_MCP_DOCS = "https://api-docs.tiro.ooo/mcp";
1966
- function registerMcp(program) {
1967
- const mcp = program.command("mcp").description("Connect Tiro MCP from agent clients (Claude Code, etc.)");
1968
- registerMcpInfo(mcp);
1969
- registerMcpInstall(mcp);
1970
- }
278
+ Examples:
279
+ tiro wiki graph <pageGuid> # around, radius 2
280
+ tiro wiki graph <pageGuid> --mode expand --depth 2
281
+ tiro wiki graph <pageGuid> --mode links --page <g2> --page <g3>
282
+ tiro wiki graph --mode seed --query "billing"
283
+ tiro wiki graph <pageGuid> --workspace <guid>
284
+
285
+ Returns a node+edge slice of the workspace wiki graph. The workspace defaults
286
+ to the one implicit in your API key; pass --workspace to target a specific
287
+ workspace (from 'tiro wiki workspaces').
288
+ `;function EA(e){e.command("graph [pageGuid]").description("Get a node+edge slice of the wiki link graph around a page.").option("--mode <mode>",`Graph mode: ${le.join(" | ")} (default: around)`).option("--depth <n>","expand mode: link-hops to traverse outward (default 1)").option("--radius <n>","around mode: neighborhood radius in hops (default 2)").option("--limit <n>","Max nodes to return (max 200)").option("--page <guid>","links mode: additional page guid (repeatable)",qr,[]).option("--type <type>","seed mode: restrict to a page type (CONCEPT|DECISION|ENTITY)").option("--since <date>","seed mode: only pages updated at/after this date").option("--query <keyword>","seed mode: keyword to seed the overview graph").option("--workspace <guid>","Target a specific workspace (from `tiro wiki workspaces`); defaults to your default workspace").addHelpText("after",Sr).action(async(A,t,r)=>{let n=r.optsWithGlobals(),i=Pr(t.mode);if((i==="expand"||i==="around")&&!A)throw new f({code:"missing_page_guid",message:`--mode ${i} requires a <pageGuid> positional argument.`,errorType:"bad_request",suggestion:`tiro wiki graph <pageGuid> --mode ${i}`},u.Usage);let s=k({...n.hostname!==void 0&&{hostnameOverride:n.hostname}}),c=t.workspace??await E(s),d=i==="links"?void 0:ue(t.limit,200)??Fr,p=await Dr(s,c,i,A??"",t,d),l=Hr(p,d??p.nodes.length);y(n)==="json"?v({ok:!0,data:l},n):Wr(l,n)})}async function Dr(e,A,t,r,n,i){let s=`/v1/external/workspaces/${encodeURIComponent(A)}/wiki/graph`;if(t==="expand")return e.getJson(`${s}/expand`,M,{pageGuid:r,depth:ue(n.depth,200),limit:i});if(t==="around")return e.getJson(`${s}/around`,M,{pageGuid:r,radius:ue(n.radius,200),limit:i});if(t==="links"){let p=[r,...n.page??[]].filter(l=>l&&l.length>0);return e.getJson(`${s}/links`,M,{pageGuids:p.join(",")})}let c=n.query,d=c&&c.length>RA?c.slice(0,RA):c;return e.getJson(`${s}/seed`,M,{type:n.type,since:n.since?I(n.since):void 0,q:d,limit:i})}function Pr(e){if(!e)return"around";let A=e.toLowerCase();if(le.includes(A))return A;throw new f({code:"invalid_mode",message:`Invalid --mode "${e}". Allowed: ${le.join(", ")}.`,errorType:"bad_request",suggestion:"tiro wiki graph <pageGuid> --mode around"},u.Usage)}function ue(e,A){if(!e)return;let t=parseInt(e,10);if(!(!Number.isFinite(t)||t<=0))return Math.min(t,A)}function qr(e,A){return[...A,e]}function Hr(e,A){let t=e.nodes.slice(0,A),r=new Set(t.map(s=>s.guid)),n=e.edges.filter(s=>r.has(s.sourcePageGuid)&&r.has(s.targetPageGuid)),i=e.nodes.length>A||n.length<e.edges.length;return{...e,nodes:t,edges:n,truncated:i}}function Wr(e,A){let t=process.stdout.write.bind(process.stdout);t(`${a("nodes","gray",A)} ${e.nodes.length} ${a("edges","gray",A)} ${e.edges.length}
289
+ `),e.truncated&&t(`${a(`(truncated \u2014 showing first ${e.nodes.length} nodes; narrow with --query / --type / smaller --radius)`,"gray",A)}
290
+ `),t(`
291
+ `);for(let r of e.nodes)t(`${a("\u25CF","cyan",A)} ${a(r.guid,"dim",A)} ${r.canonicalName}
292
+ `);e.edges.length>0&&t(`
293
+ `);for(let r of e.edges){let n=r.isDirectional?"\u2192":"\u2014";t(`${a(r.sourcePageGuid,"dim",A)} ${n} ${a(r.targetPageGuid,"dim",A)} ${a(r.linkType,"gray",A)}
294
+ `)}}import"commander";var Mr=`
295
+ Examples:
296
+ tiro wiki workspaces
297
+ tiro wiki workspaces --json
1971
298
 
1972
- // src/lib/updateCheck.ts
1973
- import updateNotifier from "update-notifier";
1974
- import { readFile } from "fs/promises";
1975
- import { fileURLToPath as fileURLToPath2 } from "url";
1976
- import { dirname as dirname3, resolve as resolve3 } from "path";
1977
- var HERE2 = dirname3(fileURLToPath2(import.meta.url));
1978
- var CANDIDATE_PATHS2 = [
1979
- resolve3(HERE2, "../../package.json"),
1980
- resolve3(HERE2, "../../../package.json")
1981
- ];
1982
- var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
1983
- async function startUpdateCheck() {
1984
- if (process.env["NO_UPDATE_NOTIFIER"] === "1") return null;
1985
- if (process.env["CI"]) return null;
1986
- if (process.stdout.isTTY !== true) return null;
1987
- const pkg = await loadPkg();
1988
- if (!pkg) return null;
1989
- try {
1990
- const factory = updateNotifier;
1991
- return factory({
1992
- pkg,
1993
- updateCheckInterval: ONE_DAY_MS,
1994
- shouldNotifyInNpmScript: false
1995
- });
1996
- } catch {
1997
- return null;
1998
- }
1999
- }
2000
- function emitUpdateBanner(notifier) {
2001
- if (!notifier) return;
2002
- if (!notifier.update) return;
2003
- notifier.notify({
2004
- isGlobal: true,
2005
- defer: false,
2006
- message: "Update available {currentVersion} \u2192 {latestVersion}\nRun npm install -g {packageName} to update\n\nChangelog: https://www.npmjs.com/package/{packageName}?activeTab=versions"
2007
- });
2008
- }
2009
- async function loadPkg() {
2010
- for (const path of CANDIDATE_PATHS2) {
2011
- try {
2012
- const raw = await readFile(path, "utf8");
2013
- const parsed = JSON.parse(raw);
2014
- if (typeof parsed.name === "string" && typeof parsed.version === "string" && parsed.name.length > 0 && parsed.version.length > 0) {
2015
- return { name: parsed.name, version: parsed.version };
2016
- }
2017
- } catch {
2018
- }
2019
- }
2020
- return null;
2021
- }
299
+ Lists all workspaces you are a member of. Use the guid with --workspace on
300
+ any other wiki command to target a non-default workspace.
301
+ `;function IA(e){e.command("workspaces").description("List all workspaces you are a member of (use guid with --workspace).").addHelpText("after",Mr).action(async(A,t)=>{let r=t.optsWithGlobals(),n=k({...r.hostname!==void 0&&{hostnameOverride:r.hostname}}),i=await Ze(n);if(y(r)==="json")for(let c of i)C(c);else Nr(i,r)})}function Nr(e,A){if(e.length===0){process.stdout.write(`${a("(no workspaces)","gray",A)}
302
+ `);return}for(let t of e){let r=t.isWikiEnabled?a("wiki:on","green",A):a("wiki:off","gray",A);process.stdout.write(`${a(t.guid,"dim",A)} ${r} ${t.name}
303
+ `)}}function OA(e){let A=e.command("wiki").description("Search and explore the workspace wiki (pages, mentions, link graph)");TA(A),xA(A),LA(A),EA(A),IA(A)}import"commander";import"commander";function XA(e){e.command("info").description("Show Tiro MCP endpoint and connection instructions").action((A,t)=>{let r=t.optsWithGlobals();v({ok:!0,data:{name:q,transport:"http",url:P,docs:FA,install:{claudeCode:`claude mcp add --transport http ${q} ${P}`}}},r)})}import"commander";function SA(e){e.command("install").description("Print the one-line command to add Tiro MCP to Claude Code").option("--print","Print the raw `claude mcp add ...` command to stdout (default behavior)").action((A,t)=>{let r=t.optsWithGlobals(),n=`claude mcp add --transport http ${q} ${P}`;if(r.json){v({ok:!0,data:{command:n,name:q,url:P}},r);return}process.stdout.isTTY&&A.print!==!0&&process.stderr.write(`Run this in your terminal to register Tiro MCP with Claude Code:
304
+
305
+ `),process.stdout.write(`${n}
306
+ `)})}var P="https://mcp.tiro.ooo/mcp",q="tiro",FA="https://api-docs.tiro.ooo/mcp";function DA(e){let A=e.command("mcp").description("Connect Tiro MCP from agent clients (Claude Code, etc.)");XA(A),SA(A)}import Gr from"update-notifier";import{readFile as Vr}from"fs/promises";import{fileURLToPath as Ur}from"url";import{dirname as jr,resolve as PA}from"path";var qA=jr(Ur(import.meta.url)),Qr=[PA(qA,"../../package.json"),PA(qA,"../../../package.json")],zr=1440*60*1e3;async function HA(){if(process.env.NO_UPDATE_NOTIFIER==="1"||process.env.CI||process.stdout.isTTY!==!0)return null;let e=await Yr();if(!e)return null;try{return Gr({pkg:e,updateCheckInterval:zr,shouldNotifyInNpmScript:!1})}catch{return null}}function WA(e){e&&e.update&&e.notify({isGlobal:!0,defer:!1,message:`Update available {currentVersion} \u2192 {latestVersion}
307
+ Run npm install -g {packageName} to update
2022
308
 
2023
- // src/bin/tiro.ts
2024
- var EXAMPLES = `
309
+ Changelog: https://www.npmjs.com/package/{packageName}?activeTab=versions`})}async function Yr(){for(let e of Qr)try{let A=await Vr(e,"utf8"),t=JSON.parse(A);if(typeof t.name=="string"&&typeof t.version=="string"&&t.name.length>0&&t.version.length>0)return{name:t.name,version:t.version}}catch{}return null}var Zr=`
2025
310
  EXAMPLES
2026
311
  $ tiro auth login
2027
312
  $ tiro notes list --since 7d
@@ -2029,6 +314,9 @@ EXAMPLES
2029
314
  $ tiro notes get <guid> --output ./meeting.md --include transcript
2030
315
  $ tiro notes transcript <guid> --format md --output ./transcript.md
2031
316
  $ tiro notes transcript <guid> --format md --no-timestamps --output ./clean.md
317
+ $ tiro folders list --workspace <guid>
318
+ $ tiro wiki search "onboarding" --json
319
+ $ tiro wiki graph <pageGuid> --mode around --radius 2
2032
320
  $ tiro mcp install # one-line setup for Claude Code
2033
321
 
2034
322
  ENVIRONMENT
@@ -2039,59 +327,9 @@ ENVIRONMENT
2039
327
 
2040
328
  DOCS
2041
329
  https://api-docs.tiro.ooo/cli
2042
- `;
2043
- function buildProgram() {
2044
- const program = new Command13();
2045
- program.name("tiro").description("Tiro AI notes & transcripts \u2014 agent-first command line").version(VERSION, "-v, --version", "Print version").option("--hostname <url>", "API base URL (default: https://api.tiro.ooo)").option("--json", "Force JSON output").option("--pretty", "Force pretty (human) output").option("--quiet", "Suppress non-error output").option("--verbose", "Verbose logging to stderr").option("--no-color", "Disable ANSI colors").addHelpText("after", EXAMPLES);
2046
- program.showHelpAfterError("(run `tiro --help` for available commands)");
2047
- registerAuth(program);
2048
- registerNotes(program);
2049
- registerMcp(program);
2050
- return program;
2051
- }
2052
- async function main() {
2053
- const program = buildProgram();
2054
- const notifier = await startUpdateCheck();
2055
- try {
2056
- await program.parseAsync(process.argv);
2057
- emitUpdateBanner(notifier);
2058
- } catch (err) {
2059
- handleError(err, program);
2060
- }
2061
- }
2062
- function handleError(err, program) {
2063
- const opts = program.opts();
2064
- if (err instanceof TiroError) {
2065
- if (opts.json) {
2066
- printError(err.toJSON());
2067
- } else if (!opts.quiet) {
2068
- process.stderr.write(`${color("\u2717", "red", opts)} ${err.message}
2069
- `);
2070
- if (err.suggestion) {
2071
- process.stderr.write(` ${color("\u2192", "gray", opts)} ${err.suggestion}
2072
- `);
2073
- }
2074
- }
2075
- process.exit(err.exitCode);
2076
- }
2077
- if (err instanceof Error) {
2078
- if (opts.json) {
2079
- printError({
2080
- ok: false,
2081
- error: { code: "internal_error", message: err.message, errorType: "internal_error" }
2082
- });
2083
- } else if (!opts.quiet) {
2084
- process.stderr.write(`${color("\u2717", "red", opts)} ${err.message}
2085
- `);
2086
- }
2087
- process.exit(ExitCode.Generic);
2088
- }
2089
- process.stderr.write(`Unknown error: ${String(err)}
2090
- `);
2091
- process.exit(ExitCode.Generic);
2092
- }
2093
- main().catch((err) => {
2094
- process.stderr.write(`Fatal: ${String(err)}
2095
- `);
2096
- process.exit(ExitCode.Generic);
2097
- });
330
+ `;function Jr(){let e=new Kr;return e.name("tiro").description("Tiro AI notes & transcripts \u2014 agent-first command line").version(fe,"-v, --version","Print version").option("--hostname <url>","API base URL (default: https://api.tiro.ooo)").option("--json","Force JSON output").option("--pretty","Force pretty (human) output").option("--quiet","Suppress non-error output").option("--verbose","Verbose logging to stderr").option("--no-color","Disable ANSI colors").addHelpText("after",Zr),e.showHelpAfterError("(run `tiro --help` for available commands)"),_e(e),mA(e),wA(e),kA(e),OA(e),DA(e),e}async function $r(){let e=Jr(),A=await HA();try{await e.parseAsync(process.argv),WA(A)}catch(t){_r(t,e)}}function _r(e,A){let t=A.opts();e instanceof f&&(t.json?te(e.toJSON()):t.quiet||(process.stderr.write(`${a("\u2717","red",t)} ${e.message}
331
+ `),e.suggestion&&process.stderr.write(` ${a("\u2192","gray",t)} ${e.suggestion}
332
+ `)),process.exit(e.exitCode)),e instanceof Error&&(t.json?te({ok:!1,error:{code:"internal_error",message:e.message,errorType:"internal_error"}}):t.quiet||process.stderr.write(`${a("\u2717","red",t)} ${e.message}
333
+ `),process.exit(u.Generic)),process.stderr.write(`Unknown error: ${String(e)}
334
+ `),process.exit(u.Generic)}$r().catch(e=>{process.stderr.write(`Fatal: ${String(e)}
335
+ `),process.exit(u.Generic)});