@raidiant/notifai 4.0.0 → 6.0.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 (140) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +7 -2
  3. package/dist/client.d.ts +8 -3
  4. package/dist/client.js +24 -3
  5. package/dist/client.js.map +1 -1
  6. package/dist/commands-auth.d.ts +14 -0
  7. package/dist/commands-auth.js +154 -0
  8. package/dist/commands-auth.js.map +1 -0
  9. package/dist/commands-config.d.ts +31 -0
  10. package/dist/commands-config.js +246 -0
  11. package/dist/commands-config.js.map +1 -0
  12. package/dist/commands-core.d.ts +102 -0
  13. package/dist/commands-core.js +135 -0
  14. package/dist/commands-core.js.map +1 -0
  15. package/dist/commands-devices.d.ts +31 -0
  16. package/dist/commands-devices.js +124 -0
  17. package/dist/commands-devices.js.map +1 -0
  18. package/dist/commands-doctor.d.ts +24 -0
  19. package/dist/commands-doctor.js +1011 -0
  20. package/dist/commands-doctor.js.map +1 -0
  21. package/dist/commands-harness-context.d.ts +61 -0
  22. package/dist/commands-harness-context.js +93 -0
  23. package/dist/commands-harness-context.js.map +1 -0
  24. package/dist/commands-hook-shape.d.ts +17 -0
  25. package/dist/commands-hook-shape.js +37 -0
  26. package/dist/commands-hook-shape.js.map +1 -0
  27. package/dist/commands-hooks.d.ts +115 -0
  28. package/dist/commands-hooks.js +1225 -0
  29. package/dist/commands-hooks.js.map +1 -0
  30. package/dist/commands-init.d.ts +35 -0
  31. package/dist/commands-init.js +580 -0
  32. package/dist/commands-init.js.map +1 -0
  33. package/dist/commands-io.d.ts +2 -0
  34. package/dist/commands-io.js +110 -0
  35. package/dist/commands-io.js.map +1 -0
  36. package/dist/commands-logs.d.ts +30 -0
  37. package/dist/commands-logs.js +201 -0
  38. package/dist/commands-logs.js.map +1 -0
  39. package/dist/commands-send-support.d.ts +44 -0
  40. package/dist/commands-send-support.js +180 -0
  41. package/dist/commands-send-support.js.map +1 -0
  42. package/dist/commands-send.d.ts +33 -0
  43. package/dist/commands-send.js +519 -0
  44. package/dist/commands-send.js.map +1 -0
  45. package/dist/commands-setup-proof.d.ts +15 -0
  46. package/dist/commands-setup-proof.js +53 -0
  47. package/dist/commands-setup-proof.js.map +1 -0
  48. package/dist/commands-skill.d.ts +10 -0
  49. package/dist/commands-skill.js +71 -0
  50. package/dist/commands-skill.js.map +1 -0
  51. package/dist/commands.d.ts +12 -378
  52. package/dist/commands.js +12 -4420
  53. package/dist/commands.js.map +1 -1
  54. package/dist/config-schema.js +15 -6
  55. package/dist/config-schema.js.map +1 -1
  56. package/dist/config.d.ts +4 -2
  57. package/dist/config.js +13 -0
  58. package/dist/config.js.map +1 -1
  59. package/dist/credentials.js +13 -3
  60. package/dist/credentials.js.map +1 -1
  61. package/dist/file-lock.d.ts +6 -1
  62. package/dist/file-lock.js +55 -9
  63. package/dist/file-lock.js.map +1 -1
  64. package/dist/harnesses.d.ts +1 -1
  65. package/dist/harnesses.js.map +1 -1
  66. package/dist/hooks.d.ts +74 -7
  67. package/dist/hooks.js +522 -166
  68. package/dist/hooks.js.map +1 -1
  69. package/dist/install-hooks.d.ts +91 -14
  70. package/dist/install-hooks.js +226 -34
  71. package/dist/install-hooks.js.map +1 -1
  72. package/dist/interactive.d.ts +1 -1
  73. package/dist/interactive.js +5 -5
  74. package/dist/interactive.js.map +1 -1
  75. package/dist/logging.d.ts +8 -0
  76. package/dist/logging.js +9 -0
  77. package/dist/logging.js.map +1 -1
  78. package/dist/main.js +45 -18
  79. package/dist/main.js.map +1 -1
  80. package/dist/opencode-plugin.d.ts +8 -0
  81. package/dist/opencode-plugin.js +24 -162
  82. package/dist/opencode-plugin.js.map +1 -1
  83. package/dist/readiness.d.ts +3 -1
  84. package/dist/readiness.js.map +1 -1
  85. package/dist/send.d.ts +6 -0
  86. package/dist/send.js +25 -14
  87. package/dist/send.js.map +1 -1
  88. package/dist/ui/help.d.ts +0 -1
  89. package/dist/ui/help.js +6 -3
  90. package/dist/ui/help.js.map +1 -1
  91. package/dist/ui/theme.d.ts +0 -15
  92. package/dist/ui/theme.js +2 -18
  93. package/dist/ui/theme.js.map +1 -1
  94. package/package.json +2 -2
  95. package/src/client.test.ts +90 -1
  96. package/src/client.ts +35 -2
  97. package/src/commands-auth.ts +174 -0
  98. package/src/commands-config.ts +307 -0
  99. package/src/commands-core.ts +240 -0
  100. package/src/commands-devices.ts +150 -0
  101. package/src/commands-doctor.ts +1209 -0
  102. package/src/commands-harness-context.ts +126 -0
  103. package/src/commands-hook-shape.ts +53 -0
  104. package/src/commands-hooks.ts +1586 -0
  105. package/src/commands-init.ts +721 -0
  106. package/src/commands-io.ts +108 -0
  107. package/src/commands-logs.ts +243 -0
  108. package/src/commands-send-support.ts +224 -0
  109. package/src/commands-send.ts +623 -0
  110. package/src/commands-setup-proof.ts +71 -0
  111. package/src/commands-skill.ts +84 -0
  112. package/src/commands.test.ts +677 -89
  113. package/src/commands.ts +58 -5472
  114. package/src/config-schema.test.ts +1 -1
  115. package/src/config-schema.ts +17 -6
  116. package/src/config.test.ts +50 -9
  117. package/src/config.ts +19 -1
  118. package/src/credentials.test.ts +25 -1
  119. package/src/credentials.ts +13 -3
  120. package/src/file-lock.test.ts +41 -0
  121. package/src/file-lock.ts +59 -9
  122. package/src/harnesses.test.ts +37 -29
  123. package/src/harnesses.ts +1 -4
  124. package/src/hooks.test.ts +703 -26
  125. package/src/hooks.ts +590 -182
  126. package/src/install-hooks.test.ts +232 -12
  127. package/src/install-hooks.ts +241 -37
  128. package/src/interactive.test.ts +19 -1
  129. package/src/interactive.ts +5 -5
  130. package/src/logging-process-worker.test.ts +8 -2
  131. package/src/logging.test.ts +48 -20
  132. package/src/logging.ts +12 -0
  133. package/src/main.ts +58 -24
  134. package/src/opencode-plugin.ts +24 -164
  135. package/src/question-caps.test.ts +49 -0
  136. package/src/readiness.ts +3 -1
  137. package/src/send.ts +32 -16
  138. package/src/skill.test.ts +199 -146
  139. package/src/ui/help.ts +8 -3
  140. package/src/ui/theme.ts +2 -16
@@ -0,0 +1,246 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { parse as parseToml, stringify as stringifyToml } from 'smol-toml';
4
+ import { acceptedValues, configInfo } from './config-schema.js';
5
+ import { BOOLEAN_CONFIG_KEYS, CONFIG_KEYS, NUMERIC_CONFIG_KEYS, configBounds, configDefaultValue, findProjectConfigPath, globalConfigPath, personalProjectConfigPath, sessionConfigPath, } from './config.js';
6
+ import { renderConfigExplain, renderConfigList, renderConfigPlain } from './ui/config-view.js';
7
+ import { EXIT, loadLoggedConfig } from './commands-core.js';
8
+ // ---------------------------------------------------------------------------
9
+ // config show / set / unset
10
+ // ---------------------------------------------------------------------------
11
+ export function configShowCommand(deps, flags) {
12
+ const config = loadLoggedConfig(deps, { cwd: deps.cwd, env: deps.env });
13
+ if (flags.json) {
14
+ const output = Object.fromEntries(CONFIG_KEYS.map((key) => [
15
+ key,
16
+ {
17
+ value: config[key].value,
18
+ source: config[key].source,
19
+ summary: configInfo(key).summary,
20
+ },
21
+ ]));
22
+ deps.io.out(JSON.stringify(output, null, 2));
23
+ return EXIT.ok;
24
+ }
25
+ // Anything that is not a person at a terminal keeps the flat `key = value`
26
+ // form it has always had. Scripts parse this, and a prettier layout for an
27
+ // audience that cannot see it would only be a breaking change.
28
+ if (deps.io.interactive !== true || flags.plain === true) {
29
+ for (const line of renderConfigPlain(config, flags.explain === true))
30
+ deps.io.out(line);
31
+ return EXIT.ok;
32
+ }
33
+ for (const line of renderConfigList(config, { showAdvanced: flags.explain === true })) {
34
+ deps.io.out(line);
35
+ }
36
+ return EXIT.ok;
37
+ }
38
+ /**
39
+ * One setting, explained in full.
40
+ *
41
+ * The gap this closes: `config show` prints a value and provenance but that is
42
+ * not enough to explain the setting's consequences. Every key already had a
43
+ * careful explanation — in a TypeScript comment, read by everyone except the
44
+ * person who needed it.
45
+ */
46
+ export function configExplainCommand(deps, key, flags = {}) {
47
+ if (!CONFIG_KEYS.includes(key)) {
48
+ deps.io.err(`Unknown setting "${key}".`);
49
+ deps.io.err(`Valid settings: ${CONFIG_KEYS.join(', ')}`);
50
+ return EXIT.usage;
51
+ }
52
+ const configKey = key;
53
+ const config = loadLoggedConfig(deps, { cwd: deps.cwd, env: deps.env });
54
+ const info = configInfo(configKey);
55
+ const entry = config[configKey];
56
+ if (flags.json) {
57
+ deps.io.out(JSON.stringify({
58
+ key: configKey,
59
+ label: info.label,
60
+ group: info.group,
61
+ kind: info.kind,
62
+ summary: info.summary,
63
+ detail: info.detail,
64
+ accepts: acceptedValues(configKey),
65
+ ...(info.choices !== undefined ? { choices: info.choices } : {}),
66
+ value: entry.value,
67
+ source: entry.source,
68
+ }, null, 2));
69
+ return EXIT.ok;
70
+ }
71
+ if (deps.io.interactive !== true) {
72
+ deps.io.out(`${configKey} = ${JSON.stringify(entry.value)} [${entry.source}]`);
73
+ deps.io.out(info.detail.replace(/\n\n/g, '\n'));
74
+ deps.io.out(`accepts: ${acceptedValues(configKey)}`);
75
+ return EXIT.ok;
76
+ }
77
+ for (const line of renderConfigExplain(configKey, config))
78
+ deps.io.out(line);
79
+ return EXIT.ok;
80
+ }
81
+ /**
82
+ * Closest config key by edit distance, or null when nothing is close.
83
+ *
84
+ * The threshold matters more than the algorithm: suggesting a key that shares
85
+ * three letters with the typo sends the reader to the wrong setting with
86
+ * confidence, which is worse than listing all fourteen and letting them look.
87
+ */
88
+ function nearestKey(input) {
89
+ let best = null;
90
+ let bestDistance = Number.POSITIVE_INFINITY;
91
+ for (const candidate of CONFIG_KEYS) {
92
+ const distance = editDistance(input.toLowerCase(), candidate);
93
+ if (distance < bestDistance) {
94
+ bestDistance = distance;
95
+ best = candidate;
96
+ }
97
+ }
98
+ return best !== null && bestDistance <= Math.max(2, Math.floor(best.length / 3)) ? best : null;
99
+ }
100
+ function editDistance(a, b) {
101
+ const previous = Array.from({ length: b.length + 1 }, (_, i) => i);
102
+ for (let i = 1; i <= a.length; i += 1) {
103
+ let diagonal = previous[0];
104
+ previous[0] = i;
105
+ for (let j = 1; j <= b.length; j += 1) {
106
+ const above = previous[j];
107
+ previous[j] = Math.min(previous[j] + 1, previous[j - 1] + 1, diagonal + (a[i - 1] === b[j - 1] ? 0 : 1));
108
+ diagonal = above;
109
+ }
110
+ }
111
+ return previous[b.length];
112
+ }
113
+ export async function configSetCommand(deps, key, rawValue, flags) {
114
+ const configKey = configMutationKey(deps, key);
115
+ if (configKey === null)
116
+ return EXIT.usage;
117
+ const info = configInfo(configKey);
118
+ let value = rawValue;
119
+ if (NUMERIC_CONFIG_KEYS.includes(configKey)) {
120
+ const numeric = Number(rawValue);
121
+ if (!Number.isInteger(numeric)) {
122
+ deps.io.err(`${key} takes ${acceptedValues(configKey)}, not "${rawValue}".`);
123
+ return EXIT.usage;
124
+ }
125
+ const bounds = configBounds(configKey);
126
+ if (bounds !== undefined && (numeric < bounds.min || numeric > bounds.max)) {
127
+ deps.io.err(`${key} must be between ${bounds.min} and ${bounds.max}.`);
128
+ return EXIT.usage;
129
+ }
130
+ value = numeric;
131
+ }
132
+ if (BOOLEAN_CONFIG_KEYS.includes(configKey)) {
133
+ if (rawValue !== 'true' && rawValue !== 'false') {
134
+ deps.io.err(`${key} is a toggle — pass "true" or "false", not "${rawValue}".`);
135
+ return EXIT.usage;
136
+ }
137
+ value = rawValue === 'true';
138
+ }
139
+ // Enum keys were accepted unchecked, so `config set sound whatever` wrote a
140
+ // value the sender would later reject — a typo that only surfaces at the
141
+ // moment a notification fails to carry the sound you asked for.
142
+ if (info.kind === 'enum' && info.choices !== undefined && !info.choices.includes(rawValue)) {
143
+ deps.io.err(`${key} takes one of: ${info.choices.join(', ')} — not "${rawValue}".`);
144
+ return EXIT.usage;
145
+ }
146
+ if (key === 'devices')
147
+ value = rawValue.split(',').map((s) => s.trim()).filter(Boolean);
148
+ const target = await configMutationTarget(deps, flags);
149
+ if (target === null)
150
+ return EXIT.usage;
151
+ if (target.layer === 'global' && Object.is(value, configDefaultValue(configKey))) {
152
+ deps.io.err(`${key} is already the shipped default (${JSON.stringify(value)}).`);
153
+ deps.io.err(`Run \`notifai config unset ${key} --yes\` to remove a redundant override instead of creating one.`);
154
+ return EXIT.usage;
155
+ }
156
+ if (!flags.yes) {
157
+ const confirmed = await deps.io.confirm(`Set ${key} = ${JSON.stringify(value)} in ${target.path}?`);
158
+ if (!confirmed) {
159
+ deps.io.err('Not confirmed. Pass --yes to skip the confirmation gate.');
160
+ return EXIT.usage;
161
+ }
162
+ }
163
+ const existing = existsSync(target.path)
164
+ ? parseToml(readFileSync(target.path, 'utf8'))
165
+ : {};
166
+ existing[key] = value;
167
+ mkdirSync(path.dirname(target.path), { recursive: true });
168
+ writeFileSync(target.path, `${stringifyToml(existing)}\n`);
169
+ deps.io.out(`Wrote ${key} to ${target.path}`);
170
+ return EXIT.ok;
171
+ }
172
+ function configMutationKey(deps, key) {
173
+ if (!CONFIG_KEYS.includes(key)) {
174
+ deps.io.err(`Unknown setting "${key}".`);
175
+ const near = nearestKey(key);
176
+ if (near !== null)
177
+ deps.io.err(`Did you mean "${near}"?`);
178
+ deps.io.err(`Valid settings: ${CONFIG_KEYS.join(', ')}`);
179
+ deps.io.err('Run `notifai config explain <key>` to see what one of them does.');
180
+ return null;
181
+ }
182
+ return key;
183
+ }
184
+ async function configMutationTarget(deps, flags) {
185
+ let layer = flags.local ? 'local' : flags.project ? 'project' : 'global';
186
+ if (flags.session === undefined &&
187
+ flags.local !== true &&
188
+ flags.project !== true &&
189
+ flags.yes !== true &&
190
+ deps.io.interactive === true &&
191
+ deps.io.select) {
192
+ const selected = await deps.io.select('Where should this setting live?', [
193
+ { value: 'global', label: 'This machine', hint: 'applies across projects' },
194
+ { value: 'project', label: 'This project (shared)', hint: '.notifai/config.toml' },
195
+ { value: 'local', label: 'This project (personal)', hint: 'stored on this machine, not in the repo' },
196
+ ]);
197
+ if (selected === null) {
198
+ deps.io.err('No configuration layer selected.');
199
+ return null;
200
+ }
201
+ layer = selected;
202
+ }
203
+ const targetPath = flags.session
204
+ ? sessionConfigPath(flags.session, deps.env)
205
+ : layer === 'local'
206
+ ? personalProjectConfigPath(deps.cwd, deps.env)
207
+ : layer === 'project'
208
+ ? (findProjectConfigPath(deps.cwd) ?? path.join(deps.cwd, '.notifai', 'config.toml'))
209
+ : globalConfigPath(deps.env);
210
+ return {
211
+ path: targetPath,
212
+ layer: flags.session ? 'session' : layer,
213
+ };
214
+ }
215
+ export async function configUnsetCommand(deps, key, flags) {
216
+ const configKey = configMutationKey(deps, key);
217
+ if (configKey === null)
218
+ return EXIT.usage;
219
+ const target = await configMutationTarget(deps, flags);
220
+ if (target === null)
221
+ return EXIT.usage;
222
+ const existing = existsSync(target.path)
223
+ ? parseToml(readFileSync(target.path, 'utf8'))
224
+ : {};
225
+ if (!Object.prototype.hasOwnProperty.call(existing, configKey)) {
226
+ deps.io.out(`${configKey} is not set in ${target.path}`);
227
+ return EXIT.ok;
228
+ }
229
+ if (!flags.yes) {
230
+ const confirmed = await deps.io.confirm(`Remove ${configKey} from ${target.path}?`);
231
+ if (!confirmed) {
232
+ deps.io.err('Not confirmed. Pass --yes to skip the confirmation gate.');
233
+ return EXIT.usage;
234
+ }
235
+ }
236
+ delete existing[configKey];
237
+ if (Object.keys(existing).length === 0) {
238
+ rmSync(target.path, { force: true });
239
+ }
240
+ else {
241
+ writeFileSync(target.path, `${stringifyToml(existing)}\n`);
242
+ }
243
+ deps.io.out(`Removed ${configKey} from ${target.path}; the inherited value now applies.`);
244
+ return EXIT.ok;
245
+ }
246
+ //# sourceMappingURL=commands-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands-config.js","sourceRoot":"","sources":["../src/commands-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { type ClaudeWakeAdapters } from './claude-wake.js';
2
+ import { type ApiClient, type ClientOptions } from './client.js';
3
+ import { type CodexWakeAdapters } from './codex-wake.js';
4
+ import { loadConfig, type CliConfig } from './config.js';
5
+ import type { CredentialStore, MachineCredential } from './credentials.js';
6
+ import { type HookAdapterTarget } from './hook-adapter.js';
7
+ import { type Logger } from './logging.js';
8
+ import type { NativeSkills } from './native-skills.js';
9
+ import type { Tone } from './ui/theme.js';
10
+ export interface CommandIo {
11
+ out(line: string): void;
12
+ err(line: string): void;
13
+ /** Interactive confirmation; resolves `fallback` (default false) when not interactive. */
14
+ confirm(question: string, fallback?: boolean): Promise<boolean>;
15
+ openUrl(url: string): void;
16
+ /**
17
+ * True only when a human is demonstrably driving a terminal. Everything below
18
+ * is optional sugar that MUST only be called behind this flag: an agent that
19
+ * reaches an interactive prompt does not error, it hangs — the prompt
20
+ * libraries wait on stdin for ever — so the gate is bypass, not handling.
21
+ * Test fakes leave all of this undefined and exercise the plain paths.
22
+ */
23
+ interactive?: boolean;
24
+ select?(message: string, options: {
25
+ value: string;
26
+ label: string;
27
+ hint?: string;
28
+ }[]): Promise<string | null>;
29
+ /** Interactive multi-select. `initial` are pre-selected values. */
30
+ multiselect?(message: string, options: {
31
+ value: string;
32
+ label: string;
33
+ hint?: string;
34
+ }[], initial?: string[]): Promise<string[] | null>;
35
+ intro?(title: string): Promise<void>;
36
+ outro?(message: string): Promise<void>;
37
+ note?(message: string, title?: string): Promise<void>;
38
+ spinner?(message: string): Promise<CommandSpinner | null>;
39
+ /**
40
+ * A report line. `tone` distinguishes the two states that are neither pass
41
+ * nor fail — something optional the user declined, and something that was
42
+ * never evaluated — which a boolean has to round to one or the other.
43
+ * Optional so existing implementations keep type-checking.
44
+ */
45
+ check?(ok: boolean, message: string, tone?: Tone): Promise<void>;
46
+ }
47
+ export interface CommandSpinner {
48
+ message(message: string): void;
49
+ stop(message: string): void;
50
+ error(message: string): void;
51
+ }
52
+ export interface CommandDeps {
53
+ io: CommandIo;
54
+ store: CredentialStore;
55
+ env: NodeJS.ProcessEnv;
56
+ cwd: string;
57
+ /** Test seam; production fixes the hook adapter under os.homedir(). */
58
+ hookAdapterHome?: string;
59
+ /** Test seam; production uses this process's Node and CLI paths. */
60
+ hookInstallTarget?: HookAdapterTarget;
61
+ /** Test seam; production uses process.platform for adapter format and quoting. */
62
+ hookPlatform?: NodeJS.Platform;
63
+ /** Test seam; production uses fetch against base_url. */
64
+ clientFactory?: (baseUrl: string, bearer: string | null, options?: ClientOptions) => ApiClient;
65
+ /** Test seam for bounded polling without wall-clock sleeps. */
66
+ now?: () => number;
67
+ /** Test seam for retry/backoff timing. */
68
+ sleep?: (milliseconds: number) => Promise<void>;
69
+ /** Test seams for Claude liveness, socket delivery, and cold resume. */
70
+ claudeWake?: ClaudeWakeAdapters;
71
+ claudeSourcePid?: number;
72
+ /** Test seams for the Codex thread-writer probe and cold resume. */
73
+ codexWake?: CodexWakeAdapters;
74
+ codexSourcePid?: number;
75
+ /** Test seam and production adapter for the external native skills installer. */
76
+ nativeSkills?: NativeSkills;
77
+ /**
78
+ * The local record of what this invocation did. Optional so a test fake need
79
+ * not carry one; `log(deps)` supplies a logger that records nothing.
80
+ */
81
+ logger?: Logger;
82
+ }
83
+ /** The invocation's logger, or one that discards everything. */
84
+ export declare function log(deps: CommandDeps): Logger;
85
+ export declare function loadLoggedConfig(deps: CommandDeps, options: Parameters<typeof loadConfig>[0]): CliConfig;
86
+ export declare const EXIT: {
87
+ readonly ok: 0;
88
+ readonly failed: 1;
89
+ readonly usage: 2;
90
+ readonly noReply: 3;
91
+ readonly auth: 4;
92
+ readonly network: 5;
93
+ };
94
+ export declare function makeClient(deps: CommandDeps, baseUrl: string, bearer: string | null, options?: ClientOptions): ApiClient;
95
+ export declare function resolvedBaseUrl(config: CliConfig, credential: MachineCredential | null): string;
96
+ export declare function authedClient(deps: CommandDeps, config: CliConfig): {
97
+ client: ApiClient;
98
+ baseUrl: string;
99
+ } | null;
100
+ export declare const UPDATE_CLI_COMMAND = "npm install -g @raidiant/notifai";
101
+ export declare function reportError(deps: CommandDeps, err: unknown, context?: Record<string, unknown>): number;
102
+ export declare function rejectedPaths(details: unknown): string[];
@@ -0,0 +1,135 @@
1
+ import { SHIPPED_CLI_CAPABILITIES } from '@raidiant/notifai-protocol';
2
+ import {} from './claude-wake.js';
3
+ import { ApiCallError, NetworkError, createClient, } from './client.js';
4
+ import {} from './codex-wake.js';
5
+ import { loadConfig } from './config.js';
6
+ import {} from './hook-adapter.js';
7
+ import { logConfigResolved, logSettingsFrom, nullLogger } from './logging.js';
8
+ import { packageVersion } from './release.js';
9
+ /** The invocation's logger, or one that discards everything. */
10
+ export function log(deps) {
11
+ return deps.logger ?? nullLogger();
12
+ }
13
+ export function loadLoggedConfig(deps, options) {
14
+ const config = loadConfig(options);
15
+ const logger = log(deps);
16
+ logger.adopt(logSettingsFrom(config));
17
+ logger.bind({ project: config.project.value });
18
+ logConfigResolved(logger, config);
19
+ return config;
20
+ }
21
+ export const EXIT = {
22
+ ok: 0,
23
+ failed: 1,
24
+ usage: 2,
25
+ noReply: 3,
26
+ auth: 4,
27
+ network: 5,
28
+ };
29
+ export function makeClient(deps, baseUrl, bearer, options) {
30
+ return (deps.clientFactory ?? createClient)(baseUrl, bearer, {
31
+ ...options,
32
+ logger: log(deps),
33
+ cliVersion: packageVersion(),
34
+ capabilities: SHIPPED_CLI_CAPABILITIES,
35
+ });
36
+ }
37
+ export function resolvedBaseUrl(config, credential) {
38
+ return config.base_url.source === 'default' && credential ? credential.baseUrl : config.base_url.value;
39
+ }
40
+ export function authedClient(deps, config) {
41
+ const credential = deps.store.load();
42
+ if (!credential) {
43
+ // The commonest reason a command does nothing, and one that leaves no other
44
+ // trace: it returns before any request is made, so without this the log
45
+ // shows an exit code and no cause.
46
+ log(deps).error('cli.error', { kind: 'auth', message: 'not signed in', store: deps.store.describe() });
47
+ deps.io.err('Not signed in. Run `notifai login` first.');
48
+ return null;
49
+ }
50
+ const baseUrl = resolvedBaseUrl(config, credential);
51
+ return {
52
+ client: makeClient(deps, baseUrl, `Bearer nfm_${credential.machineId}.${credential.secret}`),
53
+ baseUrl,
54
+ };
55
+ }
56
+ export const UPDATE_CLI_COMMAND = 'npm install -g @raidiant/notifai';
57
+ function localRecovery(action) {
58
+ switch (action) {
59
+ case 'update_cli':
60
+ return `next: ${UPDATE_CLI_COMMAND}`;
61
+ case 'update_companion':
62
+ return 'next: Update Notifai on the named device.';
63
+ case 'wait_for_service':
64
+ return 'next: The service is being updated; try again later.';
65
+ default:
66
+ return null;
67
+ }
68
+ }
69
+ export function reportError(deps, err, context = {}) {
70
+ // Recorded before it is printed: stderr from an agent's shell call is often
71
+ // the one thing that does not survive into the next turn, and this is exactly
72
+ // the line someone comes back looking for.
73
+ log(deps).error('cli.error', {
74
+ ...context,
75
+ ...(err instanceof ApiCallError
76
+ ? {
77
+ kind: 'api',
78
+ status: err.status,
79
+ code: err.code,
80
+ message: err.message,
81
+ next_action: err.nextAction,
82
+ recovery_action: err.recoveryAction,
83
+ details: err.details,
84
+ }
85
+ : err instanceof NetworkError
86
+ ? { kind: 'network', message: err.message }
87
+ : { kind: 'unknown', message: String(err) }),
88
+ });
89
+ if (err instanceof ApiCallError) {
90
+ deps.io.err(deps.io.interactive === true && err.recoveryAction !== null
91
+ ? err.message
92
+ : `${err.code}: ${err.message}`);
93
+ // The server's field-level details were already being logged above, but
94
+ // stderr is the one surface an agent's next turn actually reads — so the
95
+ // diagnosis has to be on it, the same way the hook path prints it.
96
+ const paths = rejectedPaths(err.details);
97
+ if (paths.length > 0)
98
+ deps.io.err(`the server rejected: ${paths.join(', ')}`);
99
+ // A 422 on a request this CLI built is not a user error: the two sides
100
+ // disagree about the contract, in whichever direction. `doctor` says which.
101
+ // Codes that name a policy the account chose are the exception — the
102
+ // contract held, the body simply did not satisfy that account.
103
+ if (err.status === 422 &&
104
+ err.code !== 'acknowledgement_text_required' &&
105
+ err.code !== 'feature_unavailable') {
106
+ deps.io.err('this build sent a field the server did not accept — the CLI and server ' +
107
+ 'disagree about the contract; check with `notifai doctor`');
108
+ }
109
+ const recovery = localRecovery(err.recoveryAction);
110
+ if (recovery !== null)
111
+ deps.io.err(recovery);
112
+ else if (err.recoveryAction === null && err.nextAction)
113
+ deps.io.err(`next: ${err.nextAction}`);
114
+ if (err.code === 'auth_required' || err.code === 'machine_revoked')
115
+ return EXIT.auth;
116
+ return err.status >= 500 ? EXIT.network : EXIT.failed;
117
+ }
118
+ if (err instanceof NetworkError) {
119
+ deps.io.err(err.message);
120
+ return EXIT.network;
121
+ }
122
+ deps.io.err(String(err));
123
+ return EXIT.failed;
124
+ }
125
+ export function rejectedPaths(details) {
126
+ if (!Array.isArray(details))
127
+ return [];
128
+ return details
129
+ .map((issue) => typeof issue === 'object' && issue !== null && typeof issue.path === 'string'
130
+ ? issue.path
131
+ : null)
132
+ .filter((path) => path !== null && path !== '')
133
+ .slice(0, 5);
134
+ }
135
+ //# sourceMappingURL=commands-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands-core.js","sourceRoot":"","sources":["../src/commands-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type Platform, type RoutableDevice } from '@raidiant/notifai-protocol';
2
+ import { type CommandDeps } from './commands-core.js';
3
+ export declare function devicesCommand(deps: CommandDeps, flags: {
4
+ json?: boolean;
5
+ }): Promise<number>;
6
+ /**
7
+ * Devices as data, for surfaces that render them themselves.
8
+ *
9
+ * `devicesCommand` prints and returns an exit code, which is the right shape
10
+ * for a command and the wrong one for a menu that wants to show names beside
11
+ * checkboxes. Silent on every failure by design: the interactive app already
12
+ * shows the credential and connectivity state on its status card, so a second
13
+ * error line here would be reporting the same fault twice.
14
+ */
15
+ export declare function deviceInventory(deps: CommandDeps): Promise<RoutableDevice[] | null>;
16
+ /** Whether a device is in a state where a notification would actually arrive. */
17
+ export declare function canDeviceReceive(device: RoutableDevice): boolean;
18
+ export declare function capabilitiesCommand(deps: CommandDeps, flags: {
19
+ json?: boolean;
20
+ platform?: Platform;
21
+ }): Promise<number>;
22
+ export declare function supportPageUrl(baseUrl: string): string;
23
+ /** Same-account line for the device hop; prefers the real email when known. */
24
+ export declare function sameAccountSignInLine(email: string | null | undefined): string;
25
+ export declare function deviceInstallRemedy(options: {
26
+ baseUrl: string;
27
+ email: string | null;
28
+ devices: readonly RoutableDevice[];
29
+ }): string;
30
+ export declare function deviceCanReceive(device: RoutableDevice): boolean;
31
+ export declare function readyIosDevices(devices: readonly RoutableDevice[]): RoutableDevice[];