@raidiant/notifai 9.3.0 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +1 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -1
- package/dist/commands-agent-sessions.d.ts +6 -0
- package/dist/commands-agent-sessions.js +51 -0
- package/dist/commands-agent-sessions.js.map +1 -0
- package/dist/commands-auth.js +4 -4
- package/dist/commands-auth.js.map +1 -1
- package/dist/commands-config.js +11 -4
- package/dist/commands-config.js.map +1 -1
- package/dist/commands-core.d.ts +5 -0
- package/dist/commands-core.js +2 -0
- package/dist/commands-core.js.map +1 -1
- package/dist/commands-doctor.js +121 -40
- package/dist/commands-doctor.js.map +1 -1
- package/dist/commands-harness-context.d.ts +15 -2
- package/dist/commands-harness-context.js +40 -1
- package/dist/commands-harness-context.js.map +1 -1
- package/dist/commands-hooks.d.ts +4 -3
- package/dist/commands-hooks.js +139 -16
- package/dist/commands-hooks.js.map +1 -1
- package/dist/commands-init.js +10 -5
- package/dist/commands-init.js.map +1 -1
- package/dist/commands-send-support.js +18 -1
- package/dist/commands-send-support.js.map +1 -1
- package/dist/commands-send.js +2 -2
- package/dist/commands-send.js.map +1 -1
- package/dist/commands-sounds.d.ts +12 -0
- package/dist/commands-sounds.js +35 -0
- package/dist/commands-sounds.js.map +1 -0
- package/dist/commands.d.ts +2 -0
- package/dist/commands.js +2 -0
- package/dist/commands.js.map +1 -1
- package/dist/config-schema.js +5 -2
- package/dist/config-schema.js.map +1 -1
- package/dist/config.d.ts +3 -4
- package/dist/config.js +5 -2
- package/dist/config.js.map +1 -1
- package/dist/credentials.js +4 -1
- package/dist/credentials.js.map +1 -1
- package/dist/harnesses.d.ts +49 -7
- package/dist/harnesses.js +110 -24
- package/dist/harnesses.js.map +1 -1
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +2 -2
- package/dist/hooks.js.map +1 -1
- package/dist/install-hooks.d.ts +10 -11
- package/dist/install-hooks.js +18 -13
- package/dist/install-hooks.js.map +1 -1
- package/dist/interactive.js +20 -23
- package/dist/interactive.js.map +1 -1
- package/dist/invocation-context.d.ts +2 -2
- package/dist/openclaw-plugin.d.ts +49 -0
- package/dist/openclaw-plugin.js +350 -0
- package/dist/openclaw-plugin.js.map +1 -0
- package/dist/orca-session-title.d.ts +10 -0
- package/dist/orca-session-title.js +98 -0
- package/dist/orca-session-title.js.map +1 -0
- package/dist/program.d.ts +3 -1
- package/dist/program.js +37 -13
- package/dist/program.js.map +1 -1
- package/dist/send.js +11 -14
- package/dist/send.js.map +1 -1
- package/dist/session-activation.js +1 -1
- package/dist/session-activation.js.map +1 -1
- package/dist/session-labels.d.ts +18 -2
- package/dist/session-labels.js +79 -8
- package/dist/session-labels.js.map +1 -1
- package/dist/sound-ref.d.ts +23 -0
- package/dist/sound-ref.js +28 -0
- package/dist/sound-ref.js.map +1 -0
- package/dist/ui/help.d.ts +4 -5
- package/dist/ui/help.js +5 -6
- package/dist/ui/help.js.map +1 -1
- package/package.json +3 -3
- package/src/client.test.ts +12 -0
- package/src/client.ts +8 -0
- package/src/commands-agent-sessions.ts +72 -0
- package/src/commands-auth.ts +4 -3
- package/src/commands-config.ts +10 -4
- package/src/commands-core.ts +6 -0
- package/src/commands-doctor.ts +143 -38
- package/src/commands-harness-context.ts +56 -2
- package/src/commands-hooks.ts +180 -20
- package/src/commands-init.ts +10 -4
- package/src/commands-send-support.ts +23 -1
- package/src/commands-send.ts +2 -2
- package/src/commands-sounds.test.ts +106 -0
- package/src/commands-sounds.ts +49 -0
- package/src/commands.test.ts +529 -17
- package/src/commands.ts +5 -0
- package/src/config-schema.test.ts +1 -0
- package/src/config-schema.ts +5 -2
- package/src/config.test.ts +42 -20
- package/src/config.ts +6 -5
- package/src/credentials.test.ts +20 -0
- package/src/credentials.ts +4 -1
- package/src/fixtures/hermes-0.20.6-classic-cli-local.json +50 -0
- package/src/fixtures/openclaw-2026.7.1-2-agent-local.json +57 -0
- package/src/harness-integration.test.ts +294 -0
- package/src/harnesses.test.ts +115 -8
- package/src/harnesses.ts +133 -30
- package/src/hooks.test.ts +4 -3
- package/src/hooks.ts +4 -4
- package/src/install-hooks.test.ts +213 -4
- package/src/install-hooks.ts +38 -30
- package/src/interactive.test.ts +31 -0
- package/src/interactive.ts +20 -26
- package/src/invocation-context.ts +2 -2
- package/src/openclaw-plugin.ts +409 -0
- package/src/orca-session-title.test.ts +54 -0
- package/src/orca-session-title.ts +103 -0
- package/src/program.test.ts +27 -0
- package/src/program.ts +47 -12
- package/src/send.ts +10 -19
- package/src/session-activation.ts +1 -1
- package/src/session-labels.test.ts +58 -9
- package/src/session-labels.ts +95 -12
- package/src/skill.test.ts +14 -3
- package/src/sound-ref.test.ts +31 -0
- package/src/sound-ref.ts +34 -0
- package/src/ui/config-view.test.ts +1 -0
- package/src/ui/help.test.ts +16 -0
- package/src/ui/help.ts +6 -7
package/src/install-hooks.ts
CHANGED
|
@@ -20,15 +20,19 @@ import {
|
|
|
20
20
|
type HookHostPlatform,
|
|
21
21
|
} from './hook-adapter.js'
|
|
22
22
|
import { opencodePluginPath, opencodePluginTarget } from './opencode-plugin.js'
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
OPENCLAW_EVENTS,
|
|
25
|
+
openclawHasGlobalEvidence,
|
|
26
|
+
openclawPluginPath,
|
|
27
|
+
openclawPluginTarget,
|
|
28
|
+
} from './openclaw-plugin.js'
|
|
29
|
+
import { HOOK_INSTALLABLE_HARNESSES, type HookInstallableHarness } from './harnesses.js'
|
|
24
30
|
import { accountHome } from './platform.js'
|
|
25
31
|
import {
|
|
26
32
|
NON_ROUTING_STOP_TIMEOUT_SECONDS,
|
|
27
33
|
QUESTION_STOP_TIMEOUT_SECONDS,
|
|
28
34
|
} from './question-timing.js'
|
|
29
35
|
|
|
30
|
-
export { HARNESSES, type Harness } from './harnesses.js'
|
|
31
|
-
|
|
32
36
|
/**
|
|
33
37
|
* The three joints the OpenCode plugin hooks into, as (harness event, the
|
|
34
38
|
* `notifai hook` event it runs). The plugin is a module and has no settings
|
|
@@ -73,7 +77,7 @@ export interface HookGroup {
|
|
|
73
77
|
export type HookConfig = Record<string, HookGroup[]>
|
|
74
78
|
|
|
75
79
|
export interface InstallPlan {
|
|
76
|
-
harness:
|
|
80
|
+
harness: HookInstallableHarness
|
|
77
81
|
/** Absolute path of the settings file that will be written. */
|
|
78
82
|
file: string
|
|
79
83
|
/** True when the file is machine-wide rather than per-project. */
|
|
@@ -97,7 +101,7 @@ export interface HookCommandOptions {
|
|
|
97
101
|
export function hookCommand(
|
|
98
102
|
adapterPath: string,
|
|
99
103
|
event: string,
|
|
100
|
-
harness?:
|
|
104
|
+
harness?: HookInstallableHarness,
|
|
101
105
|
options: HookCommandOptions = {},
|
|
102
106
|
): string {
|
|
103
107
|
return (
|
|
@@ -174,7 +178,7 @@ export interface BuildOptions {
|
|
|
174
178
|
/** Stable user-level executable installed by the hook adapter module. */
|
|
175
179
|
adapterPath: string
|
|
176
180
|
/** The installed adapter stamps its exact harness into project pointers. */
|
|
177
|
-
harness?:
|
|
181
|
+
harness?: HookInstallableHarness
|
|
178
182
|
platform?: NodeJS.Platform | HookHostPlatform
|
|
179
183
|
/** Registered Node named first in Windows hook commands. */
|
|
180
184
|
nodePath?: string
|
|
@@ -195,7 +199,7 @@ export { QUESTION_STOP_TIMEOUT_SECONDS } from './question-timing.js'
|
|
|
195
199
|
* `question-timing.ts`.
|
|
196
200
|
*/
|
|
197
201
|
export function stopHandlerIsDetached(
|
|
198
|
-
harness:
|
|
202
|
+
harness: HookInstallableHarness | undefined,
|
|
199
203
|
platform?: Parameters<typeof hookHostPlatform>[0],
|
|
200
204
|
): boolean {
|
|
201
205
|
return harness === 'claude-code' && hookHostPlatform(platform) === 'posix'
|
|
@@ -213,7 +217,7 @@ export function stopHandlerIsDetached(
|
|
|
213
217
|
*/
|
|
214
218
|
function stopHandler(
|
|
215
219
|
adapterPath: string,
|
|
216
|
-
harness:
|
|
220
|
+
harness: HookInstallableHarness | undefined,
|
|
217
221
|
options: HookCommandOptions,
|
|
218
222
|
): HookHandler {
|
|
219
223
|
const command = hookCommand(adapterPath, 'stop', harness, options)
|
|
@@ -355,7 +359,7 @@ export function buildCursorHookConfig(options: BuildOptions): CursorHookConfig {
|
|
|
355
359
|
* questions pushed to is not a property of the repository.
|
|
356
360
|
*/
|
|
357
361
|
export function settingsFile(
|
|
358
|
-
harness:
|
|
362
|
+
harness: HookInstallableHarness,
|
|
359
363
|
global: boolean,
|
|
360
364
|
cwd: string,
|
|
361
365
|
env: NodeJS.ProcessEnv = process.env,
|
|
@@ -366,6 +370,8 @@ export function settingsFile(
|
|
|
366
370
|
// generated plugin module, so it owns a whole file instead.
|
|
367
371
|
case 'opencode':
|
|
368
372
|
return opencodePluginPath(global, cwd, env, platform)
|
|
373
|
+
case 'openclaw':
|
|
374
|
+
return openclawPluginPath(global, cwd, env, platform)
|
|
369
375
|
case 'cursor': {
|
|
370
376
|
const home = harnessAccountHome(env, platform)
|
|
371
377
|
return global
|
|
@@ -606,7 +612,7 @@ export function withCodexLayerTransaction<T>(
|
|
|
606
612
|
|
|
607
613
|
/** Every file in this layer Codex might already be reading hooks from. */
|
|
608
614
|
export function hookDefinitionFiles(
|
|
609
|
-
harness:
|
|
615
|
+
harness: HookInstallableHarness,
|
|
610
616
|
global: boolean,
|
|
611
617
|
cwd: string,
|
|
612
618
|
env: NodeJS.ProcessEnv = process.env,
|
|
@@ -741,14 +747,15 @@ function ourHandlerEvents(document: SettingsDocument | null): string[] {
|
|
|
741
747
|
* document. Treating it as evidence of any one harness would be a guess
|
|
742
748
|
* dressed up as detection.
|
|
743
749
|
*/
|
|
744
|
-
function localHarnessEvidence(cwd: string):
|
|
745
|
-
const found:
|
|
750
|
+
function localHarnessEvidence(cwd: string): HookInstallableHarness[] {
|
|
751
|
+
const found: HookInstallableHarness[] = []
|
|
746
752
|
if (existsSync(path.join(cwd, '.claude')) || existsSync(path.join(cwd, 'CLAUDE.md'))) {
|
|
747
753
|
found.push('claude-code')
|
|
748
754
|
}
|
|
749
755
|
if (existsSync(path.join(cwd, '.codex'))) found.push('codex')
|
|
750
756
|
if (existsSync(path.join(cwd, '.cursor'))) found.push('cursor')
|
|
751
757
|
if (existsSync(path.join(cwd, '.opencode'))) found.push('opencode')
|
|
758
|
+
if (existsSync(path.join(cwd, '.openclaw'))) found.push('openclaw')
|
|
752
759
|
return found
|
|
753
760
|
}
|
|
754
761
|
|
|
@@ -756,13 +763,14 @@ function localHarnessEvidence(cwd: string): Harness[] {
|
|
|
756
763
|
function globalHarnessEvidence(
|
|
757
764
|
env: NodeJS.ProcessEnv = process.env,
|
|
758
765
|
platform: NodeJS.Platform | HookHostPlatform = process.platform,
|
|
759
|
-
):
|
|
766
|
+
): HookInstallableHarness[] {
|
|
760
767
|
const home = harnessAccountHome(env, platform)
|
|
761
|
-
const found:
|
|
768
|
+
const found: HookInstallableHarness[] = []
|
|
762
769
|
if (existsSync(path.join(home, '.claude'))) found.push('claude-code')
|
|
763
770
|
if (existsSync(codexGlobalDir(env, platform))) found.push('codex')
|
|
764
771
|
if (existsSync(path.join(home, '.cursor'))) found.push('cursor')
|
|
765
772
|
if (existsSync(path.join(home, '.config', 'opencode'))) found.push('opencode')
|
|
773
|
+
if (openclawHasGlobalEvidence(existsSync, env, platform)) found.push('openclaw')
|
|
766
774
|
return found
|
|
767
775
|
}
|
|
768
776
|
|
|
@@ -777,12 +785,12 @@ export function detectedHarnesses(
|
|
|
777
785
|
cwd: string,
|
|
778
786
|
env: NodeJS.ProcessEnv = process.env,
|
|
779
787
|
platform: NodeJS.Platform | HookHostPlatform = process.platform,
|
|
780
|
-
):
|
|
781
|
-
const seen = new Set<
|
|
788
|
+
): HookInstallableHarness[] {
|
|
789
|
+
const seen = new Set<HookInstallableHarness>([
|
|
782
790
|
...localHarnessEvidence(cwd),
|
|
783
791
|
...globalHarnessEvidence(env, platform),
|
|
784
792
|
])
|
|
785
|
-
return
|
|
793
|
+
return HOOK_INSTALLABLE_HARNESSES.filter((harness) => seen.has(harness))
|
|
786
794
|
}
|
|
787
795
|
|
|
788
796
|
/**
|
|
@@ -798,7 +806,7 @@ export function detectHarness(
|
|
|
798
806
|
cwd: string,
|
|
799
807
|
env: NodeJS.ProcessEnv = process.env,
|
|
800
808
|
platform: NodeJS.Platform | HookHostPlatform = process.platform,
|
|
801
|
-
):
|
|
809
|
+
): HookInstallableHarness | null {
|
|
802
810
|
const local = localHarnessEvidence(cwd)
|
|
803
811
|
if (local.length > 0) return local.length === 1 ? local[0]! : null
|
|
804
812
|
const global = globalHarnessEvidence(env, platform)
|
|
@@ -1193,7 +1201,7 @@ export interface InstalledHandler {
|
|
|
1193
1201
|
}
|
|
1194
1202
|
|
|
1195
1203
|
export interface Installation {
|
|
1196
|
-
harness:
|
|
1204
|
+
harness: HookInstallableHarness
|
|
1197
1205
|
file: string
|
|
1198
1206
|
global: boolean
|
|
1199
1207
|
handlers: InstalledHandler[]
|
|
@@ -1331,7 +1339,7 @@ export function findInstallations(
|
|
|
1331
1339
|
...(nodePath === undefined ? {} : { nodePath }),
|
|
1332
1340
|
}
|
|
1333
1341
|
const found: Installation[] = []
|
|
1334
|
-
for (const harness of
|
|
1342
|
+
for (const harness of HOOK_INSTALLABLE_HARNESSES) {
|
|
1335
1343
|
for (const global of [false, true]) {
|
|
1336
1344
|
const files = hookDefinitionFiles(harness, global, cwd, env, platform)
|
|
1337
1345
|
for (const file of files) {
|
|
@@ -1339,38 +1347,38 @@ export function findInstallations(
|
|
|
1339
1347
|
// OpenCode's adapter is a plugin module, not a settings document, so it
|
|
1340
1348
|
// is reported as one installation covering all three events rather than
|
|
1341
1349
|
// parsed for handlers.
|
|
1342
|
-
if (harness === 'opencode') {
|
|
1350
|
+
if (harness === 'opencode' || harness === 'openclaw') {
|
|
1343
1351
|
let source: string
|
|
1344
1352
|
try {
|
|
1345
1353
|
source = readOwnedRegularFile(file)
|
|
1346
1354
|
} catch {
|
|
1347
1355
|
continue
|
|
1348
1356
|
}
|
|
1349
|
-
const target =
|
|
1357
|
+
const target =
|
|
1358
|
+
harness === 'openclaw' ? openclawPluginTarget(source) : opencodePluginTarget(source)
|
|
1350
1359
|
if (target === null) continue
|
|
1360
|
+
const label = harness === 'openclaw' ? 'OpenClaw' : 'OpenCode'
|
|
1351
1361
|
const problems = [
|
|
1352
1362
|
...(!target.current
|
|
1353
|
-
? [
|
|
1363
|
+
? [`obsolete ${label} event wiring; rerun \`notifai hooks install --harness ${harness}\``]
|
|
1354
1364
|
: []),
|
|
1355
1365
|
...(target.adapter !== hookAdapterPath(adapterHome)
|
|
1356
1366
|
? [
|
|
1357
|
-
|
|
1367
|
+
`${label} still names a mutable CLI or runtime path; rerun \`notifai hooks install --harness ${harness}\``,
|
|
1358
1368
|
]
|
|
1359
1369
|
: []),
|
|
1360
1370
|
]
|
|
1371
|
+
const events = harness === 'openclaw' ? OPENCLAW_EVENTS : OPENCODE_EVENTS
|
|
1361
1372
|
found.push({
|
|
1362
1373
|
harness,
|
|
1363
1374
|
file,
|
|
1364
1375
|
global,
|
|
1365
1376
|
...(problems.length > 0 ? { problems } : {}),
|
|
1366
|
-
|
|
1367
|
-
// the plugin's own path: every check downstream asks which build a
|
|
1368
|
-
// handler invokes, and for a module that answer lives inside it.
|
|
1369
|
-
handlers: OPENCODE_EVENTS.map(([event, hookEvent]) => ({
|
|
1377
|
+
handlers: events.map(([event, hookEvent]) => ({
|
|
1370
1378
|
event,
|
|
1371
1379
|
groupIndex: 0,
|
|
1372
1380
|
handlerIndex: 0,
|
|
1373
|
-
command: hookCommand(target.adapter, hookEvent,
|
|
1381
|
+
command: hookCommand(target.adapter, hookEvent, harness, {
|
|
1374
1382
|
...commandOptions,
|
|
1375
1383
|
...(target.nodePath === undefined ? {} : { nodePath: target.nodePath }),
|
|
1376
1384
|
}),
|
|
@@ -1411,7 +1419,7 @@ export function findInstallations(
|
|
|
1411
1419
|
}
|
|
1412
1420
|
|
|
1413
1421
|
function harnessMarkerProblems(
|
|
1414
|
-
harness:
|
|
1422
|
+
harness: HookInstallableHarness,
|
|
1415
1423
|
handlers: InstalledHandler[],
|
|
1416
1424
|
adapterHome?: string,
|
|
1417
1425
|
options: HookCommandOptions = {},
|
package/src/interactive.test.ts
CHANGED
|
@@ -226,6 +226,37 @@ describe('interactiveCommand', () => {
|
|
|
226
226
|
answers = []
|
|
227
227
|
})
|
|
228
228
|
|
|
229
|
+
it('enters init on first-run instead of a parallel Sign in path', async () => {
|
|
230
|
+
const cwd = mkdtempSync(path.join(os.tmpdir(), 'notifai-interactive-first-run-'))
|
|
231
|
+
const out: string[] = []
|
|
232
|
+
const deps = makeDeps(cwd)
|
|
233
|
+
deps.store.load = () => null
|
|
234
|
+
deps.io.out = (line: string) => {
|
|
235
|
+
out.push(line)
|
|
236
|
+
}
|
|
237
|
+
answers = [CANCEL]
|
|
238
|
+
|
|
239
|
+
expect(await interactiveCommand(deps, '0.0.0-test')).toBe(EXIT.ok)
|
|
240
|
+
expect(out.join('\n')).toContain('Next: This machine')
|
|
241
|
+
expect(out.join('\n')).toContain('notifai init')
|
|
242
|
+
expect(out.join('\n')).not.toContain('notifai login')
|
|
243
|
+
const menu = promptLog.find((entry) => entry.message === 'What would you like to do?')
|
|
244
|
+
expect(menu?.options?.[0]).toMatchObject({ value: 'setup', label: 'Finish setup' })
|
|
245
|
+
expect(optionLabels(menu!)).not.toContain('Sign in')
|
|
246
|
+
expect(optionLabels(menu!)).not.toContain('Add a device')
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
it('offers Finish setup instead of a parallel Add a device path', async () => {
|
|
250
|
+
const cwd = mkdtempSync(path.join(os.tmpdir(), 'notifai-interactive-finish-setup-'))
|
|
251
|
+
answers = [CANCEL]
|
|
252
|
+
|
|
253
|
+
expect(await interactiveCommand(makeDeps(cwd), '0.0.0-test')).toBe(EXIT.ok)
|
|
254
|
+
const menu = promptLog.find((entry) => entry.message === 'What would you like to do?')
|
|
255
|
+
expect(menu?.options?.[0]).toMatchObject({ value: 'setup', label: 'Finish setup' })
|
|
256
|
+
expect(optionLabels(menu!)).not.toContain('Add a device')
|
|
257
|
+
expect(optionLabels(menu!)).not.toContain('Sign in')
|
|
258
|
+
})
|
|
259
|
+
|
|
229
260
|
it('quits from the root menu on Escape', async () => {
|
|
230
261
|
const cwd = mkdtempSync(path.join(os.tmpdir(), 'notifai-interactive-root-esc-'))
|
|
231
262
|
answers = [CANCEL]
|
package/src/interactive.ts
CHANGED
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Three things shape the layout:
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* seeing the thing arrive on
|
|
18
|
+
* First-run is `init`, not a second sign-in/device split. An unsigned machine
|
|
19
|
+
* enters that journey immediately; a remaining blocker is offered as Finish
|
|
20
|
+
* setup. Once send-prerequisites are ready, the menu leads with the test
|
|
21
|
+
* notification, because seeing the thing arrive on a device is what makes the
|
|
22
|
+
* product real.
|
|
22
23
|
*
|
|
23
24
|
* Detail is earned, not given. A settings group shows fourteen one-line
|
|
24
25
|
* summaries, and the paragraph explaining a key appears once the reader has
|
|
@@ -180,6 +181,10 @@ export async function interactiveCommand(deps: CommandDeps, version: string): Pr
|
|
|
180
181
|
process.stdout.write(` ${tagline(version)}\n`)
|
|
181
182
|
|
|
182
183
|
let readiness = await assess(deps)
|
|
184
|
+
if (stateById(readiness, 'credential')?.status !== 'ready') {
|
|
185
|
+
await initCommand(deps, {})
|
|
186
|
+
readiness = await assess(deps)
|
|
187
|
+
}
|
|
183
188
|
let first = true
|
|
184
189
|
|
|
185
190
|
for (;;) {
|
|
@@ -362,15 +367,13 @@ function menuFor(readiness: Readiness): { value: Screen; label: string; hint?: s
|
|
|
362
367
|
|
|
363
368
|
const options: { value: Screen; label: string; hint?: string }[] = []
|
|
364
369
|
|
|
365
|
-
if (
|
|
366
|
-
options.push({ value: 'account', label: 'Sign in', hint: 'approve this machine in your browser' })
|
|
367
|
-
} else if (!hasDevice) {
|
|
370
|
+
if (blocker !== null) {
|
|
368
371
|
options.push({
|
|
369
|
-
value: '
|
|
370
|
-
label: '
|
|
371
|
-
hint:
|
|
372
|
+
value: 'setup',
|
|
373
|
+
label: 'Finish setup',
|
|
374
|
+
hint: shorten(blocker.title.toLowerCase(), 40),
|
|
372
375
|
})
|
|
373
|
-
} else {
|
|
376
|
+
} else if (signedIn && hasDevice) {
|
|
374
377
|
options.push({
|
|
375
378
|
value: 'test',
|
|
376
379
|
label: 'Send a test notification',
|
|
@@ -378,10 +381,6 @@ function menuFor(readiness: Readiness): { value: Screen; label: string; hint?: s
|
|
|
378
381
|
})
|
|
379
382
|
}
|
|
380
383
|
|
|
381
|
-
if (blocker !== null && signedIn) {
|
|
382
|
-
options.push({ value: 'setup', label: 'Finish setup', hint: shorten(blocker.title.toLowerCase(), 40) })
|
|
383
|
-
}
|
|
384
|
-
|
|
385
384
|
options.push(
|
|
386
385
|
{ value: 'settings', label: 'Settings', hint: 'sounds, timing, presence, project' },
|
|
387
386
|
{
|
|
@@ -393,11 +392,11 @@ function menuFor(readiness: Readiness): { value: Screen; label: string; hint?: s
|
|
|
393
392
|
if (signedIn && hasDevice) {
|
|
394
393
|
options.push({ value: 'devices', label: 'Devices', hint: 'what can receive right now' })
|
|
395
394
|
}
|
|
396
|
-
options.push(
|
|
397
|
-
|
|
398
|
-
{ value: 'account', label: 'Account', hint:
|
|
399
|
-
|
|
400
|
-
)
|
|
395
|
+
options.push({ value: 'doctor', label: 'Run diagnostics', hint: 'check every part of the setup' })
|
|
396
|
+
if (signedIn) {
|
|
397
|
+
options.push({ value: 'account', label: 'Account', hint: 'plan, machine, sign out' })
|
|
398
|
+
}
|
|
399
|
+
options.push({ value: 'quit', label: 'Quit' })
|
|
401
400
|
return options
|
|
402
401
|
}
|
|
403
402
|
|
|
@@ -822,12 +821,7 @@ async function accountScreen(deps: CommandDeps, readiness: Readiness): Promise<b
|
|
|
822
821
|
const signedIn = stateById(readiness, 'credential')?.status === 'ready'
|
|
823
822
|
|
|
824
823
|
if (!signedIn) {
|
|
825
|
-
|
|
826
|
-
message: 'Sign in now? This opens your browser to approve this machine.',
|
|
827
|
-
initialValue: true,
|
|
828
|
-
})
|
|
829
|
-
if (cancelled(go) || go !== true) return false
|
|
830
|
-
await loginCommand(deps, {})
|
|
824
|
+
await initCommand(deps, {})
|
|
831
825
|
return true
|
|
832
826
|
}
|
|
833
827
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { type SourceContextT } from '@raidiant/notifai-protocol'
|
|
4
|
-
import type {
|
|
4
|
+
import type { SourceContextHarness } from './harnesses.js'
|
|
5
5
|
import { resolveSessionLabel } from './session-labels.js'
|
|
6
6
|
|
|
7
7
|
export type GitCommand = (cwd: string, args: readonly string[]) => string | null
|
|
@@ -138,7 +138,7 @@ export interface SourceContextInput {
|
|
|
138
138
|
sessionId?: string
|
|
139
139
|
sessionLabel?: string
|
|
140
140
|
activeHarness?: {
|
|
141
|
-
harness:
|
|
141
|
+
harness: SourceContextHarness
|
|
142
142
|
sessionId?: string
|
|
143
143
|
sessionLabel?: string
|
|
144
144
|
sessionLabelPending?: boolean
|