@ora-ai/cli 0.1.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 (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/dist/auth-commands.d.ts +39 -0
  4. package/dist/auth-commands.d.ts.map +1 -0
  5. package/dist/auth-commands.js +116 -0
  6. package/dist/auth-commands.js.map +1 -0
  7. package/dist/core/auth.d.ts +41 -0
  8. package/dist/core/auth.d.ts.map +1 -0
  9. package/dist/core/auth.js +110 -0
  10. package/dist/core/auth.js.map +1 -0
  11. package/dist/core/config.d.ts +26 -0
  12. package/dist/core/config.d.ts.map +1 -0
  13. package/dist/core/config.js +51 -0
  14. package/dist/core/config.js.map +1 -0
  15. package/dist/core/http.d.ts +46 -0
  16. package/dist/core/http.d.ts.map +1 -0
  17. package/dist/core/http.js +82 -0
  18. package/dist/core/http.js.map +1 -0
  19. package/dist/core/login.d.ts +14 -0
  20. package/dist/core/login.d.ts.map +1 -0
  21. package/dist/core/login.js +70 -0
  22. package/dist/core/login.js.map +1 -0
  23. package/dist/core/output.d.ts +18 -0
  24. package/dist/core/output.d.ts.map +1 -0
  25. package/dist/core/output.js +94 -0
  26. package/dist/core/output.js.map +1 -0
  27. package/dist/core/run-operation.d.ts +57 -0
  28. package/dist/core/run-operation.d.ts.map +1 -0
  29. package/dist/core/run-operation.js +119 -0
  30. package/dist/core/run-operation.js.map +1 -0
  31. package/dist/core/sse.d.ts +13 -0
  32. package/dist/core/sse.d.ts.map +1 -0
  33. package/dist/core/sse.js +63 -0
  34. package/dist/core/sse.js.map +1 -0
  35. package/dist/generated/operations.d.ts +47 -0
  36. package/dist/generated/operations.d.ts.map +1 -0
  37. package/dist/generated/operations.js +2050 -0
  38. package/dist/generated/operations.js.map +1 -0
  39. package/dist/generated/types.d.ts +1039 -0
  40. package/dist/generated/types.d.ts.map +1 -0
  41. package/dist/generated/types.js +5 -0
  42. package/dist/generated/types.js.map +1 -0
  43. package/dist/index.d.ts +7 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +17 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/interactive/derive-prompts.d.ts +44 -0
  48. package/dist/interactive/derive-prompts.d.ts.map +1 -0
  49. package/dist/interactive/derive-prompts.js +58 -0
  50. package/dist/interactive/derive-prompts.js.map +1 -0
  51. package/dist/interactive/inquirer-prompter.d.ts +11 -0
  52. package/dist/interactive/inquirer-prompter.d.ts.map +1 -0
  53. package/dist/interactive/inquirer-prompter.js +64 -0
  54. package/dist/interactive/inquirer-prompter.js.map +1 -0
  55. package/dist/interactive/menu.d.ts +25 -0
  56. package/dist/interactive/menu.d.ts.map +1 -0
  57. package/dist/interactive/menu.js +57 -0
  58. package/dist/interactive/menu.js.map +1 -0
  59. package/dist/interactive/prompter.d.ts +25 -0
  60. package/dist/interactive/prompter.d.ts.map +1 -0
  61. package/dist/interactive/prompter.js +14 -0
  62. package/dist/interactive/prompter.js.map +1 -0
  63. package/dist/interactive/session.d.ts +19 -0
  64. package/dist/interactive/session.d.ts.map +1 -0
  65. package/dist/interactive/session.js +204 -0
  66. package/dist/interactive/session.js.map +1 -0
  67. package/dist/program.d.ts +81 -0
  68. package/dist/program.d.ts.map +1 -0
  69. package/dist/program.js +178 -0
  70. package/dist/program.js.map +1 -0
  71. package/dist/render/ansi.d.ts +13 -0
  72. package/dist/render/ansi.d.ts.map +1 -0
  73. package/dist/render/ansi.js +34 -0
  74. package/dist/render/ansi.js.map +1 -0
  75. package/dist/render/banner.d.ts +7 -0
  76. package/dist/render/banner.d.ts.map +1 -0
  77. package/dist/render/banner.js +18 -0
  78. package/dist/render/banner.js.map +1 -0
  79. package/dist/render/glyphs.d.ts +39 -0
  80. package/dist/render/glyphs.d.ts.map +1 -0
  81. package/dist/render/glyphs.js +83 -0
  82. package/dist/render/glyphs.js.map +1 -0
  83. package/dist/render/index.d.ts +13 -0
  84. package/dist/render/index.d.ts.map +1 -0
  85. package/dist/render/index.js +24 -0
  86. package/dist/render/index.js.map +1 -0
  87. package/dist/render/insight-lines.d.ts +8 -0
  88. package/dist/render/insight-lines.d.ts.map +1 -0
  89. package/dist/render/insight-lines.js +62 -0
  90. package/dist/render/insight-lines.js.map +1 -0
  91. package/dist/render/insight.d.ts +9 -0
  92. package/dist/render/insight.d.ts.map +1 -0
  93. package/dist/render/insight.js +68 -0
  94. package/dist/render/insight.js.map +1 -0
  95. package/dist/render/journey-graph.d.ts +73 -0
  96. package/dist/render/journey-graph.d.ts.map +1 -0
  97. package/dist/render/journey-graph.js +250 -0
  98. package/dist/render/journey-graph.js.map +1 -0
  99. package/dist/render/journey.d.ts +14 -0
  100. package/dist/render/journey.d.ts.map +1 -0
  101. package/dist/render/journey.js +67 -0
  102. package/dist/render/journey.js.map +1 -0
  103. package/dist/render/live-panel.d.ts +34 -0
  104. package/dist/render/live-panel.d.ts.map +1 -0
  105. package/dist/render/live-panel.js +84 -0
  106. package/dist/render/live-panel.js.map +1 -0
  107. package/dist/render/mode.d.ts +19 -0
  108. package/dist/render/mode.d.ts.map +1 -0
  109. package/dist/render/mode.js +23 -0
  110. package/dist/render/mode.js.map +1 -0
  111. package/dist/render/registry.d.ts +17 -0
  112. package/dist/render/registry.d.ts.map +1 -0
  113. package/dist/render/registry.js +34 -0
  114. package/dist/render/registry.js.map +1 -0
  115. package/dist/render/run-list.d.ts +11 -0
  116. package/dist/render/run-list.d.ts.map +1 -0
  117. package/dist/render/run-list.js +53 -0
  118. package/dist/render/run-list.js.map +1 -0
  119. package/dist/render/spinner.d.ts +14 -0
  120. package/dist/render/spinner.d.ts.map +1 -0
  121. package/dist/render/spinner.js +37 -0
  122. package/dist/render/spinner.js.map +1 -0
  123. package/dist/render/table.d.ts +20 -0
  124. package/dist/render/table.d.ts.map +1 -0
  125. package/dist/render/table.js +29 -0
  126. package/dist/render/table.js.map +1 -0
  127. package/dist/render/trajectory.d.ts +19 -0
  128. package/dist/render/trajectory.d.ts.map +1 -0
  129. package/dist/render/trajectory.js +75 -0
  130. package/dist/render/trajectory.js.map +1 -0
  131. package/dist/render/tunnel.d.ts +10 -0
  132. package/dist/render/tunnel.d.ts.map +1 -0
  133. package/dist/render/tunnel.js +108 -0
  134. package/dist/render/tunnel.js.map +1 -0
  135. package/dist/render/usage.d.ts +29 -0
  136. package/dist/render/usage.d.ts.map +1 -0
  137. package/dist/render/usage.js +83 -0
  138. package/dist/render/usage.js.map +1 -0
  139. package/dist/tunnel-command.d.ts +15 -0
  140. package/dist/tunnel-command.d.ts.map +1 -0
  141. package/dist/tunnel-command.js +267 -0
  142. package/dist/tunnel-command.js.map +1 -0
  143. package/dist/watch.d.ts +53 -0
  144. package/dist/watch.d.ts.map +1 -0
  145. package/dist/watch.js +305 -0
  146. package/dist/watch.js.map +1 -0
  147. package/package.json +36 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Rich renderer for a run's trajectory artifact (`GET .../runs/:id/trajectory`
3
+ * — see `@ora/trace-normalize`'s `TrajectoryData`). Draws the JOURNEY GRAPH —
4
+ * the same picture the ora product shows: the intent root, every tool action
5
+ * as a rounded box, attribution-driven edges, reasoning pinned as (…) notes
6
+ * above the action it produced — followed by the step summary. Ported from
7
+ * the standalone eralabs-ai/ora-cli renderer (render/journey-graph.ts).
8
+ */
9
+ import { GLYPHS, accent } from "./glyphs.js";
10
+ import { buildJourneyTree, drawJourneyTree, journeySummary, } from "./journey-graph.js";
11
+ /**
12
+ * `steps` + `action_sequence` + `well_known_probes` together are unique to
13
+ * the trajectory artifact among this CLI's captured shapes: the insight
14
+ * artifact has no step array at all, and journey/run-list nest their arrays
15
+ * under `data`/`results` rather than a bare top-level `steps`. Pinned on the
16
+ * live-captured fixture (__fixtures__/trajectory.json).
17
+ *
18
+ * Every element must also be a non-null object (mirrors run-list's `isRunRow`
19
+ * check on its rows) — a `null`/primitive step would otherwise pass the
20
+ * array check here and then throw in `glyphForStep` (`step.type` on null).
21
+ * Rejecting it here sends the payload to the plain fallback instead.
22
+ */
23
+ function isTrajectory(data) {
24
+ if (typeof data !== "object" || data === null)
25
+ return false;
26
+ const d = data;
27
+ return (Array.isArray(d.steps) &&
28
+ d.steps.every((s) => typeof s === "object" && s !== null) &&
29
+ typeof d.action_sequence === "string" &&
30
+ Array.isArray(d.well_known_probes));
31
+ }
32
+ /**
33
+ * A tool_call always gets the tool glyph. Of the text sub-kinds, `output` (the
34
+ * agent's final answer) reads as `ok` — everything else (`reasoning`,
35
+ * `prompt`, generic `text`) reads as `thought`, since they're all
36
+ * intermediate agent thinking/instruction rather than a completed result.
37
+ */
38
+ function glyphForStep(step) {
39
+ if (step.type === "tool_call")
40
+ return GLYPHS.tool;
41
+ if (step.kind === "output")
42
+ return GLYPHS.ok;
43
+ return GLYPHS.thought;
44
+ }
45
+ function labelForStep(step) {
46
+ if (step.type === "tool_call")
47
+ return typeof step.tool === "string" ? step.tool : "tool";
48
+ return typeof step.kind === "string" ? step.kind : "text";
49
+ }
50
+ /** Absent `elapsed_ms` (a step with no wall-clock timestamp) renders no duration at all — never "0ms" or "NaNms". */
51
+ function durationSuffix(step) {
52
+ return typeof step.elapsed_ms === "number" ? ` (${Math.round(step.elapsed_ms)}ms)` : "";
53
+ }
54
+ export function renderStep(step) {
55
+ return `${glyphForStep(step)} ${labelForStep(step)}${durationSuffix(step)}`;
56
+ }
57
+ /** Root label: the run's first target when the artifact carries one. */
58
+ function rootLabel(d) {
59
+ return typeof d.first_target === "string" && d.first_target ? d.first_target : "journey";
60
+ }
61
+ function render(data) {
62
+ const d = data;
63
+ const header = accent.bold(`Trajectory — ${d.steps.length} step${d.steps.length === 1 ? "" : "s"} (${d.action_sequence})`);
64
+ const steps = d.steps;
65
+ const tree = buildJourneyTree(steps, rootLabel(d), true);
66
+ return [header, journeySummary(steps), "", ...drawJourneyTree(tree)].join("\n");
67
+ }
68
+ // The flat step line remains for very small terminals / debugging via the
69
+ // exported helpers below (renderStep is exercised directly by tests).
70
+ export const trajectoryRenderer = {
71
+ name: "trajectory",
72
+ canRender: isTrajectory,
73
+ render,
74
+ };
75
+ //# sourceMappingURL=trajectory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trajectory.js","sourceRoot":"","sources":["../../src/render/trajectory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Rich renderers for the tunnels surface: the LIST (`GET /tunnels/v1`) as a
3
+ * status-glyph table, a single tunnel (get/create/revoke responses) as a
4
+ * card. Same Registry-of-Strategies contract as run-list.ts; shared column
5
+ * machinery from ./table.js.
6
+ */
7
+ import type { Renderer } from "./registry.js";
8
+ export declare const tunnelListRenderer: Renderer;
9
+ export declare const tunnelCardRenderer: Renderer;
10
+ //# sourceMappingURL=tunnel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/render/tunnel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAyG9C,eAAO,MAAM,kBAAkB,EAAE,QAIhC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,QAIhC,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Rich renderers for the tunnels surface: the LIST (`GET /tunnels/v1`) as a
3
+ * status-glyph table, a single tunnel (get/create/revoke responses) as a
4
+ * card. Same Registry-of-Strategies contract as run-list.ts; shared column
5
+ * machinery from ./table.js.
6
+ */
7
+ import chalk from "chalk";
8
+ import { cell, columnWidths, padLine, rowCountLabel } from "./table.js";
9
+ const STATUS_GLYPH = {
10
+ connected: chalk.green("●"),
11
+ pending: chalk.dim("○"),
12
+ disconnected: chalk.yellow("◌"),
13
+ revoked: chalk.red("✖")
14
+ };
15
+ const ACCESS_LABEL = {
16
+ private: chalk.dim("private"),
17
+ protected: chalk.yellow("protected"),
18
+ public: chalk.cyan("public")
19
+ };
20
+ function isTunnel(row) {
21
+ if (typeof row !== "object" || row === null)
22
+ return false;
23
+ const r = row;
24
+ return (typeof r.id === "string" &&
25
+ typeof r.name === "string" &&
26
+ typeof r.status === "string" &&
27
+ typeof r.access === "string" &&
28
+ "publicUrl" in r);
29
+ }
30
+ /** `{ tunnels: [...] }` with tunnel-shaped rows — unique to tunnels.list. */
31
+ function isTunnelList(data) {
32
+ if (typeof data !== "object" || data === null)
33
+ return false;
34
+ const d = data;
35
+ return Array.isArray(d.tunnels) && d.tunnels.every(isTunnel);
36
+ }
37
+ function ago(iso) {
38
+ if (!iso)
39
+ return "—";
40
+ const ms = Date.now() - Date.parse(iso);
41
+ if (!Number.isFinite(ms) || ms < 0)
42
+ return "—";
43
+ const m = Math.floor(ms / 60_000);
44
+ if (m < 1)
45
+ return "just now";
46
+ if (m < 60)
47
+ return `${m}m ago`;
48
+ const h = Math.floor(m / 60);
49
+ return h < 48 ? `${h}h ago` : `${Math.floor(h / 24)}d ago`;
50
+ }
51
+ function renderList(data) {
52
+ const rows = data.tunnels;
53
+ if (rows.length === 0) {
54
+ return chalk.dim("no tunnels — start one with `ora tunnel <port>`");
55
+ }
56
+ // Same discipline as run-list.ts: ONLY the leading glyph carries color (a
57
+ // single cell whose ANSI slack barely shifts column 1); every other cell is
58
+ // plain text so padEnd alignment stays exact.
59
+ const header = ["", "name", "id", "access", "url", "last seen"];
60
+ const body = rows.map((t) => [
61
+ STATUS_GLYPH[t.status] ?? "?",
62
+ cell(t.name),
63
+ `${t.id.slice(0, 8)}…`,
64
+ t.access,
65
+ t.publicUrl ? cell(t.publicUrl.replace(/^https?:\/\//, "")) : "—",
66
+ ago(t.lastSeenAt)
67
+ ]);
68
+ const widths = columnWidths(header, body);
69
+ return [
70
+ chalk.bold(padLine(header, widths)),
71
+ ...body.map((cells) => padLine(cells, widths)),
72
+ chalk.dim(rowCountLabel(rows.length)),
73
+ chalk.dim("start one: `ora tunnel <port>` · remove: `ora tunnels delete <id>`")
74
+ ].join("\n");
75
+ }
76
+ function renderCard(data) {
77
+ const t = data;
78
+ const line = (label, value) => ` ${chalk.dim(label.padEnd(10))} ${value}`;
79
+ const out = [
80
+ "",
81
+ ` ${STATUS_GLYPH[t.status] ?? "?"} ${chalk.bold(t.name)} ${chalk.dim(`(${t.status})`)}`,
82
+ line("id", t.id),
83
+ line("access", ACCESS_LABEL[t.access] ?? t.access)
84
+ ];
85
+ if (t.publicUrl)
86
+ out.push(line("url", chalk.cyan.underline(t.publicUrl)));
87
+ if (t.accessToken) {
88
+ out.push(line("secret", `${chalk.yellow(t.accessToken)} ${chalk.dim("(shown ONCE)")}`));
89
+ }
90
+ if (t.lastSeenAt)
91
+ out.push(line("last seen", ago(t.lastSeenAt)));
92
+ if (t.status !== "connected") {
93
+ out.push(line("", chalk.dim("hold it live: `ora tunnel <port> --id " + t.id + "`")));
94
+ }
95
+ out.push("");
96
+ return out.join("\n");
97
+ }
98
+ export const tunnelListRenderer = {
99
+ name: "tunnel-list",
100
+ canRender: isTunnelList,
101
+ render: renderList
102
+ };
103
+ export const tunnelCardRenderer = {
104
+ name: "tunnel-card",
105
+ canRender: isTunnel,
106
+ render: renderCard
107
+ };
108
+ //# sourceMappingURL=tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../src/render/tunnel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Token/cost/cache metadata chips — the "how much did this journey spend"
3
+ * line under a journey's agents and a run's outcome. ONE normalizer accepts
4
+ * BOTH spellings the platform serves (journey agents are camelCase; run-list
5
+ * rows are snake_case), so every renderer reads the same shape.
6
+ */
7
+ export interface UsageLike {
8
+ inputTokens?: number | null;
9
+ outputTokens?: number | null;
10
+ totalTokens?: number | null;
11
+ cacheReadTokens?: number | null;
12
+ cacheCreationTokens?: number | null;
13
+ costUsd?: number | null;
14
+ numTurns?: number | null;
15
+ durationMs?: number | null;
16
+ }
17
+ /** Read usage off any object, accepting camelCase and snake_case spellings. */
18
+ export declare function readUsage(raw: unknown): UsageLike;
19
+ export declare function formatTokens(n: number): string;
20
+ export declare function formatCost(usd: number): string;
21
+ /**
22
+ * The chips line: `in 12.3k · out 4.1k · cache 197.9k r / 135.8k w · $0.042 ·
23
+ * 7 turns · 33.3s`. Only fields that exist appear — a null never renders as a
24
+ * dash, it just isn't spent yet.
25
+ */
26
+ export declare function usageChips(usage: UsageLike): string;
27
+ /** Sum every numeric field across a set of usages (a journey's agents). */
28
+ export declare function sumUsage(usages: UsageLike[]): UsageLike;
29
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/render/usage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,SAAS;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAKD,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAajD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAgBnD;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAevD"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Token/cost/cache metadata chips — the "how much did this journey spend"
3
+ * line under a journey's agents and a run's outcome. ONE normalizer accepts
4
+ * BOTH spellings the platform serves (journey agents are camelCase; run-list
5
+ * rows are snake_case), so every renderer reads the same shape.
6
+ */
7
+ import chalk from "chalk";
8
+ const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined;
9
+ /** Read usage off any object, accepting camelCase and snake_case spellings. */
10
+ export function readUsage(raw) {
11
+ if (typeof raw !== "object" || raw === null)
12
+ return {};
13
+ const r = raw;
14
+ return {
15
+ inputTokens: num(r.inputTokens) ?? num(r.input_tokens),
16
+ outputTokens: num(r.outputTokens) ?? num(r.output_tokens),
17
+ totalTokens: num(r.totalTokens) ?? num(r.total_tokens),
18
+ cacheReadTokens: num(r.cacheReadTokens) ?? num(r.cache_read_tokens),
19
+ cacheCreationTokens: num(r.cacheCreationTokens) ?? num(r.cache_creation_tokens),
20
+ costUsd: num(r.costUsd) ?? num(r.cost_usd),
21
+ numTurns: num(r.numTurns) ?? num(r.num_turns),
22
+ durationMs: num(r.durationMs) ?? num(r.duration_ms),
23
+ };
24
+ }
25
+ export function formatTokens(n) {
26
+ if (n >= 1_000_000)
27
+ return `${(n / 1_000_000).toFixed(1)}M`;
28
+ if (n >= 1000)
29
+ return `${(n / 1000).toFixed(1)}k`;
30
+ return String(n);
31
+ }
32
+ export function formatCost(usd) {
33
+ if (usd < 0.01)
34
+ return `$${usd.toFixed(4)}`;
35
+ if (usd < 1)
36
+ return `$${usd.toFixed(3)}`;
37
+ return `$${usd.toFixed(2)}`;
38
+ }
39
+ /**
40
+ * The chips line: `in 12.3k · out 4.1k · cache 197.9k r / 135.8k w · $0.042 ·
41
+ * 7 turns · 33.3s`. Only fields that exist appear — a null never renders as a
42
+ * dash, it just isn't spent yet.
43
+ */
44
+ export function usageChips(usage) {
45
+ const chips = [];
46
+ if (usage.inputTokens != null)
47
+ chips.push(`in ${formatTokens(usage.inputTokens)}`);
48
+ if (usage.outputTokens != null)
49
+ chips.push(`out ${formatTokens(usage.outputTokens)}`);
50
+ if (usage.totalTokens != null && usage.inputTokens == null && usage.outputTokens == null)
51
+ chips.push(`${formatTokens(usage.totalTokens)} tokens`);
52
+ if (usage.cacheReadTokens != null || usage.cacheCreationTokens != null) {
53
+ const read = usage.cacheReadTokens != null ? `${formatTokens(usage.cacheReadTokens)} r` : "";
54
+ const write = usage.cacheCreationTokens != null ? `${formatTokens(usage.cacheCreationTokens)} w` : "";
55
+ chips.push(`cache ${[read, write].filter(Boolean).join(" / ")}`);
56
+ }
57
+ if (usage.costUsd != null)
58
+ chips.push(formatCost(usage.costUsd));
59
+ if (usage.numTurns != null)
60
+ chips.push(`${usage.numTurns} turns`);
61
+ if (usage.durationMs != null)
62
+ chips.push(`${(usage.durationMs / 1000).toFixed(1)}s`);
63
+ return chips.join(chalk.dim(" · "));
64
+ }
65
+ /** Sum every numeric field across a set of usages (a journey's agents). */
66
+ export function sumUsage(usages) {
67
+ const total = {};
68
+ const add = (key) => {
69
+ const values = usages.map((u) => u[key]).filter((v) => v != null);
70
+ if (values.length)
71
+ total[key] = values.reduce((a, b) => a + b, 0);
72
+ };
73
+ add("inputTokens");
74
+ add("outputTokens");
75
+ add("totalTokens");
76
+ add("cacheReadTokens");
77
+ add("cacheCreationTokens");
78
+ add("costUsd");
79
+ add("numTurns");
80
+ add("durationMs");
81
+ return total;
82
+ }
83
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/render/usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Command } from "commander";
2
+ import type { ResolvedDeps } from "./program.js";
3
+ /**
4
+ * `ora tunnel <port>` — the ngrok-style one-shot: resolve (create or reuse)
5
+ * a tunnel, dial the `/connect` WebSocket, and forward every proxied request
6
+ * to `127.0.0.1:<port>` until Ctrl-C. This is the HAND-WRITTEN companion to
7
+ * the generated `ora tunnels …` CRUD (create/list/get/revoke manage the
8
+ * ledger; THIS command is the live data plane).
9
+ *
10
+ * Reuse-by-name: running `ora tunnel 3000` twice reuses the `dev-3000` row
11
+ * (create → 409 name-conflict → list lookup), so the id — and therefore the
12
+ * public hostname — stays stable across restarts.
13
+ */
14
+ export declare function attachTunnelCommand(program: Command, deps: ResolvedDeps): void;
15
+ //# sourceMappingURL=tunnel-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-command.d.ts","sourceRoot":"","sources":["../src/tunnel-command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA2BjD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAiC9E"}
@@ -0,0 +1,267 @@
1
+ import http from "node:http";
2
+ import chalk from "chalk";
3
+ import { WebSocket } from "ws";
4
+ import { TunnelConnector, V1Codec } from "@ora-ai/tunnel-protocol";
5
+ import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { credentials } from "./core/run-operation.js";
8
+ import { renderError } from "./core/output.js";
9
+ /**
10
+ * Protected-mode secrets are shown ONCE by the API (only sha256 stored), so
11
+ * the CLI remembers them per tunnel-id in the config dir — the ngrok
12
+ * authtoken model: your own machine keeps your own credential, and
13
+ * `ora tunnel <port>` keeps "just working" across restarts. A tunnel whose
14
+ * secret was lost (created elsewhere) is deleted + recreated instead — a new
15
+ * URL, exactly like ngrok restarting.
16
+ */
17
+ const SECRETS_FILE = "tunnel-secrets.json";
18
+ function readSecrets(dir) {
19
+ try {
20
+ return JSON.parse(readFileSync(join(dir, SECRETS_FILE), "utf8"));
21
+ }
22
+ catch {
23
+ return {};
24
+ }
25
+ }
26
+ function rememberSecret(dir, tunnelId, secret) {
27
+ const all = readSecrets(dir);
28
+ all[tunnelId] = secret;
29
+ mkdirSync(dir, { recursive: true });
30
+ writeFileSync(join(dir, SECRETS_FILE), JSON.stringify(all, null, 2), { mode: 0o600 });
31
+ }
32
+ /**
33
+ * `ora tunnel <port>` — the ngrok-style one-shot: resolve (create or reuse)
34
+ * a tunnel, dial the `/connect` WebSocket, and forward every proxied request
35
+ * to `127.0.0.1:<port>` until Ctrl-C. This is the HAND-WRITTEN companion to
36
+ * the generated `ora tunnels …` CRUD (create/list/get/revoke manage the
37
+ * ledger; THIS command is the live data plane).
38
+ *
39
+ * Reuse-by-name: running `ora tunnel 3000` twice reuses the `dev-3000` row
40
+ * (create → 409 name-conflict → list lookup), so the id — and therefore the
41
+ * public hostname — stays stable across restarts.
42
+ */
43
+ export function attachTunnelCommand(program, deps) {
44
+ program
45
+ .command("tunnel")
46
+ .description("Expose a local port to ora (hold a live dev tunnel until Ctrl-C)")
47
+ .argument("<port>", "local port to forward to (e.g. 3000)")
48
+ .option("--name <name>", "tunnel name (default: dev-<port>; reused across runs)")
49
+ .option("--access <mode>", "exposure: protected | public | private", "protected")
50
+ .option("--id <tunnelId>", "reuse a specific existing tunnel instead of name-based create")
51
+ .option("--host <host>", "local host to forward to", "127.0.0.1")
52
+ .option("--api-url <url>", "override the API base URL")
53
+ .addHelpText("after", [
54
+ "",
55
+ "Access modes:",
56
+ " protected a URL only holders of the printed link can reach (default — journeys use this)",
57
+ " public an open URL — real answer engines can browse it",
58
+ " private no URL; only ora's own scanners reach it",
59
+ "",
60
+ "Examples:",
61
+ " ora tunnel 8081 # like `ngrok http 8081` — prints a working URL",
62
+ " ora tunnel 8081 --access public # let answer engines index the dev site",
63
+ " ora tunnel 3000 --name account-ui"
64
+ ].join("\n"))
65
+ .action(async (portArg, opts) => {
66
+ try {
67
+ await runTunnel(portArg, opts, deps);
68
+ }
69
+ catch (error) {
70
+ deps.errOut(renderError(error));
71
+ process.exitCode = 1;
72
+ }
73
+ });
74
+ }
75
+ async function runTunnel(portArg, opts, deps) {
76
+ const port = Number.parseInt(portArg, 10);
77
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
78
+ throw new Error(`invalid port "${portArg}" — expected 1-65535`);
79
+ }
80
+ const access = opts.access ?? "protected";
81
+ if (!["private", "protected", "public"].includes(access)) {
82
+ throw new Error(`invalid --access "${access}" — expected private | protected | public`);
83
+ }
84
+ const creds = credentials(deps, opts.apiUrl);
85
+ if (!creds)
86
+ return; // credentials() already reported the login hint
87
+ const client = deps.makeClient(creds);
88
+ const tunnel = await resolveTunnel(client, deps, {
89
+ id: opts.id,
90
+ name: opts.name ?? `dev-${port}`,
91
+ access
92
+ });
93
+ if (tunnel.accessToken)
94
+ rememberSecret(deps.dir, tunnel.id, tunnel.accessToken);
95
+ const secret = tunnel.accessToken ?? readSecrets(deps.dir)[tunnel.id] ?? null;
96
+ printHeader(deps, tunnel, port, secret);
97
+ if (tunnel.connection.kind !== "ora-ws") {
98
+ throw new Error(`provider connection kind "${tunnel.connection.kind}" is not supported by this CLI yet`);
99
+ }
100
+ const token = await deps.makeAuth(creds).getToken();
101
+ await holdConnection(tunnel, token, { host: opts.host ?? "127.0.0.1", port }, deps);
102
+ }
103
+ /**
104
+ * create-or-reuse: --id wins; else create by name, falling back to the
105
+ * existing row on 409. A reused tunnel must be USABLE: if its access mode
106
+ * differs from the request, or it is protected and this machine no longer
107
+ * has the secret, it is deleted + recreated (a fresh URL — the ngrok model)
108
+ * rather than handed back half-working.
109
+ */
110
+ async function resolveTunnel(client, deps, want) {
111
+ if (want.id) {
112
+ return (await client.call({ method: "GET", path: `/tunnels/v1/${want.id}` }));
113
+ }
114
+ try {
115
+ return (await client.call({
116
+ method: "POST",
117
+ path: "/tunnels/v1",
118
+ body: { name: want.name, access: want.access }
119
+ }));
120
+ }
121
+ catch (error) {
122
+ if (!(error instanceof Error) || !/409|conflict/i.test(error.message))
123
+ throw error;
124
+ const { tunnels } = (await client.call({ method: "GET", path: "/tunnels/v1" }));
125
+ const existing = tunnels.find((t) => t.name === want.name && t.status !== "revoked");
126
+ if (!existing)
127
+ throw error;
128
+ const secretLost = existing.access === "protected" && !readSecrets(deps.dir)[existing.id];
129
+ if (existing.access !== want.access || secretLost) {
130
+ await client.call({ method: "DELETE", path: `/tunnels/v1/${existing.id}` });
131
+ return (await client.call({
132
+ method: "POST",
133
+ path: "/tunnels/v1",
134
+ body: { name: want.name, access: want.access }
135
+ }));
136
+ }
137
+ return existing;
138
+ }
139
+ }
140
+ function printHeader(deps, tunnel, port, secret) {
141
+ const line = (label, value) => deps.out(` ${chalk.dim(label.padEnd(10))} ${value}`);
142
+ deps.out("");
143
+ deps.out(` ${chalk.bold("🚇 ora tunnel")} ${chalk.dim("—")} ${tunnel.name}`);
144
+ line("forwards", `${chalk.cyan(`localhost:${port}`)} ${chalk.dim("→")} ${tunnel.id.slice(0, 8)}…`);
145
+ // THE line: one URL that works as printed (ngrok parity). Protected embeds
146
+ // the remembered secret; journeys take it verbatim as targetDomain.
147
+ const openable = tunnel.publicUrl && tunnel.access === "protected" && secret
148
+ ? `${tunnel.publicUrl}/?ora_token=${secret}`
149
+ : tunnel.publicUrl;
150
+ if (openable) {
151
+ line("url", chalk.cyan.underline(openable));
152
+ if (tunnel.access === "protected") {
153
+ line("", chalk.dim("only holders of this link reach it — paste it as a journey targetDomain"));
154
+ }
155
+ else {
156
+ line("", chalk.dim("open: anyone (and answer engines) can browse it"));
157
+ }
158
+ }
159
+ else {
160
+ line("access", `${tunnel.access} ${chalk.dim("— no URL: only ora scans reach it (use --access protected for a link)")}`);
161
+ }
162
+ deps.out("");
163
+ }
164
+ /** Dial the WS, run the protocol connector, and log traffic until Ctrl-C. */
165
+ async function holdConnection(tunnel, bearer, target, deps) {
166
+ const url = `${tunnel.connection.url}?tunnelId=${tunnel.id}`;
167
+ const ws = new WebSocket(url, [tunnel.connection.subprotocol], {
168
+ headers: { Authorization: `Bearer ${bearer}` }
169
+ });
170
+ await new Promise((resolve, reject) => {
171
+ ws.once("open", () => resolve());
172
+ ws.once("unexpected-response", (_req, res) => reject(new Error(`connect refused: HTTP ${res.statusCode} (is the tunnel revoked, or the active-tunnel limit reached?)`)));
173
+ ws.once("error", reject);
174
+ });
175
+ const connector = new TunnelConnector({
176
+ socket: wsSocket(ws),
177
+ codec: new V1Codec(),
178
+ hello: {
179
+ agentVersion: "ora-cli",
180
+ target: { protocol: "http", host: target.host, port: target.port },
181
+ maxStreams: 32
182
+ },
183
+ forwarder: { forward: (req) => forwardLocal(req, target, deps) }
184
+ });
185
+ const ack = await connector.start();
186
+ deps.out(` ${chalk.green("●")} connected ${chalk.dim(`(${ack.tunnelId})`)} — Ctrl-C to stop\n`);
187
+ await new Promise((resolve) => {
188
+ const stop = () => {
189
+ deps.out(`\n ${chalk.dim("closing tunnel…")}`);
190
+ connector.close(1000, "cli exit");
191
+ try {
192
+ ws.terminate();
193
+ }
194
+ catch {
195
+ /* already closed */
196
+ }
197
+ resolve();
198
+ };
199
+ process.once("SIGINT", stop);
200
+ process.once("SIGTERM", stop);
201
+ ws.once("close", (code, reason) => {
202
+ deps.out(`\n ${chalk.red("●")} disconnected (${code}${reason.length ? ` ${reason.toString()}` : ""})`);
203
+ resolve();
204
+ });
205
+ });
206
+ }
207
+ /** Forward one proxied request to the local server, logging ngrok-style. */
208
+ async function forwardLocal(req, target, deps) {
209
+ const started = Date.now();
210
+ const res = await new Promise((resolve, reject) => {
211
+ const out = http.request({
212
+ host: target.host,
213
+ port: target.port,
214
+ path: req.path,
215
+ method: req.method,
216
+ headers: sanitizeLocalHeaders(req.headers)
217
+ }, resolve);
218
+ out.on("error", reject);
219
+ void pipeBody(req.body, out);
220
+ });
221
+ const status = res.statusCode ?? 0;
222
+ const color = status < 400 ? chalk.green : status < 500 ? chalk.yellow : chalk.red;
223
+ deps.out(` ${color(String(status))} ${req.method.padEnd(6)} ${req.path} ${chalk.dim(`${Date.now() - started}ms`)}`);
224
+ return {
225
+ status,
226
+ headers: Object.fromEntries(Object.entries(res.headers).filter((e) => typeof e[1] === "string")),
227
+ body: res
228
+ };
229
+ }
230
+ async function pipeBody(body, out) {
231
+ try {
232
+ for await (const chunk of body)
233
+ out.write(chunk);
234
+ }
235
+ finally {
236
+ out.end();
237
+ }
238
+ }
239
+ /** hop-by-hop + host headers must not be replayed against the local server. */
240
+ function sanitizeLocalHeaders(headers) {
241
+ const banned = new Set(["host", "connection", "keep-alive", "transfer-encoding", "upgrade", "te"]);
242
+ return Object.fromEntries(Object.entries(headers).filter(([k]) => !banned.has(k.toLowerCase())));
243
+ }
244
+ /** A `ws` WebSocket adapted to the protocol's transport-neutral ISocket. */
245
+ function wsSocket(ws) {
246
+ return {
247
+ get bufferedAmount() {
248
+ return ws.bufferedAmount;
249
+ },
250
+ send: (data) => {
251
+ if (ws.readyState === ws.OPEN)
252
+ ws.send(data, { binary: true });
253
+ },
254
+ close: (code, reason) => {
255
+ try {
256
+ ws.close(code, reason);
257
+ }
258
+ catch {
259
+ ws.terminate();
260
+ }
261
+ },
262
+ onMessage: (h) => ws.on("message", (d, isBinary) => isBinary && h(new Uint8Array(d))),
263
+ onClose: (h) => ws.on("close", (c, r) => h(c, r.toString())),
264
+ onError: (h) => ws.on("error", h)
265
+ };
266
+ }
267
+ //# sourceMappingURL=tunnel-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-command.js","sourceRoot":"","sources":["../src/tunnel-command.ts"],"names":[],"mappings":"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"}