otter-axi 0.1.0 → 1.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.
- package/README.md +11 -5
- package/dist/src/commands/fetch.d.ts +15 -1
- package/dist/src/commands/fetch.js +93 -72
- package/dist/src/commands/fetch.js.map +1 -1
- package/package.json +9 -1
- package/skills/otter-axi/SKILL.md +6 -4
package/README.md
CHANGED
|
@@ -17,10 +17,13 @@ any agent session or shell, with refresh handled silently.
|
|
|
17
17
|
## Install & authenticate
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
|
|
20
|
+
npm install -g otter-axi # install the CLI on your PATH
|
|
21
|
+
otter-axi auth login # one-time browser approval
|
|
21
22
|
otter-axi doctor # config → credentials → MCP reachable
|
|
22
23
|
```
|
|
23
24
|
|
|
25
|
+
Or run any command ad hoc without installing: `npx -y otter-axi <command>`.
|
|
26
|
+
|
|
24
27
|
Tokens are stored in `~/.config/otter-axi/config.json` (mode `0600`) and refreshed
|
|
25
28
|
automatically; they are never printed. Read-only scopes: `profile:read`, `conversations:read`.
|
|
26
29
|
|
|
@@ -44,14 +47,17 @@ Flags: `-q/--query`, `--after`/`--before` (ISO or relative `7d`/`2w`/`3m`/`1y`),
|
|
|
44
47
|
```sh
|
|
45
48
|
otter-axi fetch <id> # metadata + preview
|
|
46
49
|
otter-axi fetch <id> --full # verbatim transcript to stdout (for piping)
|
|
47
|
-
otter-axi fetch <id> --
|
|
48
|
-
otter-axi fetch <id> --json-out
|
|
49
|
-
otter-axi fetch <id> --csv-out
|
|
50
|
+
otter-axi fetch <id> --json-out # parsed segments → auto-path in the OS temp dir
|
|
51
|
+
otter-axi fetch <id> --json-out=t.json # …or an explicit path
|
|
52
|
+
otter-axi fetch <id> --csv-out # CSV (--tsv-out / --text-out likewise)
|
|
50
53
|
```
|
|
51
54
|
|
|
52
55
|
The segment formats (`--json-out`/`--csv-out`/`--tsv-out`) parse the `[H:MM:SS] Speaker N: …`
|
|
53
56
|
transcript into `{start, speaker, text}` rows — otter-axi owns one tested, lossless parser so
|
|
54
|
-
agents don't re-derive it.
|
|
57
|
+
agents don't re-derive it. Per the [AXI side-channel-file convention](https://github.com/kunchenguid/axi/issues/32),
|
|
58
|
+
the path is optional (bare → `<os-tmpdir>/otter-axi/<ts>-<id>.<ext>` — transient scratch the OS
|
|
59
|
+
cleans up), and writing a file is additive: stdout keeps the preview and adds `wrote:`/`columns:`
|
|
60
|
+
and a `jq` hint.
|
|
55
61
|
|
|
56
62
|
## Commands
|
|
57
63
|
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import type { StructuredOutput } from "../output.js";
|
|
2
|
-
export declare const FETCH_HELP = "usage: otter-axi fetch <id|url> [output-mode]\nargs:\n <id|url>
|
|
2
|
+
export declare const FETCH_HELP = "usage: otter-axi fetch <id|url> [output-mode]\nargs:\n <id|url> conversation slug or an https://otter.ai/u/<id> URL\noutput modes (at most one; default is a preview):\n --full print the entire verbatim transcript to stdout (for piping)\n --text-out[=path] write the verbatim transcript text to a file (alias: --out)\n --json-out[=path] write parsed segments [{start,speaker,text}] as JSON\n --csv-out[=path] write parsed segments as CSV (start,speaker,text)\n --tsv-out[=path] write parsed segments as TSV\nnotes:\n Path is optional: bare flag auto-writes ~/.config/otter-axi/exports/<ts>-<id>.<ext>;\n use --json-out=path for an explicit location. Writing a file is additive \u2014 stdout keeps\n the preview and adds wrote/columns/jq help. otter-axi owns the lossless transcript parse.";
|
|
3
|
+
type OutFormat = "text" | "json" | "csv" | "tsv";
|
|
3
4
|
/** Normalize a conversation slug or otter.ai URL to a bare id. */
|
|
4
5
|
export declare function normalizeConversationId(input: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Explicit path (expanded), or an auto path in the OS temp dir keyed by timestamp + id.
|
|
8
|
+
* An auto-generated export is ephemeral scratch, so it goes in `os.tmpdir()` (OS-pruned) —
|
|
9
|
+
* never under `~/.config`, which nothing prunes. `os.tmpdir()` → `/tmp` on Linux, `$TMPDIR` on macOS.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveExportPath(explicit: string | undefined, format: OutFormat, id: string, now?: Date): string;
|
|
12
|
+
/**
|
|
13
|
+
* Write an export file. Auto-generated files (no explicit path) land in a world-readable temp
|
|
14
|
+
* dir and may hold a sensitive transcript → owner-only `0600`. Explicit paths are the caller's
|
|
15
|
+
* responsibility and use the default umask.
|
|
16
|
+
*/
|
|
17
|
+
export declare function writeExport(path: string, body: string, auto: boolean): void;
|
|
5
18
|
export declare function fetchCommand(args: string[]): Promise<StructuredOutput | string>;
|
|
19
|
+
export {};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { writeFileSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir, tmpdir } from "node:os";
|
|
3
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
2
4
|
import { Buffer } from "node:buffer";
|
|
3
5
|
import { AxiError } from "axi-sdk-js";
|
|
4
6
|
import { hasFlag, parseArgs, strFlag } from "../flags.js";
|
|
@@ -7,36 +9,66 @@ import { truncateCell } from "../output.js";
|
|
|
7
9
|
import { parseTranscript, segmentsToCsv, segmentsToTsv, } from "../transcript.js";
|
|
8
10
|
export const FETCH_HELP = `usage: otter-axi fetch <id|url> [output-mode]
|
|
9
11
|
args:
|
|
10
|
-
<id|url>
|
|
12
|
+
<id|url> conversation slug or an https://otter.ai/u/<id> URL
|
|
11
13
|
output modes (at most one; default is a preview):
|
|
12
|
-
--full
|
|
13
|
-
--text-out
|
|
14
|
-
--json-out
|
|
15
|
-
--csv-out
|
|
16
|
-
--tsv-out
|
|
14
|
+
--full print the entire verbatim transcript to stdout (for piping)
|
|
15
|
+
--text-out[=path] write the verbatim transcript text to a file (alias: --out)
|
|
16
|
+
--json-out[=path] write parsed segments [{start,speaker,text}] as JSON
|
|
17
|
+
--csv-out[=path] write parsed segments as CSV (start,speaker,text)
|
|
18
|
+
--tsv-out[=path] write parsed segments as TSV
|
|
17
19
|
notes:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
Path is optional: bare flag auto-writes ~/.config/otter-axi/exports/<ts>-<id>.<ext>;
|
|
21
|
+
use --json-out=path for an explicit location. Writing a file is additive — stdout keeps
|
|
22
|
+
the preview and adds wrote/columns/jq help. otter-axi owns the lossless transcript parse.`;
|
|
20
23
|
const PREVIEW_CHARS = 1200;
|
|
24
|
+
const EXT = { text: "txt", json: "json", csv: "csv", tsv: "tsv" };
|
|
25
|
+
// Flags that select a file-export format. NOT in `valued`, so a bare flag is boolean
|
|
26
|
+
// (→ auto-path) and an explicit path uses `--json-out=path` (avoids eating the <id> positional).
|
|
27
|
+
const OUT_FLAGS = [
|
|
28
|
+
{ flag: "json-out", format: "json" },
|
|
29
|
+
{ flag: "csv-out", format: "csv" },
|
|
30
|
+
{ flag: "tsv-out", format: "tsv" },
|
|
31
|
+
{ flag: "text-out", format: "text" },
|
|
32
|
+
{ flag: "out", format: "text" }, // back-compat alias
|
|
33
|
+
];
|
|
21
34
|
/** Normalize a conversation slug or otter.ai URL to a bare id. */
|
|
22
35
|
export function normalizeConversationId(input) {
|
|
23
36
|
const trimmed = input.trim();
|
|
24
37
|
const match = trimmed.match(/otter\.ai\/u\/([^/?#]+)/i);
|
|
25
38
|
return match ? match[1] : trimmed;
|
|
26
39
|
}
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
function expandPath(p) {
|
|
41
|
+
const e = p.startsWith("~/") ? join(homedir(), p.slice(2)) : p;
|
|
42
|
+
return isAbsolute(e) ? e : resolve(e);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Explicit path (expanded), or an auto path in the OS temp dir keyed by timestamp + id.
|
|
46
|
+
* An auto-generated export is ephemeral scratch, so it goes in `os.tmpdir()` (OS-pruned) —
|
|
47
|
+
* never under `~/.config`, which nothing prunes. `os.tmpdir()` → `/tmp` on Linux, `$TMPDIR` on macOS.
|
|
48
|
+
*/
|
|
49
|
+
export function resolveExportPath(explicit, format, id, now = new Date()) {
|
|
50
|
+
if (explicit)
|
|
51
|
+
return expandPath(explicit);
|
|
52
|
+
const stamp = now.toISOString().replace(/[:.]/g, "-");
|
|
53
|
+
return join(tmpdir(), "otter-axi", `${stamp}-${id}.${EXT[format]}`);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Write an export file. Auto-generated files (no explicit path) land in a world-readable temp
|
|
57
|
+
* dir and may hold a sensitive transcript → owner-only `0600`. Explicit paths are the caller's
|
|
58
|
+
* responsibility and use the default umask.
|
|
59
|
+
*/
|
|
60
|
+
export function writeExport(path, body, auto) {
|
|
61
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
62
|
+
writeFileSync(path, body, auto ? { mode: 0o600 } : undefined);
|
|
63
|
+
}
|
|
64
|
+
function jqHelp(format, path) {
|
|
65
|
+
if (format === "json") {
|
|
66
|
+
return `Run \`jq -r '.[] | "[\\(.start)] \\(.speaker): \\(.text)"' ${path}\` to process the segments`;
|
|
35
67
|
}
|
|
36
|
-
return
|
|
68
|
+
return undefined;
|
|
37
69
|
}
|
|
38
70
|
export async function fetchCommand(args) {
|
|
39
|
-
const parsed = parseArgs(args
|
|
71
|
+
const parsed = parseArgs(args);
|
|
40
72
|
const raw = parsed.positionals[0];
|
|
41
73
|
if (!raw) {
|
|
42
74
|
throw new AxiError("Missing conversation id or URL", "VALIDATION_ERROR", [
|
|
@@ -45,14 +77,10 @@ export async function fetchCommand(args) {
|
|
|
45
77
|
]);
|
|
46
78
|
}
|
|
47
79
|
const id = normalizeConversationId(raw);
|
|
48
|
-
const
|
|
49
|
-
const jsonPath = outPath(parsed, "json-out");
|
|
50
|
-
const csvPath = outPath(parsed, "csv-out");
|
|
51
|
-
const tsvPath = outPath(parsed, "tsv-out");
|
|
80
|
+
const present = OUT_FLAGS.filter((m) => hasFlag(parsed, m.flag));
|
|
52
81
|
const full = hasFlag(parsed, "full");
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
if (modeCount > 1) {
|
|
82
|
+
const distinctFormats = new Set(present.map((m) => m.format));
|
|
83
|
+
if (distinctFormats.size + (full ? 1 : 0) > 1) {
|
|
56
84
|
throw new AxiError("Choose a single output mode", "VALIDATION_ERROR", [
|
|
57
85
|
"Use one of --full | --text-out | --json-out | --csv-out | --tsv-out",
|
|
58
86
|
]);
|
|
@@ -69,7 +97,10 @@ export async function fetchCommand(args) {
|
|
|
69
97
|
]);
|
|
70
98
|
}
|
|
71
99
|
const text = t.text ?? "";
|
|
72
|
-
|
|
100
|
+
// Raw transcript to stdout for piping — return a string so the SDK passes it through as-is.
|
|
101
|
+
if (full)
|
|
102
|
+
return text;
|
|
103
|
+
const base = {
|
|
73
104
|
id: t.id ?? id,
|
|
74
105
|
title: t.title ?? "",
|
|
75
106
|
url: t.url ?? `https://otter.ai/u/${t.id ?? id}`,
|
|
@@ -79,54 +110,44 @@ export async function fetchCommand(args) {
|
|
|
79
110
|
action_items: Array.isArray(t.metadata?.action_items)
|
|
80
111
|
? t.metadata.action_items.length
|
|
81
112
|
: 0,
|
|
113
|
+
chars: text.length,
|
|
114
|
+
preview: truncateCell(text, PREVIEW_CHARS),
|
|
82
115
|
};
|
|
83
|
-
|
|
84
|
-
if (textPath) {
|
|
85
|
-
writeFileSync(textPath, text);
|
|
86
|
-
return { ...meta, format: "text", saved: textPath, bytes: Buffer.byteLength(text) };
|
|
87
|
-
}
|
|
88
|
-
// Parsed segment formats → file.
|
|
89
|
-
if (jsonPath || csvPath || tsvPath) {
|
|
90
|
-
const segments = parseTranscript(text);
|
|
91
|
-
const speakers = [...new Set(segments.map((s) => s.speaker).filter(Boolean))];
|
|
92
|
-
let body;
|
|
93
|
-
let path;
|
|
94
|
-
let format;
|
|
95
|
-
if (jsonPath) {
|
|
96
|
-
body = `${JSON.stringify(segments, null, 2)}\n`;
|
|
97
|
-
path = jsonPath;
|
|
98
|
-
format = "json";
|
|
99
|
-
}
|
|
100
|
-
else if (csvPath) {
|
|
101
|
-
body = segmentsToCsv(segments);
|
|
102
|
-
path = csvPath;
|
|
103
|
-
format = "csv";
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
body = segmentsToTsv(segments);
|
|
107
|
-
path = tsvPath;
|
|
108
|
-
format = "tsv";
|
|
109
|
-
}
|
|
110
|
-
writeFileSync(path, body);
|
|
116
|
+
if (present.length === 0) {
|
|
111
117
|
return {
|
|
112
|
-
...
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
speakers,
|
|
118
|
+
...base,
|
|
119
|
+
help: [
|
|
120
|
+
"Export with --json-out / --csv-out / --tsv-out / --text-out (add =path for an explicit location)",
|
|
121
|
+
"--full prints the whole verbatim transcript to stdout",
|
|
122
|
+
],
|
|
118
123
|
};
|
|
119
124
|
}
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
// File export — additive: keep the preview, write the file, add wrote/columns/jq help.
|
|
126
|
+
const format = present[0].format;
|
|
127
|
+
const explicit = present.map((m) => strFlag(parsed, m.flag)).find((v) => v !== undefined);
|
|
128
|
+
const path = resolveExportPath(explicit, format, id);
|
|
129
|
+
let body;
|
|
130
|
+
const extra = {};
|
|
131
|
+
if (format === "text") {
|
|
132
|
+
body = text;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const segments = parseTranscript(text);
|
|
136
|
+
body =
|
|
137
|
+
format === "json"
|
|
138
|
+
? `${JSON.stringify(segments, null, 2)}\n`
|
|
139
|
+
: format === "csv"
|
|
140
|
+
? segmentsToCsv(segments)
|
|
141
|
+
: segmentsToTsv(segments);
|
|
142
|
+
extra.segments = segments.length;
|
|
143
|
+
extra.columns = "start, speaker, text";
|
|
144
|
+
}
|
|
145
|
+
// Auto-generated (no explicit path) → owner-only 0600 (sensitive transcript in a temp dir).
|
|
146
|
+
writeExport(path, body, explicit === undefined);
|
|
147
|
+
const help = [];
|
|
148
|
+
const jq = jqHelp(format, path);
|
|
149
|
+
if (jq)
|
|
150
|
+
help.push(jq);
|
|
151
|
+
return { ...base, wrote: path, bytes: Buffer.byteLength(body), ...extra, ...(help.length ? { help } : {}) };
|
|
131
152
|
}
|
|
132
153
|
//# sourceMappingURL=fetch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/commands/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/commands/fetch.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "otter-axi",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Find and pull Otter.ai meeting transcripts from the terminal with token-efficient output.",
|
|
6
6
|
"bin": {
|
|
@@ -37,6 +37,14 @@
|
|
|
37
37
|
"vitest": "^4.1.9"
|
|
38
38
|
},
|
|
39
39
|
"author": "Jarvus Innovations",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/JarvusInnovations/otter-axi.git"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/JarvusInnovations/otter-axi#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/JarvusInnovations/otter-axi/issues"
|
|
47
|
+
},
|
|
40
48
|
"keywords": [
|
|
41
49
|
"otter",
|
|
42
50
|
"otter.ai",
|
|
@@ -51,14 +51,16 @@ Tokens live in `~/.config/otter-axi/config.json` (mode 0600) and are never print
|
|
|
51
51
|
```sh
|
|
52
52
|
otter-axi fetch <id> # metadata header + preview
|
|
53
53
|
otter-axi fetch <id> --full # verbatim transcript to stdout (pipe it)
|
|
54
|
-
otter-axi fetch <id> --
|
|
55
|
-
otter-axi fetch <id> --json-out
|
|
56
|
-
otter-axi fetch <id> --csv-out
|
|
54
|
+
otter-axi fetch <id> --json-out # parsed segments → auto-path under exports/
|
|
55
|
+
otter-axi fetch <id> --json-out=t.json # …or an explicit path (note the = form)
|
|
56
|
+
otter-axi fetch <id> --csv-out # CSV (--tsv-out / --text-out likewise)
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
Transcripts are `[H:MM:SS] Speaker N: …`. Default/`--full`/`--text-out` are verbatim; the
|
|
60
60
|
`--json-out`/`--csv-out`/`--tsv-out` modes parse into `{start,speaker,text}` segments via
|
|
61
|
-
otter-axi's own lossless parser (so you don't re-derive it).
|
|
61
|
+
otter-axi's own lossless parser (so you don't re-derive it). Path is optional (bare →
|
|
62
|
+
auto-path in the OS temp dir `<os-tmpdir>/otter-axi/`; `=path` for explicit); writing is additive —
|
|
63
|
+
stdout keeps the preview and adds `wrote:`/`columns:` + a `jq` hint. One output mode per call.
|
|
62
64
|
|
|
63
65
|
## Notes
|
|
64
66
|
|