@oh-hai/cli 0.2.0 → 0.2.1
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 +51 -8
- package/dist/auth/resolve-token.d.ts +2 -4
- package/dist/auth/resolve-token.js +4 -11
- package/dist/auth/resolve-token.js.map +1 -1
- package/dist/bindings.d.ts +65 -0
- package/dist/bindings.js +242 -0
- package/dist/bindings.js.map +1 -0
- package/dist/cli.js +171 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/ask.js +21 -17
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/binary-update.d.ts +61 -0
- package/dist/commands/binary-update.js +160 -0
- package/dist/commands/binary-update.js.map +1 -0
- package/dist/commands/context.d.ts +123 -0
- package/dist/commands/doctor.js +30 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/flags.d.ts +14 -2
- package/dist/commands/flags.js +34 -6
- package/dist/commands/flags.js.map +1 -1
- package/dist/commands/handlers.js +6 -0
- package/dist/commands/handlers.js.map +1 -1
- package/dist/commands/inbox.js +129 -33
- package/dist/commands/inbox.js.map +1 -1
- package/dist/commands/messaging/identity.d.ts +9 -0
- package/dist/commands/messaging/identity.js +21 -0
- package/dist/commands/messaging/identity.js.map +1 -1
- package/dist/commands/messaging/validate.d.ts +6 -5
- package/dist/commands/messaging/validate.js +6 -5
- package/dist/commands/messaging/validate.js.map +1 -1
- package/dist/commands/registry.js +71 -8
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/setup.d.ts +17 -0
- package/dist/commands/setup.js +103 -3
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/task.js +21 -24
- package/dist/commands/task.js.map +1 -1
- package/dist/commands/teach.d.ts +13 -0
- package/dist/commands/teach.js +317 -0
- package/dist/commands/teach.js.map +1 -0
- package/dist/commands/update-check.d.ts +49 -0
- package/dist/commands/update-check.js +203 -0
- package/dist/commands/update-check.js.map +1 -0
- package/dist/commands/upgrade.d.ts +2 -0
- package/dist/commands/upgrade.js +178 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/use.d.ts +2 -0
- package/dist/commands/use.js +99 -0
- package/dist/commands/use.js.map +1 -0
- package/dist/commands/whoami.js +113 -27
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config-file.js +4 -20
- package/dist/config-file.js.map +1 -1
- package/dist/config.d.ts +14 -0
- package/dist/config.js +39 -3
- package/dist/config.js.map +1 -1
- package/dist/exit-codes.d.ts +6 -0
- package/dist/exit-codes.js +6 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/help.js +4 -1
- package/dist/help.js.map +1 -1
- package/dist/os.d.ts +16 -0
- package/dist/os.js +32 -0
- package/dist/os.js.map +1 -0
- package/dist/url.d.ts +7 -0
- package/dist/url.js +14 -0
- package/dist/url.js.map +1 -1
- package/dist/version.d.ts +11 -3
- package/dist/version.js +20 -3
- package/dist/version.js.map +1 -1
- package/dist/watch-lock.d.ts +85 -0
- package/dist/watch-lock.js +358 -0
- package/dist/watch-lock.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,gGAAgG;AAChG,
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CommandContext, TeachFs } from "./context.js";
|
|
2
|
+
/**
|
|
3
|
+
* `oh-hai teach` handler (§4.9). Computes the target files + per-file action, then — unless `--dry-run` —
|
|
4
|
+
* confirms and writes. Flags: `--global` (user-level convention paths instead of the project), `--dry-run`
|
|
5
|
+
* (preview, no writes), `--yes` (skip the confirm). Under `--json`, `--yes` is required (no interactive
|
|
6
|
+
* confirm in machine mode). Reports exactly what it wrote where.
|
|
7
|
+
*/
|
|
8
|
+
export declare function teachCommand(ctx: CommandContext): Promise<void | number>;
|
|
9
|
+
/** Production `TeachFs` backed by the real filesystem + home dir. `read` classifies a target with `lstat`
|
|
10
|
+
* (which does NOT follow symlinks) before touching it — see `TeachRead`. `writeFile` creates parent
|
|
11
|
+
* directories so a global target (e.g. ~/.codex/AGENTS.md) works when the dir is absent. `cwd` degrades to
|
|
12
|
+
* "" if `process.cwd()` throws (a removed working dir), matching config-file.ts. */
|
|
13
|
+
export declare function nodeTeachFs(): TeachFs;
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
// `oh-hai teach` (docs/specs/cli.md §4.9) — teach this machine's agents that OH HAI exists and when to
|
|
2
|
+
// reach for notify / ask / task, by writing a vendor-neutral snippet into the agent-instruction files
|
|
3
|
+
// they already read: the cross-vendor AGENTS.md convention plus any auto-detected vendor files
|
|
4
|
+
// (CLAUDE.md, …). Layer 1 of the owner-aligned (2026-07-03) teaching strategy (#295) — zero server,
|
|
5
|
+
// purely local files. The write is idempotent via a stable MARKED block (below): re-running replaces the
|
|
6
|
+
// block in place, never appends a duplicate; a file whose block already matches is left untouched.
|
|
7
|
+
//
|
|
8
|
+
// Security posture (this is a security-critical Hub CLI, but teach is deliberately inert):
|
|
9
|
+
// • No secrets written — TEACH_SNIPPET is a static constant that REFERENCES the keychain/config and
|
|
10
|
+
// interpolates nothing (§5.4 spirit).
|
|
11
|
+
// • No path injection — every target path is a fixed leaf name joined to teachFs.cwd / .homedir; no
|
|
12
|
+
// user argument feeds a path (--global only switches the anchor, never the leaf names).
|
|
13
|
+
// • No terminal-injection surface — every string printed is first-party/static; no Hub-supplied data
|
|
14
|
+
// flows through teach, so sanitizeForTerminal (terminal.ts) is intentionally not needed here.
|
|
15
|
+
// • Non-destructive — marker replacement preserves all content outside the block; a file with broken
|
|
16
|
+
// or missing markers degrades to a single clean append, never corruption.
|
|
17
|
+
// • Offline — no token resolution, no network.
|
|
18
|
+
import { lstatSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
19
|
+
import { homedir } from "node:os";
|
|
20
|
+
import { dirname, isAbsolute, join } from "node:path";
|
|
21
|
+
import { CliError, buildOk, serializeEnvelope } from "../envelope.js";
|
|
22
|
+
import { safeOsValue } from "../os.js";
|
|
23
|
+
import { sanitizeForTerminal } from "../terminal.js";
|
|
24
|
+
import { flagOn, parseCommandArgs } from "./flags.js";
|
|
25
|
+
/** The idempotency delimiters. They live INSIDE TEACH_SNIPPET (its first and last lines), so the block a
|
|
26
|
+
* fresh file gets and the region a re-run replaces are the same text — one source of truth. */
|
|
27
|
+
const MARKER_START = "<!-- oh-hai:teach start -->";
|
|
28
|
+
const MARKER_END = "<!-- oh-hai:teach end -->";
|
|
29
|
+
/** Escape a literal string for embedding in a RegExp. The markers currently contain no metacharacters, so
|
|
30
|
+
* this is defensive — it keeps the block matcher correct if the marker text ever changes. */
|
|
31
|
+
function escapeRegExp(literal) {
|
|
32
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Matches exactly ONE well-formed teach block and nothing else: a MARKER_START alone on its own line, a
|
|
36
|
+
* body containing no further start line, then a MARKER_END alone on its own line. This is deliberately
|
|
37
|
+
* strict — an earlier `indexOf(MARKER_START)`/`indexOf(MARKER_END)` scan matched the marker substrings
|
|
38
|
+
* ANYWHERE (mid-line, inside a prose sentence) and replaced everything between them, so a file that merely
|
|
39
|
+
* *documented* the convention — or carried a stray/orphaned marker — had its content silently deleted.
|
|
40
|
+
* Line anchoring (`m` flag + `^…$`) means a marker mentioned inside a sentence is never a delimiter; the
|
|
41
|
+
* tempered body (negative lookahead rejecting a nested start line) stops a stray start line from slicing
|
|
42
|
+
* across an unrelated region, so an orphaned marker degrades to a clean append instead of corruption.
|
|
43
|
+
* Leading/trailing spaces or tabs on a marker line are tolerated (editors reflow them); no `g` flag, so
|
|
44
|
+
* `.exec` is stateless and finds the FIRST well-formed block.
|
|
45
|
+
*/
|
|
46
|
+
const BLOCK_RE = new RegExp(`^[ \\t]*${escapeRegExp(MARKER_START)}[ \\t]*$` +
|
|
47
|
+
`(?:(?!^[ \\t]*${escapeRegExp(MARKER_START)}[ \\t]*$)[\\s\\S])*?` +
|
|
48
|
+
`^[ \\t]*${escapeRegExp(MARKER_END)}[ \\t]*$`, "m");
|
|
49
|
+
/** The v1 teaching snippet — from #295 (owner-aligned 2026-07-03), resolver-optional per #369 (with no
|
|
50
|
+
* `--resolver` the Hub routes an ask/task to the account owner, issue #366). Static: it references the
|
|
51
|
+
* OS keychain / config path and embeds NO token. Begins with MARKER_START, ends with MARKER_END, so
|
|
52
|
+
* the same text is both what a new file receives and the region a re-run overwrites. */
|
|
53
|
+
const TEACH_SNIPPET = [
|
|
54
|
+
MARKER_START,
|
|
55
|
+
"## Reaching your human — OH HAI",
|
|
56
|
+
"",
|
|
57
|
+
"This machine has **OH HAI**: a universal inbox that lets you reach the person you're working for —",
|
|
58
|
+
"and get their answer back **even after this session ends**. Use the `oh-hai` CLI when you genuinely",
|
|
59
|
+
"need them:",
|
|
60
|
+
"",
|
|
61
|
+
'- **`oh-hai notify --title "…" --body "…"`** — an FYI / status / heads-up. Fire-and-forget, no reply.',
|
|
62
|
+
'- **`oh-hai ask submit --mode <select|input|confirm> --title "…"`** — you need a',
|
|
63
|
+
" **decision** before you can safely proceed (approve / pick an option / supply a value). It returns the",
|
|
64
|
+
" human's signed answer, so you can wait for it — or exit and resume later with `oh-hai ask await --id …`.",
|
|
65
|
+
" See `oh-hai ask --help` for the select / input / confirm modes and their flags.",
|
|
66
|
+
'- **`oh-hai task submit --title "…" --instructions "…"`** — you need the human to',
|
|
67
|
+
" **do something out-of-band** (rotate a key, flip a setting, run a step). You'll learn when it's done.",
|
|
68
|
+
"",
|
|
69
|
+
"You don't need to say **who**: with no `--resolver`, an ask/task goes to the **account owner** — the",
|
|
70
|
+
"person this machine is set up for. `--resolver human:<id>` is optional narrowing to name a specific",
|
|
71
|
+
"person; the owner can always resolve either way.",
|
|
72
|
+
"",
|
|
73
|
+
"**When to reach out:** for real decisions you can't make safely, hard blockers, or things the human",
|
|
74
|
+
"clearly wants to know — **not** routine progress. One clear `ask` beats guessing or spamming. The",
|
|
75
|
+
"human triages these in their OH HAI inbox and their reply comes back to you through the same channel.",
|
|
76
|
+
"",
|
|
77
|
+
"Auth + routing are already set up (OS keychain + `~/.config/oh-hai/config.toml`). Just run the",
|
|
78
|
+
"commands — no tokens to handle. If `oh-hai` isn't found, it isn't installed here; carry on normally.",
|
|
79
|
+
MARKER_END,
|
|
80
|
+
].join("\n");
|
|
81
|
+
/** Vendor instruction files we UPDATE in place when they already exist in the project (never create — we
|
|
82
|
+
* don't invent a CLAUDE.md in a repo that never had one). AGENTS.md is the always-ensured primary and is
|
|
83
|
+
* not in this list. Kept to single-file markdown conventions; directory-based rule stores (Cursor's
|
|
84
|
+
* `.cursor/rules/*.mdc`) are a deferred follow-up. */
|
|
85
|
+
const PROJECT_VENDOR_FILES = [
|
|
86
|
+
"CLAUDE.md",
|
|
87
|
+
"GEMINI.md",
|
|
88
|
+
join(".github", "copilot-instructions.md"),
|
|
89
|
+
".cursorrules",
|
|
90
|
+
".windsurfrules",
|
|
91
|
+
];
|
|
92
|
+
/** User-global vendor instruction files updated in place when present under --global (same never-create
|
|
93
|
+
* rule). The global AGENTS convention primary is ~/.codex/AGENTS.md (Codex's documented user-level path)
|
|
94
|
+
* and is not in this list. */
|
|
95
|
+
const GLOBAL_VENDOR_FILES = [
|
|
96
|
+
join(".claude", "CLAUDE.md"),
|
|
97
|
+
join(".gemini", "GEMINI.md"),
|
|
98
|
+
];
|
|
99
|
+
/** Resolve the primary AGENTS.md path + candidate vendor paths for the chosen scope. Paths are fixed leaf
|
|
100
|
+
* names joined to a trusted anchor (cwd / homedir) — no user input feeds a path. */
|
|
101
|
+
function targetPaths(fs, global) {
|
|
102
|
+
const anchor = global ? fs.homedir : fs.cwd;
|
|
103
|
+
const primary = global ? join(anchor, ".codex", "AGENTS.md") : join(anchor, "AGENTS.md");
|
|
104
|
+
const vendorList = global ? GLOBAL_VENDOR_FILES : PROJECT_VENDOR_FILES;
|
|
105
|
+
return { primary, vendors: vendorList.map((rel) => join(anchor, rel)) };
|
|
106
|
+
}
|
|
107
|
+
/** Compute the new content + action for a single file from its current content (undefined = absent).
|
|
108
|
+
* The marked block is replaced in place when present, appended after a blank line when the file exists
|
|
109
|
+
* without a usable marker, and written whole into a fresh/empty file. Returns action "unchanged" (and no
|
|
110
|
+
* content) when the file already matches — the idempotency property. */
|
|
111
|
+
function planContent(current) {
|
|
112
|
+
if (current === undefined) {
|
|
113
|
+
return { action: "created", next: `${TEACH_SNIPPET}\n` };
|
|
114
|
+
}
|
|
115
|
+
const match = BLOCK_RE.exec(current);
|
|
116
|
+
let next;
|
|
117
|
+
if (match !== null) {
|
|
118
|
+
// Replace the one well-formed block in place with the canonical snippet; all surrounding content
|
|
119
|
+
// (including any stray/orphaned marker lines the tempered matcher refused to treat as a block) is
|
|
120
|
+
// preserved verbatim.
|
|
121
|
+
next = current.slice(0, match.index) + TEACH_SNIPPET + current.slice(match.index + match[0].length);
|
|
122
|
+
}
|
|
123
|
+
else if (current.trim() === "") {
|
|
124
|
+
// File exists but is empty/whitespace — write the block whole (action stays "updated": it pre-existed).
|
|
125
|
+
next = `${TEACH_SNIPPET}\n`;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// No well-formed block — append one clean block after a blank-line separator, preserving prior content.
|
|
129
|
+
// A stray/orphaned marker becomes part of that preserved prose; the next run finds only THIS block.
|
|
130
|
+
next = `${current.replace(/\s*$/, "")}\n\n${TEACH_SNIPPET}\n`;
|
|
131
|
+
}
|
|
132
|
+
return next === current ? { action: "unchanged" } : { action: "updated", next };
|
|
133
|
+
}
|
|
134
|
+
/** Turn a read into the content `planContent` consumes (a regular file's text, or undefined when absent). */
|
|
135
|
+
function contentOf(read) {
|
|
136
|
+
return read.kind === "file" ? read.content : undefined;
|
|
137
|
+
}
|
|
138
|
+
/** Build the ordered target list: the primary AGENTS.md always, then each existing vendor file. Each file
|
|
139
|
+
* is read exactly once. The primary is REQUIRED, so an unsafe primary (symlink / non-regular / unreadable)
|
|
140
|
+
* aborts the whole command rather than risk overwriting whatever is actually there; unsafe VENDOR files
|
|
141
|
+
* (update-only) are skipped and reported. Spreading the plan keeps `next` OMITTED (not `undefined`) for the
|
|
142
|
+
* unchanged case, which `exactOptionalPropertyTypes` requires. */
|
|
143
|
+
function planTargets(fs, global) {
|
|
144
|
+
const { primary, vendors } = targetPaths(fs, global);
|
|
145
|
+
const primaryRead = fs.read(primary);
|
|
146
|
+
if (primaryRead.kind === "unsafe") {
|
|
147
|
+
throw new CliError("error", `refusing to write ${sanitizeForTerminal(primary)} — it ${primaryRead.reason}.`);
|
|
148
|
+
}
|
|
149
|
+
const targets = [{ path: primary, ...planContent(contentOf(primaryRead)) }];
|
|
150
|
+
const skipped = [];
|
|
151
|
+
for (const path of vendors) {
|
|
152
|
+
const read = fs.read(path);
|
|
153
|
+
if (read.kind === "absent")
|
|
154
|
+
continue; // vendor files are update-only; never created
|
|
155
|
+
if (read.kind === "unsafe") {
|
|
156
|
+
skipped.push({ path, reason: read.reason });
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
targets.push({ path, ...planContent(read.content) });
|
|
160
|
+
}
|
|
161
|
+
return { targets, skipped };
|
|
162
|
+
}
|
|
163
|
+
/** One human line per target: `<action> <path>`. Paths are sanitized for the terminal — cwd/home can
|
|
164
|
+
* carry control characters from a hostile checkout path, and every human command sanitizes echoed output
|
|
165
|
+
* (terminal.ts). The raw path is still used for the actual filesystem write and the `--json` envelope. */
|
|
166
|
+
function planLines(targets) {
|
|
167
|
+
return targets.map((t) => ` ${t.action.padEnd(9)} ${sanitizeForTerminal(t.path)}`);
|
|
168
|
+
}
|
|
169
|
+
/** Emit the plan/outcome — a `--json` envelope, or a human table. `wrote` distinguishes a completed write
|
|
170
|
+
* from a preview (dry-run or the non-interactive hint). `skipped` carries any vendor files teach refused
|
|
171
|
+
* to touch for safety. */
|
|
172
|
+
function report(ctx, plan, opts) {
|
|
173
|
+
const { targets, skipped } = plan;
|
|
174
|
+
if (ctx.json) {
|
|
175
|
+
ctx.io.log(serializeEnvelope(buildOk("teach", {
|
|
176
|
+
files: targets.map((t) => ({ path: t.path, action: t.action })),
|
|
177
|
+
// Additive, non-breaking: omitted (pruneUndefined) when nothing was skipped.
|
|
178
|
+
skipped: skipped.length > 0 ? skipped.map((s) => ({ path: s.path, reason: s.reason })) : undefined,
|
|
179
|
+
dry_run: opts.dryRun,
|
|
180
|
+
wrote: opts.wrote,
|
|
181
|
+
})));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const header = opts.dryRun
|
|
185
|
+
? "oh-hai teach — dry run (no files written):"
|
|
186
|
+
: opts.wrote
|
|
187
|
+
? "oh-hai teach — wrote the OH HAI snippet:"
|
|
188
|
+
: "oh-hai teach — would write the OH HAI snippet:";
|
|
189
|
+
ctx.io.log(header);
|
|
190
|
+
for (const line of planLines(targets))
|
|
191
|
+
ctx.io.log(line);
|
|
192
|
+
if (opts.wrote && targets.every((t) => t.action === "unchanged")) {
|
|
193
|
+
ctx.io.log("Everything already up to date — nothing to change.");
|
|
194
|
+
}
|
|
195
|
+
for (const s of skipped)
|
|
196
|
+
ctx.io.err(`oh-hai: skipped ${sanitizeForTerminal(s.path)} — it ${s.reason}.`);
|
|
197
|
+
}
|
|
198
|
+
/** Interactive confirmation (human mode, no --yes). Show the plan on stderr, read one line via `readLine`
|
|
199
|
+
* (falling back to `readStdin` for harnesses that don't inject `readLine`). */
|
|
200
|
+
async function promptConfirm(ctx, plan) {
|
|
201
|
+
ctx.io.err("oh-hai teach — about to write the OH HAI snippet to:");
|
|
202
|
+
for (const line of planLines(plan.targets))
|
|
203
|
+
ctx.io.err(line);
|
|
204
|
+
ctx.io.err('Type "y" to confirm: ');
|
|
205
|
+
const readOne = ctx.runtime.readLine ?? ctx.runtime.readStdin;
|
|
206
|
+
const answer = (await readOne()).trim().toLowerCase();
|
|
207
|
+
return answer === "y" || answer === "yes";
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* `oh-hai teach` handler (§4.9). Computes the target files + per-file action, then — unless `--dry-run` —
|
|
211
|
+
* confirms and writes. Flags: `--global` (user-level convention paths instead of the project), `--dry-run`
|
|
212
|
+
* (preview, no writes), `--yes` (skip the confirm). Under `--json`, `--yes` is required (no interactive
|
|
213
|
+
* confirm in machine mode). Reports exactly what it wrote where.
|
|
214
|
+
*/
|
|
215
|
+
export async function teachCommand(ctx) {
|
|
216
|
+
const { values } = parseCommandArgs(ctx.argv, {
|
|
217
|
+
global: { type: "boolean" },
|
|
218
|
+
"dry-run": { type: "boolean" },
|
|
219
|
+
yes: { type: "boolean" },
|
|
220
|
+
});
|
|
221
|
+
const global = flagOn(values.global);
|
|
222
|
+
const dryRun = flagOn(values["dry-run"]);
|
|
223
|
+
const yes = flagOn(values.yes);
|
|
224
|
+
const fs = ctx.runtime.teachFs;
|
|
225
|
+
if (fs === undefined) {
|
|
226
|
+
// Defensive: production always wires nodeTeachFs(); a missing seam is an internal wiring bug, not a
|
|
227
|
+
// user error — surface it clearly instead of a TypeError on `fs.read`.
|
|
228
|
+
throw new CliError("error", "teach: filesystem seam unavailable (internal wiring error).");
|
|
229
|
+
}
|
|
230
|
+
// Targets are joined onto a trusted anchor (cwd, or homedir under --global). If that anchor isn't an
|
|
231
|
+
// absolute path — a stripped-down account with no $HOME under --global, or a removed working directory —
|
|
232
|
+
// every target would resolve relative to the process cwd and write to the wrong place, so refuse.
|
|
233
|
+
const anchor = global ? fs.homedir : fs.cwd;
|
|
234
|
+
if (!isAbsolute(anchor)) {
|
|
235
|
+
throw new CliError("usage", global
|
|
236
|
+
? "--global needs an absolute home directory, but none is set for this user."
|
|
237
|
+
: "teach needs an absolute working directory, but the current directory is unavailable.");
|
|
238
|
+
}
|
|
239
|
+
const plan = planTargets(fs, global);
|
|
240
|
+
// --dry-run reports the plan and stops before any confirm/write.
|
|
241
|
+
if (dryRun) {
|
|
242
|
+
report(ctx, plan, { dryRun: true, wrote: false });
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
// Machine mode can't run an interactive confirm; require an explicit --yes (mirrors `agents revoke`).
|
|
246
|
+
if (ctx.json && !yes) {
|
|
247
|
+
throw new CliError("usage", "refusing to write without --yes under --json (interactive confirmation is unavailable in machine mode).");
|
|
248
|
+
}
|
|
249
|
+
if (!yes) {
|
|
250
|
+
// Past the --json guard, so this is human mode. Prompt only when a human is actually at the terminal;
|
|
251
|
+
// otherwise print the plan + how to proceed and exit WITHOUT blocking on a read and WITHOUT writing.
|
|
252
|
+
const interactive = (ctx.runtime.isInteractive?.() ?? false) && ctx.runtime.readLine !== undefined;
|
|
253
|
+
if (!interactive) {
|
|
254
|
+
report(ctx, plan, { dryRun: false, wrote: false });
|
|
255
|
+
ctx.io.err("oh-hai: re-run with --yes to write these files (no interactive terminal to confirm on).");
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (!(await promptConfirm(ctx, plan))) {
|
|
259
|
+
ctx.io.err("Aborted — no changes made.");
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// `next` is present exactly for the changed targets (planContent omits it for "unchanged"), so this
|
|
264
|
+
// guard both skips no-op writes and narrows `next` to string.
|
|
265
|
+
for (const t of plan.targets) {
|
|
266
|
+
if (t.next !== undefined) {
|
|
267
|
+
fs.writeFile(t.path, t.next);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
report(ctx, plan, { dryRun: false, wrote: true });
|
|
271
|
+
}
|
|
272
|
+
/** Production `TeachFs` backed by the real filesystem + home dir. `read` classifies a target with `lstat`
|
|
273
|
+
* (which does NOT follow symlinks) before touching it — see `TeachRead`. `writeFile` creates parent
|
|
274
|
+
* directories so a global target (e.g. ~/.codex/AGENTS.md) works when the dir is absent. `cwd` degrades to
|
|
275
|
+
* "" if `process.cwd()` throws (a removed working dir), matching config-file.ts. */
|
|
276
|
+
export function nodeTeachFs() {
|
|
277
|
+
return {
|
|
278
|
+
read: (path) => {
|
|
279
|
+
let stat;
|
|
280
|
+
try {
|
|
281
|
+
// lstat, not stat/readFile: classify the LINK itself so a symlink is caught before it's followed,
|
|
282
|
+
// and a FIFO/device is caught before an unconditional readFileSync could hang or exhaust memory.
|
|
283
|
+
stat = lstatSync(path);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
// ENOENT is genuinely absent → safe to create. Any OTHER stat error means something IS there we
|
|
287
|
+
// can't inspect — treating it as absent would let a later write truncate it, so mark it unsafe.
|
|
288
|
+
if (err.code === "ENOENT")
|
|
289
|
+
return { kind: "absent" };
|
|
290
|
+
return { kind: "unsafe", reason: `could not be inspected (${err.code ?? "stat failed"})` };
|
|
291
|
+
}
|
|
292
|
+
// A symlink would make writeFileSync follow it and write OUTSIDE the repo; a non-regular file (dir,
|
|
293
|
+
// FIFO, device, socket) is never a real instruction file and reading it could block. Refuse both.
|
|
294
|
+
if (stat.isSymbolicLink())
|
|
295
|
+
return { kind: "unsafe", reason: "is a symlink" };
|
|
296
|
+
if (!stat.isFile())
|
|
297
|
+
return { kind: "unsafe", reason: "is not a regular file" };
|
|
298
|
+
try {
|
|
299
|
+
// No size cap: a target we can't fully read must NOT look absent (a later write would truncate a
|
|
300
|
+
// legitimately large AGENTS.md). An unreadable regular file is unsafe, not absent.
|
|
301
|
+
return { kind: "file", content: readFileSync(path, "utf8") };
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return { kind: "unsafe", reason: "is unreadable" };
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
writeFile: (path, content) => {
|
|
308
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
309
|
+
writeFileSync(path, content, "utf8");
|
|
310
|
+
},
|
|
311
|
+
// `process.cwd()` can throw when the working directory was removed; degrade to "" so wiring the
|
|
312
|
+
// runtime never crashes a run that doesn't even use teach.
|
|
313
|
+
cwd: safeOsValue(() => process.cwd()),
|
|
314
|
+
homedir: homedir(),
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=teach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teach.js","sourceRoot":"","sources":["../../src/commands/teach.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { FetchLike, InstallFacts, InstallMethod } from "./context.js";
|
|
2
|
+
/** The published package name (matches cli/package.json "name"). */
|
|
3
|
+
export declare const PACKAGE_NAME = "@oh-hai/cli";
|
|
4
|
+
/** The npm packument URL — the scoped name is URL-encoded (`/` → `%2F`). The `/<name>/latest`
|
|
5
|
+
* shortcut is unreliable for scoped packages, so we read `dist-tags.latest` off the packument.
|
|
6
|
+
* `dist-tags.latest` is always a STABLE version (never a prerelease), which is exactly what a
|
|
7
|
+
* running build should be compared against. */
|
|
8
|
+
export declare const REGISTRY_PACKUMENT_URL = "https://registry.npmjs.org/@oh-hai%2Fcli";
|
|
9
|
+
/** The result of a version check. `latest`/`error` are mutually exclusive: a successful check
|
|
10
|
+
* sets `latest`; any failure sets `error` and leaves `updateAvailable` false. */
|
|
11
|
+
export interface UpdateCheck {
|
|
12
|
+
current: string;
|
|
13
|
+
latest?: string;
|
|
14
|
+
updateAvailable: boolean;
|
|
15
|
+
/** Set when the registry couldn't be consulted or parsed — callers degrade, never crash. */
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Semver precedence for the shapes this package publishes (`major.minor.patch[-prerelease]`).
|
|
20
|
+
* Returns -1 (a < b), 0 (equal), or 1 (a > b). A version WITH a prerelease is lower than the same
|
|
21
|
+
* core WITHOUT one (`1.0.0-beta.0` < `1.0.0`). Unparseable input compares as equal (0) so a bad
|
|
22
|
+
* `latest` is never read as newer.
|
|
23
|
+
*/
|
|
24
|
+
export declare function compareSemver(a: string, b: string): -1 | 0 | 1;
|
|
25
|
+
/**
|
|
26
|
+
* Classify how the CLI was installed, from injected facts (pure → fully unit-testable). Only a
|
|
27
|
+
* genuine compiled standalone classifies as `binary`, because that method now self-updates in place
|
|
28
|
+
* by replacing `process.execPath` — misclassifying a shared `node`/`bun` interpreter running our
|
|
29
|
+
* script as `binary` would let `oh-hai upgrade` overwrite the user's runtime (#358 review). So the
|
|
30
|
+
* order is deliberate:
|
|
31
|
+
* 1. a `.ts` module path → running from source via tsx (`dev`);
|
|
32
|
+
* 2. a module UNDER `node_modules` → an npm/script install, classified by prefix (GLOBAL prefix →
|
|
33
|
+
* `npm-global`; project-local / npx / brew → `unknown` guidance, never a global mutation). This
|
|
34
|
+
* is checked BEFORE the standalone fallback so a renamed interpreter (`nodejs`, `node24`, a
|
|
35
|
+
* distro wrapper) running an npm dist can never fall through to the self-update path;
|
|
36
|
+
* 3. otherwise, a NON-interpreter executable means the compiled standalone IS the executable
|
|
37
|
+
* (`binary`) — interpreter detection is a broad `node`/`bun`/`deno`-prefix match so renamed Node
|
|
38
|
+
* runtimes are excluded;
|
|
39
|
+
* 4. an interpreter running a built dist outside `node_modules` → a local checkout (`dev`);
|
|
40
|
+
* 5. anything else → `unknown`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function classifyInstall(facts: InstallFacts): InstallMethod;
|
|
43
|
+
/**
|
|
44
|
+
* Fetch the latest published `@oh-hai/cli` version and compare it to `current`. Never throws: any
|
|
45
|
+
* transport failure, non-200, unparseable body, or missing `dist-tags.latest` returns a result
|
|
46
|
+
* with `error` set and `updateAvailable` false. `timeoutMs` bounds the request (defaulted on
|
|
47
|
+
* absent/0/negative, clamped to the timer ceiling).
|
|
48
|
+
*/
|
|
49
|
+
export declare function checkForUpdate(current: string, fetchImpl: FetchLike, timeoutMs?: number): Promise<UpdateCheck>;
|