@raidiant/notifai 5.0.0 → 7.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.
- package/CHANGELOG.md +51 -0
- package/README.md +2 -2
- package/dist/atomic-file.js +13 -0
- package/dist/atomic-file.js.map +1 -1
- package/dist/client.d.ts +8 -3
- package/dist/client.js +24 -3
- package/dist/client.js.map +1 -1
- package/dist/commands-auth.d.ts +14 -0
- package/dist/commands-auth.js +154 -0
- package/dist/commands-auth.js.map +1 -0
- package/dist/commands-config.d.ts +31 -0
- package/dist/commands-config.js +246 -0
- package/dist/commands-config.js.map +1 -0
- package/dist/commands-core.d.ts +102 -0
- package/dist/commands-core.js +135 -0
- package/dist/commands-core.js.map +1 -0
- package/dist/commands-devices.d.ts +31 -0
- package/dist/commands-devices.js +124 -0
- package/dist/commands-devices.js.map +1 -0
- package/dist/commands-doctor.d.ts +24 -0
- package/dist/commands-doctor.js +1011 -0
- package/dist/commands-doctor.js.map +1 -0
- package/dist/commands-harness-context.d.ts +65 -0
- package/dist/commands-harness-context.js +97 -0
- package/dist/commands-harness-context.js.map +1 -0
- package/dist/commands-hook-shape.d.ts +17 -0
- package/dist/commands-hook-shape.js +37 -0
- package/dist/commands-hook-shape.js.map +1 -0
- package/dist/commands-hooks.d.ts +115 -0
- package/dist/commands-hooks.js +1225 -0
- package/dist/commands-hooks.js.map +1 -0
- package/dist/commands-init.d.ts +35 -0
- package/dist/commands-init.js +580 -0
- package/dist/commands-init.js.map +1 -0
- package/dist/commands-io.d.ts +2 -0
- package/dist/commands-io.js +110 -0
- package/dist/commands-io.js.map +1 -0
- package/dist/commands-logs.d.ts +30 -0
- package/dist/commands-logs.js +201 -0
- package/dist/commands-logs.js.map +1 -0
- package/dist/commands-send-support.d.ts +44 -0
- package/dist/commands-send-support.js +183 -0
- package/dist/commands-send-support.js.map +1 -0
- package/dist/commands-send.d.ts +33 -0
- package/dist/commands-send.js +519 -0
- package/dist/commands-send.js.map +1 -0
- package/dist/commands-setup-proof.d.ts +15 -0
- package/dist/commands-setup-proof.js +53 -0
- package/dist/commands-setup-proof.js.map +1 -0
- package/dist/commands-skill.d.ts +10 -0
- package/dist/commands-skill.js +71 -0
- package/dist/commands-skill.js.map +1 -0
- package/dist/commands.d.ts +12 -387
- package/dist/commands.js +12 -4536
- package/dist/commands.js.map +1 -1
- package/dist/config-schema.js +1 -1
- package/dist/config-schema.js.map +1 -1
- package/dist/config.d.ts +4 -4
- package/dist/config.js +6 -4
- package/dist/config.js.map +1 -1
- package/dist/credentials.js +13 -3
- package/dist/credentials.js.map +1 -1
- package/dist/generated-session-label.d.ts +2 -0
- package/dist/generated-session-label.js +152 -0
- package/dist/generated-session-label.js.map +1 -0
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +127 -99
- package/dist/hooks.js.map +1 -1
- package/dist/interactive.js +4 -4
- package/dist/interactive.js.map +1 -1
- package/dist/invocation-context.d.ts +3 -0
- package/dist/invocation-context.js +23 -6
- package/dist/invocation-context.js.map +1 -1
- package/dist/logging.js +1 -0
- package/dist/logging.js.map +1 -1
- package/dist/main.js +3 -3
- package/dist/main.js.map +1 -1
- package/dist/opencode-plugin.js +18 -3
- package/dist/opencode-plugin.js.map +1 -1
- package/dist/readiness.d.ts +3 -1
- package/dist/readiness.js.map +1 -1
- package/dist/session-labels.d.ts +30 -0
- package/dist/session-labels.js +278 -0
- package/dist/session-labels.js.map +1 -0
- package/package.json +2 -2
- package/src/atomic-file.ts +12 -0
- package/src/client.test.ts +90 -1
- package/src/client.ts +35 -2
- package/src/commands-auth.ts +174 -0
- package/src/commands-config.ts +307 -0
- package/src/commands-core.ts +240 -0
- package/src/commands-devices.ts +150 -0
- package/src/commands-doctor.ts +1209 -0
- package/src/commands-harness-context.ts +134 -0
- package/src/commands-hook-shape.ts +53 -0
- package/src/commands-hooks.ts +1586 -0
- package/src/commands-init.ts +721 -0
- package/src/commands-io.ts +108 -0
- package/src/commands-logs.ts +243 -0
- package/src/commands-send-support.ts +227 -0
- package/src/commands-send.ts +623 -0
- package/src/commands-setup-proof.ts +71 -0
- package/src/commands-skill.ts +84 -0
- package/src/commands.test.ts +567 -42
- package/src/commands.ts +58 -5614
- package/src/config-schema.ts +1 -1
- package/src/config.test.ts +9 -0
- package/src/config.ts +10 -5
- package/src/credentials.test.ts +25 -1
- package/src/credentials.ts +13 -3
- package/src/generated-session-label.ts +155 -0
- package/src/hooks.test.ts +355 -16
- package/src/hooks.ts +145 -97
- package/src/install-hooks.test.ts +84 -1
- package/src/interactive.test.ts +19 -1
- package/src/interactive.ts +4 -4
- package/src/invocation-context.test.ts +115 -16
- package/src/invocation-context.ts +32 -11
- package/src/logging.test.ts +15 -2
- package/src/logging.ts +1 -0
- package/src/main.ts +9 -3
- package/src/opencode-plugin.ts +18 -3
- package/src/readiness.ts +3 -1
- package/src/session-labels.test.ts +303 -0
- package/src/session-labels.ts +360 -0
- package/src/skill.test.ts +13 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-labels.js","sourceRoot":"","sources":["../src/session-labels.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raidiant/notifai",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Send native phone notifications from agents and local programs",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@clack/prompts": "^1.7.0",
|
|
24
|
-
"@raidiant/notifai-protocol": "
|
|
24
|
+
"@raidiant/notifai-protocol": "4.0.0",
|
|
25
25
|
"commander": "^14.0.0",
|
|
26
26
|
"picocolors": "^1.1.1",
|
|
27
27
|
"smol-toml": "^1.4.0"
|
package/src/atomic-file.ts
CHANGED
|
@@ -57,6 +57,7 @@ export function atomicWriteFileSync(
|
|
|
57
57
|
assertSameDirectory(directory, parent)
|
|
58
58
|
assertUnchangedTarget(file, target)
|
|
59
59
|
renameSync(temp, file)
|
|
60
|
+
syncDirectory(directory)
|
|
60
61
|
} catch (err) {
|
|
61
62
|
if (handle !== undefined) closeSync(handle)
|
|
62
63
|
try {
|
|
@@ -68,6 +69,17 @@ export function atomicWriteFileSync(
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
/** Persist the published directory entry where the host supports directory fsync. */
|
|
73
|
+
function syncDirectory(directory: string): void {
|
|
74
|
+
if (process.platform === 'win32') return
|
|
75
|
+
const handle = openSync(directory, 'r')
|
|
76
|
+
try {
|
|
77
|
+
fsyncSync(handle)
|
|
78
|
+
} finally {
|
|
79
|
+
closeSync(handle)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
71
83
|
/** Mode to preserve, or the mode for a new file. Refuses a non-regular target. */
|
|
72
84
|
interface TargetMetadata {
|
|
73
85
|
mode: number
|
package/src/client.test.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createServer, type Server } from 'node:http'
|
|
2
2
|
import type { AddressInfo } from 'node:net'
|
|
3
3
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
4
|
-
import {
|
|
4
|
+
import { CAPABILITIES_HEADER, CLI_VERSION_HEADER } from '@raidiant/notifai-protocol'
|
|
5
|
+
import { ApiCallError, NetworkError, createClient } from './client.js'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* These run against a real socket rather than a stubbed fetch, because the
|
|
@@ -192,3 +193,91 @@ describe('a server that never answers', () => {
|
|
|
192
193
|
await expect(client.listDevices()).rejects.toBeInstanceOf(NetworkError)
|
|
193
194
|
})
|
|
194
195
|
})
|
|
196
|
+
|
|
197
|
+
describe('compatibility metadata transport', () => {
|
|
198
|
+
it('advertises named CLI capabilities only on authenticated traffic', async () => {
|
|
199
|
+
const seen: Array<{
|
|
200
|
+
url: string | undefined
|
|
201
|
+
cliVersion: string | string[] | undefined
|
|
202
|
+
capabilities: string | string[] | undefined
|
|
203
|
+
}> = []
|
|
204
|
+
const baseUrl = await serving((request, response) => {
|
|
205
|
+
seen.push({
|
|
206
|
+
url: request.url,
|
|
207
|
+
cliVersion: request.headers[CLI_VERSION_HEADER],
|
|
208
|
+
capabilities: request.headers[CAPABILITIES_HEADER],
|
|
209
|
+
})
|
|
210
|
+
response.setHeader('content-type', 'application/json')
|
|
211
|
+
response.end(
|
|
212
|
+
JSON.stringify({
|
|
213
|
+
schema_version: 1,
|
|
214
|
+
platform: 'macos',
|
|
215
|
+
payload_limit_bytes: 4096,
|
|
216
|
+
sounds: [],
|
|
217
|
+
interruption_levels: [],
|
|
218
|
+
fields: [],
|
|
219
|
+
}),
|
|
220
|
+
)
|
|
221
|
+
})
|
|
222
|
+
const options = {
|
|
223
|
+
cliVersion: '5.0.0',
|
|
224
|
+
capabilities: ['agent_acknowledgement'] as const,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
await createClient(baseUrl, 'Bearer machine', options).capabilities('macos', '0.1.0', '42')
|
|
228
|
+
await createClient(baseUrl, null, options).capabilities('macos')
|
|
229
|
+
|
|
230
|
+
expect(seen).toEqual([
|
|
231
|
+
{
|
|
232
|
+
url: '/api/v1/capabilities/macos?app_version=0.1.0&app_build=42',
|
|
233
|
+
cliVersion: '5.0.0',
|
|
234
|
+
capabilities: 'agent_acknowledgement',
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
url: '/api/v1/capabilities/macos',
|
|
238
|
+
cliVersion: undefined,
|
|
239
|
+
capabilities: undefined,
|
|
240
|
+
},
|
|
241
|
+
])
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
it('keeps recovery typed when a feature is unavailable', async () => {
|
|
245
|
+
const baseUrl = await serving((_request, response) => {
|
|
246
|
+
response.statusCode = 422
|
|
247
|
+
response.setHeader('content-type', 'application/json')
|
|
248
|
+
response.end(
|
|
249
|
+
JSON.stringify({
|
|
250
|
+
error: {
|
|
251
|
+
code: 'feature_unavailable',
|
|
252
|
+
message: "The selected device can't answer questions.",
|
|
253
|
+
next_action: 'run an untrusted server command',
|
|
254
|
+
recovery_action: 'update_companion',
|
|
255
|
+
details: {
|
|
256
|
+
affected_operation: 'answer_questions',
|
|
257
|
+
missing_capabilities: ['answer'],
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
}),
|
|
261
|
+
)
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
let caught: unknown
|
|
265
|
+
try {
|
|
266
|
+
await createClient(baseUrl, 'Bearer machine').compatibility()
|
|
267
|
+
} catch (error) {
|
|
268
|
+
caught = error
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
expect(caught).toBeInstanceOf(ApiCallError)
|
|
272
|
+
expect(caught).toMatchObject({
|
|
273
|
+
status: 422,
|
|
274
|
+
code: 'feature_unavailable',
|
|
275
|
+
recoveryAction: 'update_companion',
|
|
276
|
+
nextAction: 'run an untrusted server command',
|
|
277
|
+
details: {
|
|
278
|
+
affected_operation: 'answer_questions',
|
|
279
|
+
missing_capabilities: ['answer'],
|
|
280
|
+
},
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
})
|
package/src/client.ts
CHANGED
|
@@ -9,6 +9,9 @@ import type {
|
|
|
9
9
|
EvidenceSnapshot,
|
|
10
10
|
GetAgentAcknowledgementResponse,
|
|
11
11
|
ListDevicesResponse,
|
|
12
|
+
ClientCapability,
|
|
13
|
+
CompatibilityResponse,
|
|
14
|
+
RecoveryAction,
|
|
12
15
|
ListRepliesResponse,
|
|
13
16
|
Platform,
|
|
14
17
|
PollPairingResponse,
|
|
@@ -17,6 +20,10 @@ import type {
|
|
|
17
20
|
SubmissionReceipt,
|
|
18
21
|
SubmitNotificationRequestT,
|
|
19
22
|
} from '@raidiant/notifai-protocol'
|
|
23
|
+
import {
|
|
24
|
+
CAPABILITIES_HEADER,
|
|
25
|
+
CLI_VERSION_HEADER,
|
|
26
|
+
} from '@raidiant/notifai-protocol'
|
|
20
27
|
import type { Logger } from './logging.js'
|
|
21
28
|
|
|
22
29
|
export class ApiCallError extends Error {
|
|
@@ -26,6 +33,7 @@ export class ApiCallError extends Error {
|
|
|
26
33
|
message: string,
|
|
27
34
|
public nextAction: string | null = null,
|
|
28
35
|
public details: unknown = null,
|
|
36
|
+
public recoveryAction: RecoveryAction | null = null,
|
|
29
37
|
) {
|
|
30
38
|
super(message)
|
|
31
39
|
}
|
|
@@ -67,7 +75,12 @@ export interface ApiClient {
|
|
|
67
75
|
pollPairing(pairingId: string, pollVerifier: string): Promise<PollPairingResponse>
|
|
68
76
|
accessStatus(): Promise<AccountAccessResponse>
|
|
69
77
|
listDevices(): Promise<ListDevicesResponse>
|
|
70
|
-
capabilities(
|
|
78
|
+
capabilities(
|
|
79
|
+
platform?: Platform,
|
|
80
|
+
appVersion?: string,
|
|
81
|
+
appBuild?: string,
|
|
82
|
+
): Promise<CapabilityDocument>
|
|
83
|
+
compatibility(): Promise<CompatibilityResponse>
|
|
71
84
|
submit(body: SubmitNotificationRequestT, waitSeconds: number): Promise<SubmissionReceipt>
|
|
72
85
|
evidence(requestId: string): Promise<EvidenceSnapshot>
|
|
73
86
|
replies(
|
|
@@ -112,6 +125,9 @@ export interface ClientOptions {
|
|
|
112
125
|
* instantly by a status code and a duration.
|
|
113
126
|
*/
|
|
114
127
|
logger?: Pick<Logger, 'debug' | 'error'>
|
|
128
|
+
/** Artifact identity and named jobs advertised only on authenticated traffic. */
|
|
129
|
+
cliVersion?: string | null
|
|
130
|
+
capabilities?: readonly ClientCapability[]
|
|
115
131
|
}
|
|
116
132
|
|
|
117
133
|
/** Generous enough for a slow link, short enough that nothing hangs for ever. */
|
|
@@ -126,6 +142,14 @@ export function createClient(
|
|
|
126
142
|
const budgetMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
127
143
|
const now = options.now ?? Date.now
|
|
128
144
|
const logger = options.logger
|
|
145
|
+
const clientHeaders: Record<string, string> = bearer
|
|
146
|
+
? {
|
|
147
|
+
...(options.cliVersion ? { [CLI_VERSION_HEADER]: options.cliVersion } : {}),
|
|
148
|
+
...(options.capabilities
|
|
149
|
+
? { [CAPABILITIES_HEADER]: options.capabilities.join(',') }
|
|
150
|
+
: {}),
|
|
151
|
+
}
|
|
152
|
+
: {}
|
|
129
153
|
|
|
130
154
|
async function call<T>(
|
|
131
155
|
method: string,
|
|
@@ -182,6 +206,7 @@ export function createClient(
|
|
|
182
206
|
headers: {
|
|
183
207
|
...(body !== undefined ? { 'content-type': 'application/json' } : {}),
|
|
184
208
|
...(bearer ? { authorization: bearer } : {}),
|
|
209
|
+
...clientHeaders,
|
|
185
210
|
},
|
|
186
211
|
signal,
|
|
187
212
|
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
@@ -202,6 +227,7 @@ export function createClient(
|
|
|
202
227
|
parsed?.error.message ?? `Request failed with status ${response.status}`,
|
|
203
228
|
parsed?.error.next_action ?? null,
|
|
204
229
|
parsed?.error.details ?? null,
|
|
230
|
+
parsed?.error.recovery_action ?? null,
|
|
205
231
|
)
|
|
206
232
|
}
|
|
207
233
|
if (response.status === 204) return undefined as T
|
|
@@ -220,7 +246,14 @@ export function createClient(
|
|
|
220
246
|
call('POST', `/api/v1/pairings/${pairingId}/poll`, { poll_verifier: pollVerifier }),
|
|
221
247
|
accessStatus: () => call('GET', '/api/v1/account/access'),
|
|
222
248
|
listDevices: () => call('GET', '/api/v1/devices'),
|
|
223
|
-
capabilities: (platform = 'ios') =>
|
|
249
|
+
capabilities: (platform = 'ios', appVersion, appBuild) => {
|
|
250
|
+
const query = new URLSearchParams()
|
|
251
|
+
if (appVersion !== undefined) query.set('app_version', appVersion)
|
|
252
|
+
if (appBuild !== undefined) query.set('app_build', appBuild)
|
|
253
|
+
const suffix = query.size > 0 ? `?${query.toString()}` : ''
|
|
254
|
+
return call('GET', `/api/v1/capabilities/${platform}${suffix}`)
|
|
255
|
+
},
|
|
256
|
+
compatibility: () => call('GET', '/api/v1/compatibility'),
|
|
224
257
|
submit: (body, waitSeconds) =>
|
|
225
258
|
call('POST', `/api/v1/notifications?wait_seconds=${waitSeconds}`, body, waitSeconds),
|
|
226
259
|
evidence: (requestId) => call('GET', `/api/v1/notifications/${requestId}`),
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { type AccountAccessResponse } from '@raidiant/notifai-protocol'
|
|
2
|
+
import { sha256Hex } from '@raidiant/notifai-protocol/node'
|
|
3
|
+
import { randomBytes } from 'node:crypto'
|
|
4
|
+
import os from 'node:os'
|
|
5
|
+
import { NetworkError } from './client.js'
|
|
6
|
+
import { type FlagOverrides } from './config.js'
|
|
7
|
+
import {
|
|
8
|
+
EXIT,
|
|
9
|
+
authedClient,
|
|
10
|
+
loadLoggedConfig,
|
|
11
|
+
makeClient,
|
|
12
|
+
reportError,
|
|
13
|
+
type CommandDeps,
|
|
14
|
+
} from './commands-core.js'
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// login / logout / auth status
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
export async function loginCommand(
|
|
21
|
+
deps: CommandDeps,
|
|
22
|
+
flags: { name?: string; baseUrl?: string; open?: boolean },
|
|
23
|
+
): Promise<number> {
|
|
24
|
+
const config = loadLoggedConfig(deps, { cwd: deps.cwd, env: deps.env, flags: { base_url: flags.baseUrl } as FlagOverrides })
|
|
25
|
+
const baseUrl = config.base_url.value
|
|
26
|
+
const machineName = flags.name ?? os.hostname()
|
|
27
|
+
const secret = randomBytes(32).toString('base64url')
|
|
28
|
+
const pollVerifier = randomBytes(24).toString('base64url')
|
|
29
|
+
const client = makeClient(deps, baseUrl, null)
|
|
30
|
+
|
|
31
|
+
let begin
|
|
32
|
+
try {
|
|
33
|
+
begin = await client.beginPairing({
|
|
34
|
+
machine_name: machineName,
|
|
35
|
+
credential_hash: sha256Hex(secret),
|
|
36
|
+
poll_verifier_hash: sha256Hex(pollVerifier),
|
|
37
|
+
})
|
|
38
|
+
} catch (err) {
|
|
39
|
+
return reportError(deps, err)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const interactive = deps.io.interactive === true
|
|
43
|
+
if (interactive) {
|
|
44
|
+
await deps.io.intro?.('Notifai sign in')
|
|
45
|
+
await deps.io.note?.(`Code: ${begin.code}\n${begin.approve_url}`, 'Approve this machine')
|
|
46
|
+
} else {
|
|
47
|
+
deps.io.out(`Pairing code: ${begin.code}`)
|
|
48
|
+
deps.io.out(`Approve this machine at: ${begin.approve_url}`)
|
|
49
|
+
deps.io.out('Waiting for approval…')
|
|
50
|
+
}
|
|
51
|
+
if (flags.open !== false) deps.io.openUrl(begin.approve_url)
|
|
52
|
+
|
|
53
|
+
const expiresAt = new Date(begin.expires_at).getTime()
|
|
54
|
+
const intervalMs = Math.max(begin.poll_interval_seconds, 1) * 1000
|
|
55
|
+
const now = deps.now ?? Date.now
|
|
56
|
+
const sleep = deps.sleep ?? ((milliseconds: number) => new Promise<void>((resolve) => setTimeout(resolve, milliseconds)))
|
|
57
|
+
const approvalWaitMessage = (): string => {
|
|
58
|
+
const remainingSec = Math.max(0, Math.ceil((expiresAt - now()) / 1000))
|
|
59
|
+
const minutes = Math.floor(remainingSec / 60)
|
|
60
|
+
const seconds = remainingSec % 60
|
|
61
|
+
const remaining =
|
|
62
|
+
minutes > 0 ? `${minutes}m ${seconds.toString().padStart(2, '0')}s` : `${seconds}s`
|
|
63
|
+
return `Waiting for approval… code ${begin.code} · ${remaining} left`
|
|
64
|
+
}
|
|
65
|
+
const spinner = interactive ? await deps.io.spinner?.(approvalWaitMessage()) : null
|
|
66
|
+
while (now() < expiresAt) {
|
|
67
|
+
await sleep(intervalMs)
|
|
68
|
+
let poll
|
|
69
|
+
try {
|
|
70
|
+
poll = await client.pollPairing(begin.pairing_id, pollVerifier)
|
|
71
|
+
} catch (err) {
|
|
72
|
+
if (err instanceof NetworkError) {
|
|
73
|
+
spinner?.message(`Connection lost — retrying… code ${begin.code}`)
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
spinner?.error('Pairing failed')
|
|
77
|
+
return reportError(deps, err)
|
|
78
|
+
}
|
|
79
|
+
if (poll.status === 'approved' && poll.machine_id) {
|
|
80
|
+
deps.store.save({ machineId: poll.machine_id, secret, baseUrl, machineName })
|
|
81
|
+
if (interactive) {
|
|
82
|
+
spinner?.stop(`Machine "${machineName}" approved`)
|
|
83
|
+
await deps.io.outro?.(`Credential stored in ${deps.store.describe()}`)
|
|
84
|
+
} else {
|
|
85
|
+
deps.io.out(`Machine "${machineName}" approved. Credential stored in ${deps.store.describe()}.`)
|
|
86
|
+
}
|
|
87
|
+
return EXIT.ok
|
|
88
|
+
}
|
|
89
|
+
if (poll.status === 'denied') {
|
|
90
|
+
spinner?.error('Pairing denied')
|
|
91
|
+
deps.io.err('Pairing was denied from the dashboard.')
|
|
92
|
+
return EXIT.auth
|
|
93
|
+
}
|
|
94
|
+
if (poll.status === 'no_active_plan') {
|
|
95
|
+
const next =
|
|
96
|
+
poll.next_action ??
|
|
97
|
+
`Open ${baseUrl.replace(/\/$/, '')}/support to request Alpha access, then retry.`
|
|
98
|
+
spinner?.error('Account has no Alpha access')
|
|
99
|
+
deps.io.err('This account has no active plan or temporary Alpha access.')
|
|
100
|
+
deps.io.err(`next: ${next}`)
|
|
101
|
+
deps.io.err('After access is granted, run `notifai login` again.')
|
|
102
|
+
return EXIT.auth
|
|
103
|
+
}
|
|
104
|
+
if (poll.status === 'expired') break
|
|
105
|
+
spinner?.message(approvalWaitMessage())
|
|
106
|
+
}
|
|
107
|
+
spinner?.error('Pairing expired')
|
|
108
|
+
deps.io.err('Pairing expired before it was approved. Run `notifai login` again.')
|
|
109
|
+
return EXIT.auth
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function logoutCommand(deps: CommandDeps): number {
|
|
113
|
+
deps.store.clear()
|
|
114
|
+
deps.io.out('Machine credential removed. Revoke it in the dashboard too if the machine is untrusted.')
|
|
115
|
+
return EXIT.ok
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function authStatusCommand(deps: CommandDeps, flags: { json?: boolean }): number {
|
|
119
|
+
const credential = deps.store.load()
|
|
120
|
+
if (flags.json) {
|
|
121
|
+
deps.io.out(
|
|
122
|
+
JSON.stringify(
|
|
123
|
+
credential
|
|
124
|
+
? {
|
|
125
|
+
signed_in: true,
|
|
126
|
+
machine_id: credential.machineId,
|
|
127
|
+
machine_name: credential.machineName,
|
|
128
|
+
base_url: credential.baseUrl,
|
|
129
|
+
store: deps.store.describe(),
|
|
130
|
+
}
|
|
131
|
+
: { signed_in: false },
|
|
132
|
+
null,
|
|
133
|
+
2,
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
return credential ? EXIT.ok : EXIT.auth
|
|
137
|
+
}
|
|
138
|
+
if (!credential) {
|
|
139
|
+
deps.io.err('Not signed in. Run `notifai login`.')
|
|
140
|
+
return EXIT.auth
|
|
141
|
+
}
|
|
142
|
+
deps.io.out(`Signed in as machine "${credential.machineName}" (${credential.machineId})`)
|
|
143
|
+
deps.io.out(`Server: ${credential.baseUrl}`)
|
|
144
|
+
deps.io.out(`Credential store: ${deps.store.describe()}`)
|
|
145
|
+
return EXIT.ok
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Show the server's account access decision without attempting a product mutation. */
|
|
149
|
+
export async function accessStatusCommand(
|
|
150
|
+
deps: CommandDeps,
|
|
151
|
+
flags: { json?: boolean },
|
|
152
|
+
): Promise<number> {
|
|
153
|
+
const config = loadLoggedConfig(deps, { cwd: deps.cwd, env: deps.env })
|
|
154
|
+
const authed = authedClient(deps, config)
|
|
155
|
+
if (!authed) return EXIT.auth
|
|
156
|
+
try {
|
|
157
|
+
const access: AccountAccessResponse = await authed.client.accessStatus()
|
|
158
|
+
if (flags.json) {
|
|
159
|
+
deps.io.out(JSON.stringify(access, null, 2))
|
|
160
|
+
return access.status === 'active' ? EXIT.ok : EXIT.failed
|
|
161
|
+
}
|
|
162
|
+
if (access.status === 'no_active_plan') {
|
|
163
|
+
const supportUrl = `${authed.baseUrl.replace(/\/$/, '')}/support`
|
|
164
|
+
deps.io.out('No active plan or temporary Alpha access for this account.')
|
|
165
|
+
deps.io.out(`next: Open ${supportUrl} to request Alpha access, then retry.`)
|
|
166
|
+
return EXIT.failed
|
|
167
|
+
}
|
|
168
|
+
const expiry = access.expires_at ? ` until ${access.expires_at}` : ''
|
|
169
|
+
deps.io.out(`Access active (${access.reason})${expiry}`)
|
|
170
|
+
return EXIT.ok
|
|
171
|
+
} catch (err) {
|
|
172
|
+
return reportError(deps, err)
|
|
173
|
+
}
|
|
174
|
+
}
|