@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
package/dist/commands/whoami.js
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
// secret (§5.4): agent id, base URL, token presence + a redacted fingerprint, and where the
|
|
3
3
|
// token resolved from (`keychain` / `file` / `env`). Works fully offline. `--check` adds a
|
|
4
4
|
// network probe of the Hub for token validity: exit 0 valid, 3 on 401/403, 5 unreachable (§9).
|
|
5
|
+
// The probe hits GET /auth/whoami, so a valid token ALSO yields the caller's Hub-attested actor. A
|
|
6
|
+
// `human:<id>` actor is printed as `resolver:` — the exact address an agent uses to route an ask/task
|
|
7
|
+
// to that human (issue #362); an agent-authed CLI validates but has no human resolver to show. An
|
|
8
|
+
// older Hub without that endpoint still validates via a legacy fallback probe (resolver omitted).
|
|
5
9
|
import { createHash } from "node:crypto";
|
|
6
10
|
import { CliError, buildOk, serializeEnvelope } from "../envelope.js";
|
|
7
11
|
import { resolveIdentity } from "../auth/resolve-token.js";
|
|
@@ -18,43 +22,89 @@ export function fingerprintToken(token) {
|
|
|
18
22
|
* set. §9 promises offline is an explicit state, never a silent hang — a Hub that accepts the
|
|
19
23
|
* connection but never responds must still surface a timeout rather than block forever. */
|
|
20
24
|
const DEFAULT_CHECK_TIMEOUT_MS = 10_000;
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
* authenticated, message not found). `401`/`403` = invalid/revoked; `5xx` = the Hub errored (no
|
|
25
|
-
* validity signal); a transport failure = unreachable/timeout. Any other status (a `2xx`/`3xx`
|
|
26
|
-
* from a proxy that ignores `Authorization`, a wrong `--base-url`) is NOT proof of validity and
|
|
27
|
-
* is reported as such rather than a false "valid". Side-effect-free — a GET creates nothing. */
|
|
28
|
-
async function checkToken(ctx, token) {
|
|
29
|
-
if (token === undefined) {
|
|
30
|
-
throw new CliError("auth", "not authenticated — no stored token to check (run `oh-hai login`).");
|
|
31
|
-
}
|
|
32
|
-
const url = `${ctx.config.baseUrl}/v1/messages/oh-hai-whoami-check-nonexistent`;
|
|
25
|
+
/** Side-effect-free authenticated GET, with the transport-error → §7 exit-code mapping shared by both
|
|
26
|
+
* probes (a timeout is exit 7, any other connection failure exit 5). */
|
|
27
|
+
async function probeGet(ctx, path, token) {
|
|
33
28
|
const init = {
|
|
34
29
|
method: "GET",
|
|
35
30
|
headers: { Authorization: `Bearer ${token}` },
|
|
36
31
|
signal: AbortSignal.timeout(ctx.config.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS),
|
|
37
32
|
};
|
|
38
|
-
|
|
33
|
+
// A per-request timeout is exit 7 (§7); a DNS/connection failure is exit 5 (§9). throwTransportError
|
|
34
|
+
// returns `never`, so the rejected-path handler doesn't widen the resolved type.
|
|
35
|
+
return ctx.runtime
|
|
36
|
+
.fetchImpl(`${ctx.config.baseUrl}${path}`, init)
|
|
37
|
+
.catch((error) => throwTransportError(error, ctx.config.baseUrl));
|
|
38
|
+
}
|
|
39
|
+
/** Parse a response body as a JSON object, defensively — a status-only fake, a non-JSON body, or a
|
|
40
|
+
* non-object all collapse to `{}` (mirrors agents.ts readJson). */
|
|
41
|
+
async function readJsonBody(res) {
|
|
42
|
+
if (typeof res.json !== "function")
|
|
43
|
+
return {};
|
|
39
44
|
try {
|
|
40
|
-
|
|
45
|
+
const parsed = await res.json();
|
|
46
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
|
|
47
|
+
? parsed
|
|
48
|
+
: {};
|
|
41
49
|
}
|
|
42
|
-
catch
|
|
43
|
-
|
|
44
|
-
throwTransportError(error, ctx.config.baseUrl);
|
|
50
|
+
catch {
|
|
51
|
+
return {};
|
|
45
52
|
}
|
|
53
|
+
}
|
|
54
|
+
/** The `actor` field of a whoami body — required to be a well-formed MA2H actor (`human:<id>` /
|
|
55
|
+
* `agent:<id>`, the endpoint's only shapes). A proxy `200` returning arbitrary JSON (e.g.
|
|
56
|
+
* `{actor:"ok"}`), or a blank/missing value, is NOT mistaken for a valid Hub identity. */
|
|
57
|
+
function readActor(body) {
|
|
58
|
+
const actor = typeof body.actor === "string" ? body.actor.trim() : "";
|
|
59
|
+
return /^(?:human|agent):.+/.test(actor) ? actor : undefined;
|
|
60
|
+
}
|
|
61
|
+
/** Map a "could not confirm validity" status to the §7 error the two probes share — ALWAYS throws
|
|
62
|
+
* (each probe handles its own "authenticated" status before delegating here). */
|
|
63
|
+
function classifyProbeStatus(status) {
|
|
46
64
|
if (status === 401 || status === 403) {
|
|
47
65
|
throw new CliError("auth", `token is invalid or revoked (Hub returned ${status}).`);
|
|
48
66
|
}
|
|
49
67
|
if (status >= 500) {
|
|
50
68
|
throw new CliError("server", `Hub returned ${status}; token validity could not be confirmed.`);
|
|
51
69
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
throw new CliError("error", `unexpected Hub response ${status}; could not confirm token validity (check --base-url).`);
|
|
71
|
+
}
|
|
72
|
+
/** Legacy validity probe for a Hub that predates GET /auth/whoami: an authenticated GET of a
|
|
73
|
+
* nonexistent message id. The Hub authenticates BEFORE the id lookup, so the expected `404`
|
|
74
|
+
* (authenticated, not found) proves the bearer is valid; every other status is handled uniformly.
|
|
75
|
+
* Yields no resolver id. */
|
|
76
|
+
async function legacyCheckToken(ctx, token) {
|
|
77
|
+
const status = (await probeGet(ctx, "/v1/messages/oh-hai-whoami-check-nonexistent", token)).status;
|
|
78
|
+
if (status === 404)
|
|
79
|
+
return; // authenticated + not found → valid
|
|
80
|
+
classifyProbeStatus(status);
|
|
81
|
+
}
|
|
82
|
+
/** Probe the Hub for token validity via GET /auth/whoami (issue #362). A `200` carrying an `{ actor }`
|
|
83
|
+
* body BOTH proves the presented bearer authenticated AND yields the Hub-attested resolver id (a
|
|
84
|
+
* human's `human:<id>` or an agent's `agent:<id>`), returned for display. `401`/`403` = invalid/revoked
|
|
85
|
+
* (exit 3); `5xx` = the Hub errored, no validity signal (exit 6); a transport failure = unreachable/
|
|
86
|
+
* timeout (exit 5/7). A `404` means the endpoint is absent (an older Hub) — fall back to the legacy
|
|
87
|
+
* probe so `--check` stays valid there (resolver omitted). Any other response — a `2xx`/`3xx` from a
|
|
88
|
+
* proxy that ignored `Authorization`, or a `200` without a real `{ actor }` body — is NOT proof of
|
|
89
|
+
* validity and is reported as such rather than a false "valid". Side-effect-free — a GET creates nothing. */
|
|
90
|
+
async function checkToken(ctx, token) {
|
|
91
|
+
if (token === undefined) {
|
|
92
|
+
throw new CliError("auth", "not authenticated — no stored token to check (run `oh-hai login`).");
|
|
93
|
+
}
|
|
94
|
+
const res = await probeGet(ctx, "/auth/whoami", token);
|
|
95
|
+
if (res.status === 200) {
|
|
96
|
+
const actor = readActor(await readJsonBody(res));
|
|
97
|
+
if (actor !== undefined)
|
|
98
|
+
return actor; // authenticated → the Hub-attested resolver id
|
|
99
|
+
// A 200 without a real actor body isn't the Hub's whoami (likely a proxy ignoring auth).
|
|
100
|
+
throw new CliError("error", "unexpected Hub response (200 without an identity); could not confirm token validity (check --base-url).");
|
|
56
101
|
}
|
|
57
|
-
|
|
102
|
+
if (res.status === 404) {
|
|
103
|
+
// The endpoint is absent (an older Hub) — confirm validity the legacy way; no resolver id.
|
|
104
|
+
await legacyCheckToken(ctx, token);
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
classifyProbeStatus(res.status);
|
|
58
108
|
}
|
|
59
109
|
export async function whoamiCommand(ctx) {
|
|
60
110
|
const { values } = parseCommandArgs(ctx.argv, { check: { type: "boolean" } });
|
|
@@ -65,26 +115,62 @@ export async function whoamiCommand(ctx) {
|
|
|
65
115
|
const resolved = await resolveIdentity(ctx.config, store);
|
|
66
116
|
const account = resolved.account;
|
|
67
117
|
const fingerprint = resolved.token !== undefined ? fingerprintToken(resolved.token) : undefined;
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
118
|
+
// Where `account` resolved (§6), so `whoami` explains the resolution — key once per-project bindings
|
|
119
|
+
// exist (#321). resolveConfig set `accountSource` for the flag/env/binding/user-config layers; when
|
|
120
|
+
// it's "none" (nothing configured) yet an account still resolved, resolveIdentity DISCOVERED the sole
|
|
121
|
+
// stored identity. `binding_path` rides along only for the binding source (pruned otherwise).
|
|
122
|
+
const source = ctx.config.accountSource;
|
|
123
|
+
const accountSource = source === undefined || source === "none"
|
|
124
|
+
? account !== undefined
|
|
125
|
+
? "discovered"
|
|
126
|
+
: undefined
|
|
127
|
+
: source;
|
|
128
|
+
const bindingPath = source === "binding" ? ctx.config.bindingPath : undefined;
|
|
129
|
+
// A failing --check throws before any identity is printed (the command result IS the check). On
|
|
130
|
+
// success it returns the caller's Hub-attested actor (undefined against an older Hub without the
|
|
131
|
+
// endpoint). Only a `human:<id>` actor is a resolver an agent can address to reach a human — a
|
|
132
|
+
// CLI authed with an agent bearer (the common device-code flow) resolves as `agent:<id>`, which the
|
|
133
|
+
// submit paths reject, so it must NOT be presented as a `resolver:` the user can hand out (issue #362).
|
|
134
|
+
const actor = flagOn(values.check) ? await checkToken(ctx, resolved.token) : undefined;
|
|
135
|
+
const resolver = actor !== undefined && actor.startsWith("human:") ? actor : undefined;
|
|
72
136
|
if (ctx.json) {
|
|
73
137
|
const token = { present: resolved.token !== undefined, source: resolved.source };
|
|
74
138
|
if (fingerprint !== undefined) {
|
|
75
139
|
token.fingerprint = fingerprint;
|
|
76
140
|
}
|
|
77
|
-
ctx.io.log(serializeEnvelope(buildOk("whoami", {
|
|
141
|
+
ctx.io.log(serializeEnvelope(buildOk("whoami", {
|
|
142
|
+
agent_id: account,
|
|
143
|
+
base_url: ctx.config.baseUrl,
|
|
144
|
+
token,
|
|
145
|
+
account_source: accountSource,
|
|
146
|
+
binding_path: bindingPath,
|
|
147
|
+
resolver,
|
|
148
|
+
})));
|
|
78
149
|
}
|
|
79
150
|
else {
|
|
80
151
|
// Sanitize before terminal output: a DISCOVERED account is the raw agent id the Hub chose at
|
|
81
152
|
// login time, so a hostile Hub could have stored control characters in it (the raw id is kept
|
|
82
153
|
// for lookup and the JSON envelope, where JSON.stringify escapes them — §5.4 / login parity).
|
|
83
154
|
ctx.io.log(`agent: ${account !== undefined ? sanitizeForTerminal(account) : "(none — set --account/--agent or MA2H_AGENT_ID)"}`);
|
|
155
|
+
// Explain HOW the account resolved (flag / env / binding@<path> / user config / discovered).
|
|
156
|
+
if (accountSource !== undefined) {
|
|
157
|
+
const via = accountSource === "binding" && bindingPath !== undefined
|
|
158
|
+
? `binding (${sanitizeForTerminal(bindingPath)})`
|
|
159
|
+
: accountSource === "user-config"
|
|
160
|
+
? "user config"
|
|
161
|
+
: accountSource;
|
|
162
|
+
ctx.io.log(`via: ${via}`);
|
|
163
|
+
}
|
|
84
164
|
ctx.io.log(`base url: ${ctx.config.baseUrl}`);
|
|
85
165
|
ctx.io.log(resolved.token !== undefined
|
|
86
166
|
? `token: present (…${fingerprint}) [${resolved.source}]`
|
|
87
167
|
: "token: absent");
|
|
168
|
+
// The Hub-attested human resolver id — present only after a successful --check that returned a
|
|
169
|
+
// `human:` actor (an agent-authed CLI has none to hand out). Sanitize: the actor is Hub-supplied,
|
|
170
|
+
// so a hostile Hub could smuggle control chars.
|
|
171
|
+
if (resolver !== undefined) {
|
|
172
|
+
ctx.io.log(`resolver: ${sanitizeForTerminal(resolver)}`);
|
|
173
|
+
}
|
|
88
174
|
}
|
|
89
175
|
}
|
|
90
176
|
//# sourceMappingURL=whoami.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,4FAA4F;AAC5F,2FAA2F;AAC3F,+FAA+F;
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"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"}
|
package/dist/config-file.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { readFileSync, statSync } from "node:fs";
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
17
|
import { dirname, isAbsolute, join } from "node:path";
|
|
18
|
+
import { resolveXdgConfigHome, safeOsValue } from "./os.js";
|
|
18
19
|
/**
|
|
19
20
|
* Parse the minimal config dialect: flat `key = value` lines plus an optional `[oh-hai]` section.
|
|
20
21
|
* Values are quoted strings (single/double), integers (optional sign + `_` separators), or booleans.
|
|
@@ -143,18 +144,11 @@ function mapProjectConfig(record) {
|
|
|
143
144
|
}
|
|
144
145
|
/** Load `~/.config/oh-hai/config.toml` ($XDG_CONFIG_HOME honored). Undefined when the file is absent. */
|
|
145
146
|
export function loadUserConfig(io) {
|
|
146
|
-
const xdg = io.xdgConfigHome?.trim();
|
|
147
|
-
const home = io.homedir.trim();
|
|
148
147
|
// The user-global config is TRUSTED (it alone may set base_url / default_account), so its directory
|
|
149
148
|
// must be ABSOLUTE — a relative path would resolve against cwd and let a repo-committed file
|
|
150
|
-
// masquerade as user-global config, bypassing per-project rejection.
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
const configHome = xdg !== undefined && xdg !== "" && isAbsolute(xdg)
|
|
154
|
-
? xdg
|
|
155
|
-
: home !== "" && isAbsolute(home)
|
|
156
|
-
? join(home, ".config")
|
|
157
|
-
: undefined;
|
|
149
|
+
// masquerade as user-global config, bypassing per-project rejection. `resolveXdgConfigHome` enforces
|
|
150
|
+
// that (shared with the bindings store); undefined → no absolute config dir, so skip the user config.
|
|
151
|
+
const configHome = resolveXdgConfigHome(io);
|
|
158
152
|
if (configHome === undefined) {
|
|
159
153
|
return undefined;
|
|
160
154
|
}
|
|
@@ -195,16 +189,6 @@ export function loadConfigFiles(io) {
|
|
|
195
189
|
/** Generous ceiling on a config file's size — real configs are a few keys; anything larger is either
|
|
196
190
|
* a mistake or a hostile plant, so it's skipped rather than read into memory. */
|
|
197
191
|
const MAX_CONFIG_BYTES = 1024 * 1024;
|
|
198
|
-
/** Read an OS value that can throw (notably `process.cwd()` when the working dir was removed), degrading
|
|
199
|
-
* to "" so config loading never crashes a command that doesn't even need the value. */
|
|
200
|
-
function safeOsValue(read) {
|
|
201
|
-
try {
|
|
202
|
-
return read();
|
|
203
|
-
}
|
|
204
|
-
catch {
|
|
205
|
-
return "";
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
192
|
/** Production `ConfigFileIo` backed by the real filesystem, home dir, cwd, and environment. */
|
|
209
193
|
export function nodeConfigFileIo() {
|
|
210
194
|
return {
|
package/dist/config-file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-file.js","sourceRoot":"","sources":["../src/config-file.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,kGAAkG;AAClG,kGAAkG;AAClG,EAAE;AACF,qBAAqB;AACrB,qGAAqG;AACrG,uGAAuG;AACvG,mGAAmG;AACnG,qGAAqG;AACrG,oEAAoE;AACpE,EAAE;AACF,kGAAkG;AAClG,kGAAkG;AAClG,wEAAwE;AAExE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config-file.js","sourceRoot":"","sources":["../src/config-file.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { type Binding } from "./bindings.js";
|
|
1
2
|
export declare const DEFAULT_BASE_URL = "https://inbox.ohhai.app";
|
|
2
3
|
export type OutputFormat = "human" | "json";
|
|
3
4
|
export type TokenSource = "env" | "keychain" | "file" | "none";
|
|
5
|
+
/** Where the resolved `account` came from (§6 precedence), for `whoami` to explain the resolution.
|
|
6
|
+
* `"binding"` is a user-side directory→agent binding (bindings.ts); `"none"` means nothing was
|
|
7
|
+
* configured — a downstream sole-identity DISCOVERY (resolveIdentity) may still find one. */
|
|
8
|
+
export type AccountSource = "flag" | "env" | "binding" | "user-config" | "none";
|
|
4
9
|
/** Global flags after parsing (the subset that feeds config resolution). */
|
|
5
10
|
export interface RawFlags {
|
|
6
11
|
baseUrl?: string | undefined;
|
|
@@ -45,12 +50,21 @@ export interface ResolvedConfig {
|
|
|
45
50
|
color: boolean;
|
|
46
51
|
token: string | undefined;
|
|
47
52
|
tokenSource: TokenSource;
|
|
53
|
+
/** How `account` resolved (§6), for `whoami`. Optional so a hand-built config (tests) may omit it. */
|
|
54
|
+
accountSource?: AccountSource;
|
|
55
|
+
/** The bound directory when `accountSource === "binding"`; omitted otherwise. */
|
|
56
|
+
bindingPath?: string | undefined;
|
|
48
57
|
}
|
|
49
58
|
export interface ResolveInput {
|
|
50
59
|
flags?: RawFlags | undefined;
|
|
51
60
|
env?: EnvVars | undefined;
|
|
52
61
|
userConfig?: UserConfig | undefined;
|
|
53
62
|
projectConfig?: ProjectConfig | undefined;
|
|
63
|
+
/** User-side directory→agent bindings (already loaded from the user dir; bindings.ts). Consulted for
|
|
64
|
+
* the account precedence only — a repo never reaches this, preserving credential-safety (§6). */
|
|
65
|
+
bindings?: Binding[] | undefined;
|
|
66
|
+
/** The process working directory, for walk-up binding resolution. Omitted → bindings are ignored. */
|
|
67
|
+
cwd?: string | undefined;
|
|
54
68
|
}
|
|
55
69
|
export interface ResolveResult {
|
|
56
70
|
config: ResolvedConfig;
|
package/dist/config.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
//
|
|
12
12
|
// #105 implements the resolution CONTRACT over an already-parsed, in-memory config object.
|
|
13
13
|
// The TOML file loader + per-project discovery + keychain read land in #106/#107.
|
|
14
|
+
import { resolveBinding } from "./bindings.js";
|
|
15
|
+
import { originOf } from "./url.js";
|
|
14
16
|
// The production Hub — a shipped CLI must reach the real service with zero configuration (#271, R8).
|
|
15
17
|
// Local development points at a local hub by setting MA2H_BASE_URL (or `--base-url`), which outranks
|
|
16
18
|
// this default (§6 precedence).
|
|
@@ -66,8 +68,42 @@ export function resolveConfig(input = {}) {
|
|
|
66
68
|
// empty, so fall back to the default rather than yield an unusable "".
|
|
67
69
|
const resolvedBase = (firstPresent(flags.baseUrl, env.MA2H_BASE_URL, userConfig.base_url) ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
68
70
|
const baseUrl = resolvedBase === "" ? DEFAULT_BASE_URL : resolvedBase;
|
|
69
|
-
// account: flag > env > USER config only. Project config excluded on purpose.
|
|
70
|
-
|
|
71
|
+
// account: flag > env > directory binding > USER config only (§6). Project config excluded on purpose.
|
|
72
|
+
// The directory binding (bindings.ts) is user-side + origin-scoped, so it can supply the account for
|
|
73
|
+
// the current directory tree WITHOUT a repo ever influencing identity — it sits BELOW an explicit
|
|
74
|
+
// --account / MA2H_AGENT_ID (which still win) and ABOVE the user-global default. `accountSource`
|
|
75
|
+
// records which layer won, for `whoami` to explain the resolution.
|
|
76
|
+
const origin = originOf(baseUrl);
|
|
77
|
+
const binding = input.bindings !== undefined && input.cwd !== undefined
|
|
78
|
+
? resolveBinding(input.bindings, input.cwd, origin)
|
|
79
|
+
: undefined;
|
|
80
|
+
const flagAccount = presentString(flags.account);
|
|
81
|
+
const envAccount = presentString(env.MA2H_AGENT_ID);
|
|
82
|
+
const userAccount = presentString(userConfig.default_account);
|
|
83
|
+
let account;
|
|
84
|
+
let accountSource;
|
|
85
|
+
let bindingPath = undefined;
|
|
86
|
+
if (flagAccount !== undefined) {
|
|
87
|
+
account = flagAccount;
|
|
88
|
+
accountSource = "flag";
|
|
89
|
+
}
|
|
90
|
+
else if (envAccount !== undefined) {
|
|
91
|
+
account = envAccount;
|
|
92
|
+
accountSource = "env";
|
|
93
|
+
}
|
|
94
|
+
else if (binding !== undefined) {
|
|
95
|
+
account = binding.account;
|
|
96
|
+
accountSource = "binding";
|
|
97
|
+
bindingPath = binding.path;
|
|
98
|
+
}
|
|
99
|
+
else if (userAccount !== undefined) {
|
|
100
|
+
account = userAccount;
|
|
101
|
+
accountSource = "user-config";
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
account = undefined;
|
|
105
|
+
accountSource = "none";
|
|
106
|
+
}
|
|
71
107
|
// output: an explicit --json flag wins EITHER way (--json → json, --json=false → human, upholding
|
|
72
108
|
// flag > config precedence); only when the flag is absent does the config `output` decide; else human.
|
|
73
109
|
const output = flags.json === true
|
|
@@ -93,7 +129,7 @@ export function resolveConfig(input = {}) {
|
|
|
93
129
|
const envToken = presentString(env.MA2H_AGENT_TOKEN);
|
|
94
130
|
const tokenSource = envToken !== undefined ? "env" : "none";
|
|
95
131
|
return {
|
|
96
|
-
config: { baseUrl, account, output, timeoutMs, color, token: envToken, tokenSource },
|
|
132
|
+
config: { baseUrl, account, output, timeoutMs, color, token: envToken, tokenSource, accountSource, bindingPath },
|
|
97
133
|
warnings,
|
|
98
134
|
};
|
|
99
135
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,EAAE;AACF,sFAAsF;AACtF,EAAE;AACF,sFAAsF;AACtF,2FAA2F;AAC3F,6FAA6F;AAC7F,2FAA2F;AAC3F,2FAA2F;AAC3F,0FAA0F;AAC1F,EAAE;AACF,2FAA2F;AAC3F,kFAAkF;AAElF,qGAAqG;AACrG,qGAAqG;AACrG,gCAAgC;AAChC,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/exit-codes.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ export declare const ExitCode: {
|
|
|
19
19
|
readonly CONFLICT: 8;
|
|
20
20
|
/** 9 — Invalid request (Hub 400/422/413; version not supported). */
|
|
21
21
|
readonly INVALID_REQUEST: 9;
|
|
22
|
+
/** 10 — Already running: a LOCAL precondition conflict, no Hub call — currently only a second
|
|
23
|
+
* `inbox watch` on an identity another live watcher already holds (#323). Distinct from `8`
|
|
24
|
+
* (a Hub 409) so a caller branching on the exit code never mistakes a non-retryable "stop the
|
|
25
|
+
* other watcher" for a retryable idempotency conflict. */
|
|
26
|
+
readonly ALREADY_RUNNING: 10;
|
|
22
27
|
};
|
|
23
28
|
export type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];
|
|
24
29
|
/**
|
|
@@ -39,6 +44,7 @@ declare const ERROR_CODE_TO_EXIT: {
|
|
|
39
44
|
readonly validation_error: 9;
|
|
40
45
|
readonly payload_too_large: 9;
|
|
41
46
|
readonly version_not_supported: 9;
|
|
47
|
+
readonly already_running: 10;
|
|
42
48
|
readonly not_implemented: 1;
|
|
43
49
|
};
|
|
44
50
|
export type ErrorCode = keyof typeof ERROR_CODE_TO_EXIT;
|
package/dist/exit-codes.js
CHANGED
|
@@ -22,6 +22,11 @@ export const ExitCode = {
|
|
|
22
22
|
CONFLICT: 8,
|
|
23
23
|
/** 9 — Invalid request (Hub 400/422/413; version not supported). */
|
|
24
24
|
INVALID_REQUEST: 9,
|
|
25
|
+
/** 10 — Already running: a LOCAL precondition conflict, no Hub call — currently only a second
|
|
26
|
+
* `inbox watch` on an identity another live watcher already holds (#323). Distinct from `8`
|
|
27
|
+
* (a Hub 409) so a caller branching on the exit code never mistakes a non-retryable "stop the
|
|
28
|
+
* other watcher" for a retryable idempotency conflict. */
|
|
29
|
+
ALREADY_RUNNING: 10,
|
|
25
30
|
};
|
|
26
31
|
/**
|
|
27
32
|
* Stable `error.code` strings (§8) → exit codes (§7). An exit code may cover more
|
|
@@ -41,6 +46,7 @@ const ERROR_CODE_TO_EXIT = {
|
|
|
41
46
|
validation_error: ExitCode.INVALID_REQUEST,
|
|
42
47
|
payload_too_large: ExitCode.INVALID_REQUEST,
|
|
43
48
|
version_not_supported: ExitCode.INVALID_REQUEST,
|
|
49
|
+
already_running: ExitCode.ALREADY_RUNNING,
|
|
44
50
|
not_implemented: ExitCode.ERROR,
|
|
45
51
|
};
|
|
46
52
|
/** Map a (possibly unknown) `error.code` string to its exit code; unknown → generic 1. */
|
package/dist/exit-codes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,mFAAmF;AACnF,gEAAgE;AAEhE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,mBAAmB;IACnB,OAAO,EAAE,CAAC;IACV,sCAAsC;IACtC,KAAK,EAAE,CAAC;IACR,mEAAmE;IACnE,KAAK,EAAE,CAAC;IACR,mEAAmE;IACnE,IAAI,EAAE,CAAC;IACP,sDAAsD;IACtD,SAAS,EAAE,CAAC;IACZ,oEAAoE;IACpE,OAAO,EAAE,CAAC;IACV,kCAAkC;IAClC,MAAM,EAAE,CAAC;IACT,qEAAqE;IACrE,OAAO,EAAE,CAAC;IACV,4EAA4E;IAC5E,QAAQ,EAAE,CAAC;IACX,oEAAoE;IACpE,eAAe,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,mFAAmF;AACnF,gEAAgE;AAEhE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,mBAAmB;IACnB,OAAO,EAAE,CAAC;IACV,sCAAsC;IACtC,KAAK,EAAE,CAAC;IACR,mEAAmE;IACnE,KAAK,EAAE,CAAC;IACR,mEAAmE;IACnE,IAAI,EAAE,CAAC;IACP,sDAAsD;IACtD,SAAS,EAAE,CAAC;IACZ,oEAAoE;IACpE,OAAO,EAAE,CAAC;IACV,kCAAkC;IAClC,MAAM,EAAE,CAAC;IACT,qEAAqE;IACrE,OAAO,EAAE,CAAC;IACV,4EAA4E;IAC5E,QAAQ,EAAE,CAAC;IACX,oEAAoE;IACpE,eAAe,EAAE,CAAC;IAClB;;;+DAG2D;IAC3D,eAAe,EAAE,EAAE;CACX,CAAC;AAIX;;;;GAIG;AACH,MAAM,kBAAkB,GAAG;IACzB,KAAK,EAAE,QAAQ,CAAC,KAAK;IACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;IACrB,IAAI,EAAE,QAAQ,CAAC,IAAI;IACnB,SAAS,EAAE,QAAQ,CAAC,SAAS;IAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO;IACzB,MAAM,EAAE,QAAQ,CAAC,MAAM;IACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;IACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;IAC3B,WAAW,EAAE,QAAQ,CAAC,eAAe;IACrC,gBAAgB,EAAE,QAAQ,CAAC,eAAe;IAC1C,iBAAiB,EAAE,QAAQ,CAAC,eAAe;IAC3C,qBAAqB,EAAE,QAAQ,CAAC,eAAe;IAC/C,eAAe,EAAE,QAAQ,CAAC,eAAe;IACzC,eAAe,EAAE,QAAQ,CAAC,KAAK;CACvB,CAAC;AAIX,0FAA0F;AAC1F,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAA6B,kBAAkB,CAAC;IAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC;AACvC,CAAC;AAED;;oGAEoG;AACpG,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;AACxE,CAAC"}
|
package/dist/help.js
CHANGED
|
@@ -6,11 +6,14 @@ export const TOP_LEVEL_HELP = [
|
|
|
6
6
|
"Usage: oh-hai [global flags] <command> [subcommand] [flags]",
|
|
7
7
|
"",
|
|
8
8
|
"Setup: setup (bare `oh-hai` on a new machine onboards; re-run to add/re-auth)",
|
|
9
|
-
"Auth: login | logout | whoami",
|
|
9
|
+
"Auth: login | logout | whoami | use",
|
|
10
|
+
" (use: bind this directory to an agent — per-project identity)",
|
|
10
11
|
"Messaging: notify | ask | task",
|
|
11
12
|
"Inbox: inbox watch",
|
|
12
13
|
"Agents: agents list | create | revoke",
|
|
13
14
|
"Health: doctor",
|
|
15
|
+
"Teach: teach (write the OH HAI snippet into this machine's agent-instruction files)",
|
|
16
|
+
"Update: upgrade (self-update, or --check for a newer oh-hai)",
|
|
14
17
|
"",
|
|
15
18
|
"Global flags: --base-url --account --json --quiet --verbose --no-color --timeout",
|
|
16
19
|
"Run 'oh-hai <command> --help' for details.",
|
package/dist/help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,qEAAqE;AAErE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,8DAA8D;IAC9D,EAAE;IACF,6DAA6D;IAC7D,EAAE;IACF,sFAAsF;IACtF,
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,qEAAqE;AAErE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,8DAA8D;IAC9D,EAAE;IACF,6DAA6D;IAC7D,EAAE;IACF,sFAAsF;IACtF,2CAA2C;IAC3C,mFAAmF;IACnF,iCAAiC;IACjC,yBAAyB;IACzB,2CAA2C;IAC3C,oBAAoB;IACpB,4FAA4F;IAC5F,kEAAkE;IAClE,EAAE;IACF,kFAAkF;IAClF,4CAA4C;CAC7C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC"}
|
package/dist/os.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Read an OS value that can throw (notably `process.cwd()` when the working dir was removed), degrading
|
|
2
|
+
* to "" so a caller never crashes on an OS value it may not even need. */
|
|
3
|
+
export declare function safeOsValue(read: () => string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the absolute config-home directory (`$XDG_CONFIG_HOME`, else `~/.config`) with the
|
|
6
|
+
* credential-safety discipline the TRUSTED user-side files require: prefer an ABSOLUTE
|
|
7
|
+
* `$XDG_CONFIG_HOME`, else `~/.config` when the home dir is absolute, else undefined. A relative or
|
|
8
|
+
* blank XDG is IGNORED on purpose — a relative path would resolve against cwd and let a repo-committed
|
|
9
|
+
* file masquerade as user-global config (bypassing per-project rejection). This is the single source of
|
|
10
|
+
* truth for that invariant, shared by the user config loader (`config-file.ts`, `config.toml`) and the
|
|
11
|
+
* directory-binding store (`bindings.ts`, `bindings.json`).
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveXdgConfigHome(env: {
|
|
14
|
+
homedir: string;
|
|
15
|
+
xdgConfigHome: string | undefined;
|
|
16
|
+
}): string | undefined;
|
package/dist/os.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Small OS-value helpers shared across the CLI. Kept out of any feature module so a generic guard has a
|
|
2
|
+
// neutral home (not `config-file.ts`, which owns TOML loading, nor a command module).
|
|
3
|
+
import { isAbsolute, join } from "node:path";
|
|
4
|
+
/** Read an OS value that can throw (notably `process.cwd()` when the working dir was removed), degrading
|
|
5
|
+
* to "" so a caller never crashes on an OS value it may not even need. */
|
|
6
|
+
export function safeOsValue(read) {
|
|
7
|
+
try {
|
|
8
|
+
return read();
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the absolute config-home directory (`$XDG_CONFIG_HOME`, else `~/.config`) with the
|
|
16
|
+
* credential-safety discipline the TRUSTED user-side files require: prefer an ABSOLUTE
|
|
17
|
+
* `$XDG_CONFIG_HOME`, else `~/.config` when the home dir is absolute, else undefined. A relative or
|
|
18
|
+
* blank XDG is IGNORED on purpose — a relative path would resolve against cwd and let a repo-committed
|
|
19
|
+
* file masquerade as user-global config (bypassing per-project rejection). This is the single source of
|
|
20
|
+
* truth for that invariant, shared by the user config loader (`config-file.ts`, `config.toml`) and the
|
|
21
|
+
* directory-binding store (`bindings.ts`, `bindings.json`).
|
|
22
|
+
*/
|
|
23
|
+
export function resolveXdgConfigHome(env) {
|
|
24
|
+
const xdg = env.xdgConfigHome?.trim();
|
|
25
|
+
const home = env.homedir.trim();
|
|
26
|
+
return xdg !== undefined && xdg !== "" && isAbsolute(xdg)
|
|
27
|
+
? xdg
|
|
28
|
+
: home !== "" && isAbsolute(home)
|
|
29
|
+
? join(home, ".config")
|
|
30
|
+
: undefined;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=os.js.map
|
package/dist/os.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"os.js","sourceRoot":"","sources":["../src/os.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,sFAAsF;AAEtF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE7C;2EAC2E;AAC3E,MAAM,UAAU,WAAW,CAAC,IAAkB;IAC5C,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAGpC;IACC,MAAM,GAAG,GAAG,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAChC,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC;QACvD,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,IAAI,KAAK,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC;YAC/B,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;YACvB,CAAC,CAAC,SAAS,CAAC;AAClB,CAAC"}
|
package/dist/url.d.ts
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
1
|
export declare function isHttpUrl(value: string): boolean;
|
|
2
|
+
/** Derive the Hub origin (scheme+host+port) from a base URL, for Hub-scoped keying (cli spec §5.1) —
|
|
3
|
+
* the credential store key `<origin>|<agent id>` and the origin-scoped directory bindings. A single
|
|
4
|
+
* definition shared by the config layer (config.ts, binding-origin resolution) and the auth layer
|
|
5
|
+
* (auth/resolve-token.ts, store keying); housed here so neither layer depends on the other. Falls
|
|
6
|
+
* back to the raw string when the URL can't be parsed (resolveConfig guarantees a valid default, so
|
|
7
|
+
* this is belt-and-suspenders). */
|
|
8
|
+
export declare function originOf(baseUrl: string): string;
|
package/dist/url.js
CHANGED
|
@@ -12,4 +12,18 @@ export function isHttpUrl(value) {
|
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
/** Derive the Hub origin (scheme+host+port) from a base URL, for Hub-scoped keying (cli spec §5.1) —
|
|
16
|
+
* the credential store key `<origin>|<agent id>` and the origin-scoped directory bindings. A single
|
|
17
|
+
* definition shared by the config layer (config.ts, binding-origin resolution) and the auth layer
|
|
18
|
+
* (auth/resolve-token.ts, store keying); housed here so neither layer depends on the other. Falls
|
|
19
|
+
* back to the raw string when the URL can't be parsed (resolveConfig guarantees a valid default, so
|
|
20
|
+
* this is belt-and-suspenders). */
|
|
21
|
+
export function originOf(baseUrl) {
|
|
22
|
+
try {
|
|
23
|
+
return new URL(baseUrl).origin;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return baseUrl;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
15
29
|
//# sourceMappingURL=url.js.map
|
package/dist/url.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,uGAAuG;AACvG,kGAAkG;AAClG,oGAAoG;AACpG,yEAAyE;AACzE,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,QAAQ,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,uGAAuG;AACvG,kGAAkG;AAClG,oGAAoG;AACpG,yEAAyE;AACzE,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,QAAQ,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;oCAKoC;AACpC,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/** The MA2H wire protocol version this CLI targets (docs/specs/cli.md §3). */
|
|
2
2
|
export declare const MA2H_WIRE_VERSION = "v0.3";
|
|
3
3
|
/**
|
|
4
|
-
* The CLI's own version
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The CLI's own version.
|
|
5
|
+
*
|
|
6
|
+
* A standalone binary built by `bun build --compile` (issue #344) has no package.json on the
|
|
7
|
+
* real filesystem to read, so the dist workflow inlines the version at compile time: it sets
|
|
8
|
+
* OH_HAI_BUILD_VERSION in the build env and passes `--env='OH_HAI_BUILD_*'`, which freezes this
|
|
9
|
+
* `process.env.OH_HAI_BUILD_VERSION` read into the bundle as a literal. We prefer that value **only
|
|
10
|
+
* when running as the compiled Bun executable** (`process.versions.bun` is set) — so a stray
|
|
11
|
+
* OH_HAI_BUILD_VERSION in the environment can NOT hijack `--version` on the npm/Node path, which
|
|
12
|
+
* stays exactly as before: fall back to reading the manifest relative to this module. That read
|
|
13
|
+
* works both from `dist/version.js` and `src/version.ts` via tsx — both sit one level under the
|
|
14
|
+
* package root, so `../package.json` resolves to the manifest either way.
|
|
7
15
|
*/
|
|
8
16
|
export declare function cliVersion(): string;
|