@astrale-os/cli 1.0.0-beta.3 → 1.0.0-beta.30
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 +80 -6
- package/dist/astrale.js +55471 -58674
- package/dist/public/connect-core.js +2158 -30706
- package/dist/public/keys/index.js +1016 -29541
- package/dist/public/paths/index.js +370 -28654
- package/dist/types/admin/contract.d.ts +26 -0
- package/dist/types/admin/instance/client.d.ts +20 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +6 -10
- package/dist/types/connection/auth.d.ts +3 -0
- package/dist/types/connection/call.d.ts +3 -0
- package/dist/types/connection/command.d.ts +27 -0
- package/dist/types/connection/credential.d.ts +14 -0
- package/dist/types/connection/errors.d.ts +1 -0
- package/dist/types/connection/exchange.d.ts +9 -0
- package/dist/types/connection/failure/classify.d.ts +2 -0
- package/dist/types/connection/failure/index.d.ts +5 -0
- package/dist/types/connection/failure/model.d.ts +25 -0
- package/dist/types/connection/failure/render.d.ts +3 -0
- package/dist/types/connection/index.d.ts +8 -0
- package/dist/types/connection/reasons.d.ts +37 -0
- package/dist/types/connection/self.d.ts +37 -0
- package/dist/types/connection/session.d.ts +31 -0
- package/dist/types/connection/target.d.ts +38 -0
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/lib/admin-instance.d.ts +17 -0
- package/dist/types/lib/admin-target.d.ts +11 -36
- package/dist/types/lib/config.d.ts +13 -59
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +25 -173
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +30 -88
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/output.d.ts +1 -1
- package/dist/types/lib/proc.d.ts +43 -0
- package/dist/types/lib/self.d.ts +9 -0
- package/dist/types/lib/update.d.ts +109 -0
- package/dist/types/lib/validation.d.ts +4 -1
- package/dist/types/state/exchange-credentials.d.ts +6 -2
- package/dist/types/state/files.d.ts +2 -0
- package/dist/types/state/index.d.ts +3 -2
- package/dist/types/state/paths.d.ts +2 -0
- package/dist/types/state/session-routes.d.ts +10 -0
- package/package.json +16 -19
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/.spec/architecture.md +12 -5
- package/src/admin/__tests__/fixture.ts +25 -0
- package/src/admin/catalog/.spec/api.d.ts +1 -3
- package/src/admin/catalog/.spec/architecture.md +5 -4
- package/src/admin/catalog/__tests__/client.test.ts +143 -69
- package/src/admin/catalog/client.ts +40 -54
- package/src/admin/catalog/model.ts +3 -4
- package/src/admin/contract.ts +47 -0
- package/src/admin/graph/.spec/api.d.ts +4 -10
- package/src/admin/graph/nodes.ts +1 -1
- package/src/admin/instance/.spec/api.d.ts +5 -9
- package/src/admin/instance/.spec/architecture.md +7 -7
- package/src/admin/instance/__tests__/client.test.ts +157 -175
- package/src/admin/instance/client.ts +39 -128
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +12 -18
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +34 -0
- package/src/commands/__tests__/domain-install-operation.test.ts +30 -22
- package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
- package/src/commands/__tests__/domain-list.test.ts +5 -25
- package/src/commands/__tests__/install-direct.test.ts +115 -8
- package/src/commands/__tests__/install-identity-override.test.ts +6 -17
- package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
- package/src/commands/__tests__/instance-status.test.ts +139 -0
- package/src/commands/__tests__/introspect-parse.test.ts +80 -1
- package/src/commands/__tests__/logs.test.ts +250 -2
- package/src/commands/__tests__/read-commands.test.ts +118 -10
- package/src/commands/__tests__/token-ttl.test.ts +49 -4
- package/src/commands/__tests__/update.test.ts +25 -3
- package/src/commands/__tests__/view.test.ts +50 -2
- package/src/commands/auth/logout.ts +2 -1
- package/src/commands/browser.ts +29 -0
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +71 -59
- package/src/commands/domain/install.ts +73 -46
- package/src/commands/domain/list.ts +1 -1
- package/src/commands/domain/publish.ts +14 -11
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +15 -16
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +8 -8
- package/src/commands/instance/create.ts +8 -16
- package/src/commands/instance/delete.ts +12 -9
- package/src/commands/instance/list.ts +2 -2
- package/src/commands/instance/status.ts +66 -20
- package/src/commands/instance/use.ts +16 -12
- package/src/commands/introspect.ts +53 -41
- package/src/commands/logs.ts +123 -36
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +35 -32
- package/src/commands/session/analyze.ts +26 -4
- package/src/commands/token.ts +42 -27
- package/src/commands/ui/__tests__/commands.test.ts +152 -0
- package/src/commands/ui/add.ts +51 -0
- package/src/commands/ui/doctor.ts +21 -0
- package/src/commands/ui/init.ts +38 -0
- package/src/commands/ui/list.ts +26 -0
- package/src/commands/ui/preset-apply.ts +19 -0
- package/src/commands/ui/preset-list.ts +12 -0
- package/src/commands/ui/shared.ts +25 -0
- package/src/commands/update.ts +89 -48
- package/src/commands/view.ts +82 -37
- package/src/connection/.spec/api.d.ts +7 -8
- package/src/connection/.spec/architecture.md +14 -5
- package/src/connection/.spec/flows/session.ts +2 -2
- package/src/connection/.spec/laws/connection.ts +6 -2
- package/src/connection/.spec/layout.ts +1 -0
- package/src/connection/__tests__/auth.test.ts +1 -0
- package/src/connection/__tests__/credential.test.ts +21 -1
- package/src/connection/__tests__/errors.test.ts +27 -20
- package/src/connection/__tests__/exchange.test.ts +64 -11
- package/src/connection/__tests__/failure-fixtures.ts +39 -0
- package/src/connection/__tests__/failure-safety.test.ts +75 -0
- package/src/connection/__tests__/self.test.ts +31 -11
- package/src/connection/__tests__/session.test.ts +8 -4
- package/src/connection/__tests__/target.test.ts +2 -0
- package/src/connection/auth.ts +13 -0
- package/src/connection/call.ts +1 -1
- package/src/connection/credential.ts +2 -2
- package/src/connection/errors.ts +1 -355
- package/src/connection/exchange.ts +110 -61
- package/src/connection/failure/classify.ts +110 -0
- package/src/connection/failure/index.ts +18 -0
- package/src/connection/failure/model.ts +28 -0
- package/src/connection/failure/render.ts +116 -0
- package/src/connection/reasons.ts +16 -0
- package/src/connection/self.ts +39 -21
- package/src/connection/session.ts +27 -9
- package/src/errors.ts +3 -2
- package/src/graph/.spec/api.d.ts +12 -5
- package/src/graph/.spec/layout.ts +9 -1
- package/src/graph/__tests__/mutation.test.ts +2 -2
- package/src/graph/__tests__/query.test.ts +25 -6
- package/src/graph/class.ts +30 -0
- package/src/graph/index.ts +1 -0
- package/src/graph/query.ts +21 -32
- package/src/identity/.spec/api.d.ts +2 -2
- package/src/identity/__tests__/fixtures/registry-journey.ts +13 -1
- package/src/identity/__tests__/registration.test.ts +1 -1
- package/src/identity/__tests__/registry.test.ts +4 -0
- package/src/identity/registration.ts +3 -3
- package/src/identity/registry.ts +2 -0
- package/src/keys/__tests__/keys.test.ts +4 -0
- package/src/keys/credential.ts +1 -0
- package/src/lib/__tests__/admin-target.test.ts +12 -0
- package/src/lib/__tests__/binary.test.ts +16 -1
- package/src/lib/__tests__/browser-retention.test.ts +212 -0
- package/src/lib/__tests__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/config.test.ts +27 -0
- package/src/lib/__tests__/domain-publication.test.ts +10 -16
- package/src/lib/__tests__/idp.test.ts +34 -4
- package/src/lib/__tests__/instance-candidates.test.ts +1 -3
- package/src/lib/__tests__/instance-target.test.ts +7 -39
- package/src/lib/__tests__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/skills.test.ts +809 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
- package/src/lib/__tests__/update.test.ts +264 -11
- package/src/lib/__tests__/view-assets.test.ts +25 -0
- package/src/lib/__tests__/view-external-open-intent.test.ts +150 -0
- package/src/lib/__tests__/view-external-open-origins.test.ts +27 -0
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +26 -3
- package/src/lib/__tests__/view-session.test.ts +2 -1
- package/src/lib/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/binary.ts +22 -5
- package/src/lib/browser-retention.ts +210 -0
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/config.ts +12 -1
- package/src/lib/domain-publication.ts +9 -7
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +34 -3
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +16 -11
- package/src/lib/log.ts +16 -9
- package/src/lib/output.ts +1 -1
- package/src/lib/proc.ts +7 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/skills/lock.ts +117 -0
- package/src/lib/skills/sync.ts +814 -0
- package/src/lib/skills.ts +1 -52
- package/src/lib/update.ts +298 -45
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/assets.ts +11 -2
- package/src/lib/view/external-open-intent.ts +41 -0
- package/src/lib/view/external-open-origins.ts +37 -0
- package/src/lib/view/host-capabilities.ts +17 -0
- package/src/lib/view/resolve.ts +1 -1
- package/src/lib/view/server.ts +18 -3
- package/src/lib/view/session.ts +2 -0
- package/src/program/.spec/api.d.ts +1 -0
- package/src/program/__tests__/program.test.ts +163 -6
- package/src/program/argv.ts +14 -0
- package/src/program/build.ts +26 -4
- package/src/program/command.ts +1 -0
- package/src/program/index.ts +1 -0
- package/src/program/registry.ts +2 -1
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/src/setup/steps/skills.ts +40 -38
- package/src/state/.spec/api.d.ts +21 -2
- package/src/state/.spec/architecture.md +18 -4
- package/src/state/.spec/layout.ts +1 -0
- package/src/state/__tests__/exchange-credentials.test.ts +88 -42
- package/src/state/__tests__/files.test.ts +24 -1
- package/src/state/__tests__/fixtures/session-route-process.ts +93 -0
- package/src/state/__tests__/paths.test.ts +1 -0
- package/src/state/__tests__/session-routes.test.ts +138 -0
- package/src/state/exchange-credentials.ts +22 -9
- package/src/state/files.ts +41 -0
- package/src/state/index.ts +3 -1
- package/src/state/paths.ts +3 -0
- package/src/state/session-routes.ts +34 -0
- package/src/telemetry/__tests__/analyze-log.test.ts +38 -0
- package/src/telemetry/__tests__/recorder.test.ts +1 -0
- package/src/telemetry/__tests__/retention.test.ts +267 -0
- package/src/telemetry/__tests__/settings.test.ts +102 -0
- package/src/telemetry/__tests__/store-scan.test.ts +128 -0
- package/src/telemetry/__tests__/trigger.test.ts +33 -4
- package/src/telemetry/analyze.ts +24 -2
- package/src/telemetry/recorder.ts +15 -4
- package/src/telemetry/retention.ts +176 -0
- package/src/telemetry/session.ts +18 -12
- package/src/telemetry/settings.ts +64 -11
- package/src/telemetry/store.ts +92 -9
- package/src/telemetry/trigger.ts +16 -28
- package/src/ui/.spec/api.d.ts +14 -0
- package/src/ui/.spec/architecture.md +14 -0
- package/src/ui/.spec/laws.ts +50 -0
- package/src/ui/.spec/layout.ts +16 -0
- package/src/ui/__tests__/ui.test.ts +1742 -0
- package/src/ui/index.ts +13 -0
- package/src/ui/lock.ts +89 -0
- package/src/ui/model.ts +83 -0
- package/src/ui/operations.ts +1044 -0
- package/src/ui/project.ts +333 -0
- package/src/ui/release.ts +398 -0
- package/src/ui/runner.ts +18 -0
- package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
- package/studio/client/dist/assets/index-BFVFs_8x.js +81 -0
- package/studio/client/dist/assets/index-DuB9iUdu.css +2 -0
- package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
- package/studio/client/dist/assets/schema-studio--a0kX3QU.css +1 -0
- package/studio/client/dist/assets/schema-studio-DH6oEWME.js +8 -0
- package/studio/client/dist/index.html +4 -3
- package/studio/package.json +8 -14
- package/studio/server/agent/ask.test.ts +1 -1
- package/studio/server/agent/bridge/grant.test.ts +1 -1
- package/studio/server/agent/bridge/routes.test.ts +1 -1
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/gateway/token.test.ts +1 -1
- package/studio/server/agent/harness/gateway/token.ts +3 -3
- package/studio/server/agent/prompts/anchors.test.ts +41 -32
- package/studio/server/agent/prompts/anchors.ts +23 -51
- package/studio/server/agent/prompts/system.test.ts +4 -4
- package/studio/server/agent/prompts/system.ts +5 -5
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/agent/run/preparation.ts +1 -1
- package/studio/server/api/canvas.ts +0 -1
- package/studio/server/api/context.ts +1 -1
- package/studio/server/api/deployment.ts +1 -1
- package/studio/server/api/views.ts +2 -2
- package/studio/server/api/workspace.ts +1 -1
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +1 -1
- package/studio/server/cache.test.ts +24 -18
- package/studio/server/cache.ts +10 -54
- package/studio/server/cli-consumers.test.ts +31 -3
- package/studio/server/domain.test.ts +50 -68
- package/studio/server/domain.ts +82 -63
- package/studio/server/handoff/copy.ts +2 -2
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/probe.test.ts +1 -1
- package/studio/server/introspect/anatomy/views/routes.ts +46 -37
- package/studio/server/introspect/anatomy/views.ts +10 -16
- package/studio/server/introspect/anatomy-extras.test.ts +29 -56
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +6 -9
- package/studio/server/introspect/bundle.ts +0 -3
- package/studio/server/introspect/canonical-schema.test.ts +155 -424
- package/studio/server/introspect/canonical-schema.ts +248 -601
- package/studio/server/introspect/core.ts +14 -22
- package/studio/server/introspect/diff.test.ts +21 -9
- package/studio/server/introspect/diff.ts +19 -64
- package/studio/server/introspect/extractor.ts +23 -122
- package/studio/server/introspect/overlay-tsmorph.test.ts +116 -241
- package/studio/server/introspect/overlay-tsmorph.ts +0 -1
- package/studio/server/introspect/overlay.ts +3 -51
- package/studio/server/introspect/revision.test.ts +24 -28
- package/studio/server/introspect/revision.ts +11 -22
- package/studio/server/introspect/runtime.test.ts +77 -195
- package/studio/server/introspect/runtime.ts +5 -67
- package/studio/server/introspect/schema-ir-json.test.ts +81 -0
- package/studio/server/introspect/schema-ir-json.ts +39 -69
- package/studio/server/introspect/schema-refs.test.ts +43 -88
- package/studio/server/introspect/schema-refs.ts +14 -49
- package/studio/server/introspect/source-overlay/handlers.ts +116 -636
- package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
- package/studio/server/introspect/source-overlay/spans.ts +15 -45
- package/studio/server/lifecycle.ts +4 -1
- package/studio/server/state/baseline.test.ts +14 -9
- package/studio/server/state/baseline.ts +3 -5
- package/studio/server/state/documents.test.ts +69 -0
- package/studio/server/state/documents.ts +57 -10
- package/studio/server/state/visibility.ts +1 -5
- package/studio/server/views/model.ts +3 -3
- package/studio/server/views/target.test.ts +18 -76
- package/studio/server/views/target.ts +24 -50
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +8 -4
- package/studio/server/workspace/updates.ts +23 -1
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/runtime.ts +4 -0
- package/studio/shared/contracts/schema.ts +44 -131
- package/studio/shared/contracts/surface.test.ts +15 -17
- package/studio/shared/contracts/workspace.ts +5 -11
- package/studio/shared/schema/identity.test.ts +20 -44
- package/studio/shared/schema/identity.ts +9 -24
- package/studio/tsconfig.json +2 -1
- package/tsconfig.json +1 -1
- package/viewer/dist/index.html +21 -0
- package/viewer/dist/main.js +41 -62
- package/.check-workspace.cjs +0 -40
- package/src/admin/binding.ts +0 -168
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/elk-api-lwhFo7vB.js +0 -1
- package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
- package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
- package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
- package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
- package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
- package/studio/server/introspect/core-extractor.ts +0 -139
- package/studio/server/introspect/overlay.test.ts +0 -72
- package/studio/server/introspect/source-overlay/annotations.ts +0 -14
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import addCommand from '../add'
|
|
4
|
+
import listCommand from '../list'
|
|
5
|
+
|
|
6
|
+
class ExitError extends Error {}
|
|
7
|
+
|
|
8
|
+
const commit = 'a'.repeat(40)
|
|
9
|
+
const item = {
|
|
10
|
+
name: 'pattern-chart-line-basic',
|
|
11
|
+
type: 'registry:block',
|
|
12
|
+
title: 'Line chart',
|
|
13
|
+
description: 'A controlled chart.',
|
|
14
|
+
dependencies: ['@astrale-os/ui@^0.3.0-beta.0'],
|
|
15
|
+
files: [
|
|
16
|
+
{
|
|
17
|
+
path: 'registry/patterns/chart/line-basic.tsx',
|
|
18
|
+
type: 'registry:component',
|
|
19
|
+
target: 'components/astrale/pattern/chart/line-basic.tsx',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
meta: { canonicalAddress: 'pattern/chart/line/basic' },
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let stdout = ''
|
|
26
|
+
let stderr = ''
|
|
27
|
+
let originalArgv: string[]
|
|
28
|
+
let originalExit: typeof process.exit
|
|
29
|
+
let originalFetch: typeof globalThis.fetch
|
|
30
|
+
let originalStdout: typeof process.stdout.write
|
|
31
|
+
let originalStderr: typeof process.stderr.write
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
stdout = ''
|
|
35
|
+
stderr = ''
|
|
36
|
+
originalArgv = process.argv
|
|
37
|
+
originalExit = process.exit
|
|
38
|
+
originalFetch = globalThis.fetch
|
|
39
|
+
originalStdout = process.stdout.write
|
|
40
|
+
originalStderr = process.stderr.write
|
|
41
|
+
process.stdout.write = ((chunk: string | Uint8Array) => {
|
|
42
|
+
stdout += String(chunk)
|
|
43
|
+
return true
|
|
44
|
+
}) as typeof process.stdout.write
|
|
45
|
+
process.stderr.write = ((chunk: string | Uint8Array) => {
|
|
46
|
+
stderr += String(chunk)
|
|
47
|
+
return true
|
|
48
|
+
}) as typeof process.stderr.write
|
|
49
|
+
process.exit = (() => {
|
|
50
|
+
throw new ExitError()
|
|
51
|
+
}) as typeof process.exit
|
|
52
|
+
globalThis.fetch = mockFetch()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
process.argv = originalArgv
|
|
57
|
+
process.exit = originalExit
|
|
58
|
+
globalThis.fetch = originalFetch
|
|
59
|
+
process.stdout.write = originalStdout
|
|
60
|
+
process.stderr.write = originalStderr
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe('UI command machine contracts', () => {
|
|
64
|
+
test('list emits exactly one parseable JSON value', async () => {
|
|
65
|
+
const action = listCommand.action as (
|
|
66
|
+
query: string | undefined,
|
|
67
|
+
options: { json?: boolean; limit?: string },
|
|
68
|
+
) => Promise<void>
|
|
69
|
+
await action('line-basic', { json: true, limit: '100' })
|
|
70
|
+
|
|
71
|
+
expect(stderr).toBe('')
|
|
72
|
+
expect(JSON.parse(stdout)).toEqual([item])
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('list forwards an explicit release without consulting the beta channel', async () => {
|
|
76
|
+
const seen: string[] = []
|
|
77
|
+
globalThis.fetch = mockFetch(seen)
|
|
78
|
+
const action = listCommand.action as (
|
|
79
|
+
query: string | undefined,
|
|
80
|
+
options: { json?: boolean; limit?: string; version?: string },
|
|
81
|
+
) => Promise<void>
|
|
82
|
+
|
|
83
|
+
await action('line-basic', { json: true, limit: '100', version: '0.3.0-beta.1' })
|
|
84
|
+
|
|
85
|
+
expect(JSON.parse(stdout)).toEqual([item])
|
|
86
|
+
expect(seen.some((url) => url.endsWith('/@astrale-os/ui/beta'))).toBe(false)
|
|
87
|
+
expect(seen.some((url) => url.includes('/git/ref/tags/v0.3.0-beta.1'))).toBe(true)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('add rejects missing items without prompting in machine mode', async () => {
|
|
91
|
+
process.argv = ['node', 'astrale', '--no-prompt', 'ui', 'add']
|
|
92
|
+
const add = addCommand.action as (items: string[], options: { json?: boolean }) => Promise<void>
|
|
93
|
+
await expect(add([], { json: true })).rejects.toBeInstanceOf(ExitError)
|
|
94
|
+
expect(JSON.parse(stderr)).toMatchObject({ error: 'UI_ITEM_NOT_FOUND' })
|
|
95
|
+
expect(stdout).toBe('')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('registry failures retain a stable code without leaking transport secrets', async () => {
|
|
99
|
+
globalThis.fetch = (async () => {
|
|
100
|
+
throw new Error('Authorization: Bearer npm_super_secret_value_that_must_not_escape')
|
|
101
|
+
}) as unknown as typeof fetch
|
|
102
|
+
const action = listCommand.action as (
|
|
103
|
+
query: string | undefined,
|
|
104
|
+
options: { json?: boolean; limit?: string },
|
|
105
|
+
) => Promise<void>
|
|
106
|
+
await expect(action('line-basic', { json: true, limit: '100' })).rejects.toBeInstanceOf(
|
|
107
|
+
ExitError,
|
|
108
|
+
)
|
|
109
|
+
expect(JSON.parse(stderr)).toEqual({
|
|
110
|
+
error: 'UI_REGISTRY_UNAVAILABLE',
|
|
111
|
+
message: 'Unable to reach npm UI release.',
|
|
112
|
+
})
|
|
113
|
+
expect(stderr).not.toContain('super_secret')
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
function mockFetch(seen: string[] = []): typeof fetch {
|
|
118
|
+
return (async (input: string | URL | Request) => {
|
|
119
|
+
const url = String(input)
|
|
120
|
+
seen.push(url)
|
|
121
|
+
if (url.endsWith('/@astrale-os/ui/beta')) return Response.json({ version: '0.3.0-beta.1' })
|
|
122
|
+
if (url.includes('/git/ref/tags/')) {
|
|
123
|
+
return Response.json({ object: { type: 'commit', sha: commit, url: '' } })
|
|
124
|
+
}
|
|
125
|
+
if (url.endsWith('/tooling/compatibility.json')) {
|
|
126
|
+
return Response.json({
|
|
127
|
+
version: 1,
|
|
128
|
+
shadcn: '4.18.0',
|
|
129
|
+
base: 'base',
|
|
130
|
+
style: 'nova',
|
|
131
|
+
baseUi: '1.7.0',
|
|
132
|
+
react: '^18.3.1 || ^19.0.0',
|
|
133
|
+
tailwind: '^4.3.3',
|
|
134
|
+
presets: ['astrale', 'compact', 'expressive'],
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
if (url.endsWith('/registry/patterns/chart/registry.json')) {
|
|
138
|
+
return Response.json({
|
|
139
|
+
items: [
|
|
140
|
+
{
|
|
141
|
+
...item,
|
|
142
|
+
files: item.files.map((file) => ({ ...file, path: 'line-basic.tsx' })),
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
if (url.endsWith('/registry.json')) {
|
|
148
|
+
return Response.json({ include: ['registry/patterns/chart/registry.json'] })
|
|
149
|
+
}
|
|
150
|
+
return new Response('not found', { status: 404 })
|
|
151
|
+
}) as typeof fetch
|
|
152
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../../program'
|
|
2
|
+
|
|
3
|
+
import { promptMultiSelect } from '../../lib/prompt'
|
|
4
|
+
import { addUi, listLockedUi, UiError } from '../../ui'
|
|
5
|
+
import { UI_JSON_OPTION, UI_PROJECT_OPTION, runUiCommand, type UiCommandOptions } from './shared'
|
|
6
|
+
|
|
7
|
+
type Options = UiCommandOptions & { dryRun?: boolean; overwrite?: boolean; yes?: boolean }
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
name: 'add',
|
|
11
|
+
description: 'Install consumer-owned Astrale pattern, block, or theme source',
|
|
12
|
+
arguments: [
|
|
13
|
+
{
|
|
14
|
+
name: 'items',
|
|
15
|
+
description: 'Canonical registry addresses or a local exported theme CSS file',
|
|
16
|
+
required: false,
|
|
17
|
+
variadic: true,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
options: [
|
|
21
|
+
UI_PROJECT_OPTION,
|
|
22
|
+
{ flags: '--dry-run', description: 'Show exact files and dependencies without writing' },
|
|
23
|
+
{ flags: '--overwrite', description: 'Allow replacing locally changed installed source' },
|
|
24
|
+
{ flags: '--yes', description: 'Confirm the planned operation non-interactively' },
|
|
25
|
+
UI_JSON_OPTION,
|
|
26
|
+
],
|
|
27
|
+
afterHelpText:
|
|
28
|
+
'\nInstalled source belongs to the application. Use theme/<name> for a released theme or ./theme.css for a playground export.\nOrdinary add never overwrites local edits. Run astrale ui doctor before intentionally replacing local source with --overwrite --yes.\n',
|
|
29
|
+
action: async (items: string[], options: Options) =>
|
|
30
|
+
runUiCommand(options, async () => {
|
|
31
|
+
let selected = items
|
|
32
|
+
if (selected.length === 0) {
|
|
33
|
+
if (process.argv.includes('--ci') || process.argv.includes('--no-prompt')) {
|
|
34
|
+
throw new UiError('UI_ITEM_NOT_FOUND', 'No UI item was provided in non-interactive mode.')
|
|
35
|
+
}
|
|
36
|
+
const available = await listLockedUi(options.project)
|
|
37
|
+
selected =
|
|
38
|
+
(await promptMultiSelect(
|
|
39
|
+
'Choose Astrale UI source to install',
|
|
40
|
+
available.map((item) => ({
|
|
41
|
+
name: item.title ?? item.meta.canonicalAddress,
|
|
42
|
+
value: item.meta.canonicalAddress,
|
|
43
|
+
description: item.description,
|
|
44
|
+
})),
|
|
45
|
+
)) ?? []
|
|
46
|
+
if (selected.length === 0)
|
|
47
|
+
throw new UiError('UI_ITEM_NOT_FOUND', 'No UI item was selected.')
|
|
48
|
+
}
|
|
49
|
+
return addUi(selected, options)
|
|
50
|
+
}),
|
|
51
|
+
} satisfies CommandDefinition
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../../program'
|
|
2
|
+
|
|
3
|
+
import { doctorUi, UiError } from '../../ui'
|
|
4
|
+
import { UI_JSON_OPTION, UI_PROJECT_OPTION, runUiCommand, type UiCommandOptions } from './shared'
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
name: 'doctor',
|
|
8
|
+
description: 'Verify Astrale UI package, CSS, config, lock, and installed source integrity',
|
|
9
|
+
arguments: [{ name: 'path', description: 'Application directory', required: false }],
|
|
10
|
+
options: [UI_PROJECT_OPTION, UI_JSON_OPTION],
|
|
11
|
+
action: async (path: string | undefined, options: UiCommandOptions) =>
|
|
12
|
+
runUiCommand(options, () => {
|
|
13
|
+
if (path && options.project) {
|
|
14
|
+
throw new UiError(
|
|
15
|
+
'UI_ITEM_CONFLICT',
|
|
16
|
+
'Choose either the positional application path or --project, not both.',
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
return doctorUi(options.project ?? path)
|
|
20
|
+
}),
|
|
21
|
+
} satisfies CommandDefinition
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../../program'
|
|
2
|
+
|
|
3
|
+
import { initUi, type UiPreset } from '../../ui'
|
|
4
|
+
import { UI_JSON_OPTION, runUiCommand, type UiCommandOptions } from './shared'
|
|
5
|
+
|
|
6
|
+
type Options = UiCommandOptions & {
|
|
7
|
+
preset?: UiPreset
|
|
8
|
+
version?: string
|
|
9
|
+
dryRun?: boolean
|
|
10
|
+
force?: boolean
|
|
11
|
+
install?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
name: 'init',
|
|
16
|
+
description: 'Initialize Astrale UI in an existing React and Tailwind v4 application',
|
|
17
|
+
arguments: [{ name: 'path', description: 'Application directory', required: false }],
|
|
18
|
+
options: [
|
|
19
|
+
{
|
|
20
|
+
flags: '--preset <name>',
|
|
21
|
+
description: 'Visual preset',
|
|
22
|
+
choices: ['astrale', 'compact', 'expressive'],
|
|
23
|
+
default: 'astrale',
|
|
24
|
+
},
|
|
25
|
+
{ flags: '--version <version>', description: 'Exact @astrale-os/ui version or release tag' },
|
|
26
|
+
{ flags: '--dry-run', description: 'Print the complete plan without writing or installing' },
|
|
27
|
+
{ flags: '--force', description: 'Replace an existing Astrale UI lock intentionally' },
|
|
28
|
+
{
|
|
29
|
+
flags: '--no-install',
|
|
30
|
+
description: 'Write configuration without running the package manager',
|
|
31
|
+
},
|
|
32
|
+
UI_JSON_OPTION,
|
|
33
|
+
],
|
|
34
|
+
afterHelpText:
|
|
35
|
+
'\nExamples:\n $ astrale ui init --preset astrale\n $ astrale ui init ./app --dry-run --json\n',
|
|
36
|
+
action: async (path: string | undefined, options: Options) =>
|
|
37
|
+
runUiCommand(options, () => initUi({ path, ...options })),
|
|
38
|
+
} satisfies CommandDefinition
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../../program'
|
|
2
|
+
|
|
3
|
+
import { listUi } from '../../ui'
|
|
4
|
+
import { UI_JSON_OPTION, runUiCommand, type UiCommandOptions } from './shared'
|
|
5
|
+
|
|
6
|
+
type Options = UiCommandOptions & { type?: string; limit?: string; version?: string }
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
name: 'list',
|
|
10
|
+
description: 'List or search Astrale patterns, blocks, and themes',
|
|
11
|
+
arguments: [{ name: 'query', description: 'Optional search text', required: false }],
|
|
12
|
+
options: [
|
|
13
|
+
{
|
|
14
|
+
flags: '--type <type>',
|
|
15
|
+
description: 'Restrict to pattern, block, or theme',
|
|
16
|
+
choices: ['pattern', 'block', 'theme'],
|
|
17
|
+
},
|
|
18
|
+
{ flags: '--limit <n>', description: 'Maximum results', default: '100' },
|
|
19
|
+
{ flags: '--version <version>', description: 'Exact release to inspect' },
|
|
20
|
+
UI_JSON_OPTION,
|
|
21
|
+
],
|
|
22
|
+
action: async (query: string | undefined, options: Options) =>
|
|
23
|
+
runUiCommand(options, () =>
|
|
24
|
+
listUi(query, { type: options.type, limit: Number(options.limit), version: options.version }),
|
|
25
|
+
),
|
|
26
|
+
} satisfies CommandDefinition
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../../program'
|
|
2
|
+
|
|
3
|
+
import { applyPreset, type UiPreset } from '../../ui'
|
|
4
|
+
import { UI_JSON_OPTION, UI_PROJECT_OPTION, runUiCommand, type UiCommandOptions } from './shared'
|
|
5
|
+
|
|
6
|
+
type Options = UiCommandOptions & { dryRun?: boolean }
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
name: 'apply',
|
|
10
|
+
description: 'Change the preset CSS import without rewriting component source',
|
|
11
|
+
arguments: [{ name: 'name', description: 'Preset name' }],
|
|
12
|
+
options: [
|
|
13
|
+
UI_PROJECT_OPTION,
|
|
14
|
+
{ flags: '--dry-run', description: 'Show the CSS and lock change without writing' },
|
|
15
|
+
UI_JSON_OPTION,
|
|
16
|
+
],
|
|
17
|
+
action: async (name: UiPreset, options: Options) =>
|
|
18
|
+
runUiCommand(options, () => applyPreset(name, options)),
|
|
19
|
+
} satisfies CommandDefinition
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CommandDefinition } from '../../program'
|
|
2
|
+
|
|
3
|
+
import { UI_PRESETS } from '../../ui'
|
|
4
|
+
import { UI_JSON_OPTION, runUiCommand, type UiCommandOptions } from './shared'
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
name: 'list',
|
|
8
|
+
description: 'List qualified Astrale UI visual presets',
|
|
9
|
+
options: [UI_JSON_OPTION],
|
|
10
|
+
action: async (options: UiCommandOptions) =>
|
|
11
|
+
runUiCommand(options, async () => UI_PRESETS.map((name) => ({ name }))),
|
|
12
|
+
} satisfies CommandDefinition
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { fatal } from '../../lib/log'
|
|
2
|
+
import { output } from '../../lib/output'
|
|
3
|
+
|
|
4
|
+
export type UiCommandOptions = { json?: boolean; project?: string }
|
|
5
|
+
|
|
6
|
+
export async function runUiCommand(
|
|
7
|
+
options: UiCommandOptions,
|
|
8
|
+
operation: () => Promise<unknown>,
|
|
9
|
+
): Promise<void> {
|
|
10
|
+
try {
|
|
11
|
+
output(await operation(), { json: options.json })
|
|
12
|
+
} catch (error) {
|
|
13
|
+
fatal(error, { json: options.json })
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const UI_PROJECT_OPTION = {
|
|
18
|
+
flags: '--project <path>',
|
|
19
|
+
description: 'Existing application root (defaults to the current project)',
|
|
20
|
+
} as const
|
|
21
|
+
|
|
22
|
+
export const UI_JSON_OPTION = {
|
|
23
|
+
flags: '--json',
|
|
24
|
+
description: 'Emit one machine-readable JSON value',
|
|
25
|
+
} as const
|
package/src/commands/update.ts
CHANGED
|
@@ -11,8 +11,13 @@ import {
|
|
|
11
11
|
inDomainProject,
|
|
12
12
|
type SdkOutdated,
|
|
13
13
|
} from '../lib/sdk-deps'
|
|
14
|
-
import {
|
|
15
|
-
|
|
14
|
+
import {
|
|
15
|
+
checkAstraleSkills,
|
|
16
|
+
type SkillApplyResult,
|
|
17
|
+
type SkillCheckResult,
|
|
18
|
+
syncAstraleSkills,
|
|
19
|
+
} from '../lib/skills'
|
|
20
|
+
import { DEFAULT_UPDATE_CHANNEL, packageManagedUpdateError, updateAstrale } from '../lib/update'
|
|
16
21
|
|
|
17
22
|
type UpdateOpts = RawOutputOpts & {
|
|
18
23
|
check?: boolean
|
|
@@ -23,26 +28,26 @@ type UpdateOpts = RawOutputOpts & {
|
|
|
23
28
|
yes?: boolean
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
log.
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
log.warn(`
|
|
31
|
+
async function refreshSkills(): Promise<SkillApplyResult> {
|
|
32
|
+
log.step('Ensuring Astrale agent skills are current and healthy')
|
|
33
|
+
const result = await syncAstraleSkills()
|
|
34
|
+
if (result.status === 'unchanged') log.success('Astrale skills already up to date')
|
|
35
|
+
else if (result.status === 'installed') log.success('Astrale skills installed')
|
|
36
|
+
else if (result.status === 'updated') log.success('Astrale skills updated')
|
|
37
|
+
else if (result.status === 'repaired') log.success('Astrale skills repaired and updated')
|
|
38
|
+
return result
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function skillCheckStale(skills: SkillCheckResult): boolean {
|
|
42
|
+
return skills.status === 'update-available' || skills.status === 'repair-needed'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function printSkillCheck(skills: SkillCheckResult): void {
|
|
46
|
+
if (skills.status === 'current') log.success('Astrale skills are up to date')
|
|
47
|
+
else if (skills.status === 'update-available') log.info('Astrale skills update available')
|
|
48
|
+
else if (skills.status === 'repair-needed') log.warn('Astrale skills need repair')
|
|
49
|
+
else if (skills.status === 'unavailable') {
|
|
50
|
+
log.warn(`Could not verify Astrale skills${skills.error ? `: ${skills.error}` : ''}`)
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
|
|
@@ -104,14 +109,22 @@ async function refreshSdkDeps(check: boolean, assumeYes = false): Promise<boolea
|
|
|
104
109
|
/**
|
|
105
110
|
* Read-only staleness report for tooling — `astrale update --check --json`.
|
|
106
111
|
* domain-studio polls this on load to drive its "update available" badge. It is
|
|
107
|
-
* unified and NON-THROWING:
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
112
|
+
* unified and NON-THROWING: an explicit package-managed result uses npm release
|
|
113
|
+
* identity, while script-install failures remain script failures in `error`
|
|
114
|
+
* instead of being recategorized. The SDK axis is already best-effort. Skills
|
|
115
|
+
* report meaningful health/freshness states without exposing installer metadata.
|
|
111
116
|
*/
|
|
112
117
|
export type StaleReport = {
|
|
113
118
|
stale: boolean
|
|
114
|
-
cli: {
|
|
119
|
+
cli: {
|
|
120
|
+
stale: boolean
|
|
121
|
+
managed: boolean
|
|
122
|
+
current?: string
|
|
123
|
+
latest?: string
|
|
124
|
+
channel?: string
|
|
125
|
+
error?: string
|
|
126
|
+
}
|
|
127
|
+
skills: SkillCheckResult
|
|
115
128
|
sdk: { stale: boolean; inProject: boolean; outdated: SdkOutdated[] }
|
|
116
129
|
}
|
|
117
130
|
|
|
@@ -138,6 +151,15 @@ export async function cliStale(
|
|
|
138
151
|
version: target.version,
|
|
139
152
|
currentVersion: running,
|
|
140
153
|
})
|
|
154
|
+
if (r.status === 'managed') {
|
|
155
|
+
const latest = await dependencies.fetchPackageVersion(target).catch(() => undefined)
|
|
156
|
+
return {
|
|
157
|
+
stale: latest !== undefined && latest !== running,
|
|
158
|
+
managed: true,
|
|
159
|
+
current: running,
|
|
160
|
+
...(latest === undefined ? {} : { latest, channel: 'npm' }),
|
|
161
|
+
}
|
|
162
|
+
}
|
|
141
163
|
if (r.status === 'updated') {
|
|
142
164
|
return {
|
|
143
165
|
stale: false,
|
|
@@ -154,13 +176,12 @@ export async function cliStale(
|
|
|
154
176
|
latest: r.latestVersion,
|
|
155
177
|
channel: r.channel,
|
|
156
178
|
}
|
|
157
|
-
} catch {
|
|
158
|
-
const latest = await dependencies.fetchPackageVersion(target).catch(() => undefined)
|
|
179
|
+
} catch (error) {
|
|
159
180
|
return {
|
|
160
|
-
stale:
|
|
161
|
-
managed:
|
|
181
|
+
stale: false,
|
|
182
|
+
managed: false,
|
|
162
183
|
current: running,
|
|
163
|
-
|
|
184
|
+
error: error instanceof Error ? error.message : String(error),
|
|
164
185
|
}
|
|
165
186
|
}
|
|
166
187
|
}
|
|
@@ -202,7 +223,7 @@ export default {
|
|
|
202
223
|
default: DEFAULT_UPDATE_CHANNEL,
|
|
203
224
|
},
|
|
204
225
|
{ flags: '--version <version>', description: 'Update to an exact version tag' },
|
|
205
|
-
{ flags: '--no-skills', description: 'Skip
|
|
226
|
+
{ flags: '--no-skills', description: 'Skip ensuring the Astrale agent skills' },
|
|
206
227
|
{ flags: '--no-deps', description: 'Skip checking @astrale-os SDK dependency versions' },
|
|
207
228
|
{
|
|
208
229
|
flags: '--yes',
|
|
@@ -215,23 +236,22 @@ Behavior:
|
|
|
215
236
|
Keeps three things current, in order. (1) The CLI binary: updates official
|
|
216
237
|
script installs only — if Astrale was installed by another package manager this
|
|
217
238
|
command refuses so that manager stays in charge; downloads are checksum-verified
|
|
218
|
-
before the binary is replaced. (2) The agent skills:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
239
|
+
before the binary is replaced. (2) The Astrale agent skills: installs every
|
|
240
|
+
top-level skill published from astrale-os/cli main, updates healthy older
|
|
241
|
+
installs, repairs inconsistent installs, and verifies the result before
|
|
242
|
+
reporting success. (3) SDK deps: inside a pnpm domain
|
|
222
243
|
project, proposes any @astrale-os/* dependency with a newer release and, on
|
|
223
244
|
confirm, runs "pnpm update --latest --lockfile-only" (updates package.json AND
|
|
224
245
|
the lockfile, honoring your registry + supply-chain age policy; run "pnpm
|
|
225
246
|
install" to materialize).
|
|
226
247
|
|
|
227
248
|
The default release channel is beta; --channel overrides it for one run.
|
|
228
|
-
--check is a dry run (binary + SDK deps; exit 10 if anything is available) and
|
|
249
|
+
--check is a dry run (binary + skills + SDK deps; exit 10 if anything is available) and
|
|
229
250
|
never writes. With --json it emits a unified staleness report
|
|
230
|
-
({ stale, cli, sdk }) for tooling
|
|
231
|
-
along with an update). --yes applies all three non-interactively (no prompts) and
|
|
251
|
+
({ stale, cli, skills, sdk }) for tooling. --yes applies all three non-interactively and
|
|
232
252
|
is resilient — a binary that can't self-update (package-managed) warns but never
|
|
233
|
-
blocks the skills/deps steps;
|
|
234
|
-
--no-skills / --no-deps skip those
|
|
253
|
+
blocks the skills/deps steps; a skill failure fails the command rather than
|
|
254
|
+
claiming a partial success. --no-skills / --no-deps explicitly skip those axes.
|
|
235
255
|
|
|
236
256
|
Examples:
|
|
237
257
|
$ astrale update
|
|
@@ -246,11 +266,18 @@ Examples:
|
|
|
246
266
|
try {
|
|
247
267
|
// Tooling path: a machine-readable `--check` (e.g. domain-studio's update
|
|
248
268
|
// badge polling `astrale update --check --json`) gets a unified,
|
|
249
|
-
// non-throwing staleness report
|
|
269
|
+
// non-throwing staleness report and exits.
|
|
250
270
|
if (opts.check && isMachine(opts)) {
|
|
251
271
|
const cli = await cliStale(opts)
|
|
272
|
+
const skills: SkillCheckResult =
|
|
273
|
+
opts.skills === false ? { status: 'skipped' } : await checkAstraleSkills()
|
|
252
274
|
const sdk = await sdkStale()
|
|
253
|
-
const report: StaleReport = {
|
|
275
|
+
const report: StaleReport = {
|
|
276
|
+
stale: cli.stale || skillCheckStale(skills) || sdk.stale,
|
|
277
|
+
cli,
|
|
278
|
+
skills,
|
|
279
|
+
sdk,
|
|
280
|
+
}
|
|
254
281
|
output(report, opts)
|
|
255
282
|
if (report.stale) process.exitCode = 10
|
|
256
283
|
return
|
|
@@ -294,11 +321,25 @@ Examples:
|
|
|
294
321
|
log.success(`Updated astrale ${result.previousVersion} -> ${result.currentVersion}`)
|
|
295
322
|
log.dim(` channel: ${result.channel}`)
|
|
296
323
|
log.dim(` binary: ${result.bin}`)
|
|
324
|
+
} else if (result?.status === 'managed') {
|
|
325
|
+
const error = packageManagedUpdateError(result.executable)
|
|
326
|
+
if (!opts.yes) throw error
|
|
327
|
+
log.warn(`CLI self-update skipped: ${error.message}`)
|
|
297
328
|
}
|
|
298
329
|
|
|
299
|
-
// Axis B — agent skills.
|
|
300
|
-
//
|
|
301
|
-
if (
|
|
330
|
+
// Axis B — agent skills. A successful real update guarantees a verified
|
|
331
|
+
// latest cohort; --check remains read-only and reports its status.
|
|
332
|
+
if (opts.skills !== false) {
|
|
333
|
+
if (opts.check) {
|
|
334
|
+
const skills = await checkAstraleSkills()
|
|
335
|
+
printSkillCheck(skills)
|
|
336
|
+
if (skillCheckStale(skills)) anyAvailable = true
|
|
337
|
+
} else {
|
|
338
|
+
await refreshSkills()
|
|
339
|
+
}
|
|
340
|
+
} else if (!opts.check) {
|
|
341
|
+
log.dim(' Astrale skills skipped (--no-skills)')
|
|
342
|
+
}
|
|
302
343
|
|
|
303
344
|
// Axis C — first-party @astrale-os/* deps in the current domain project.
|
|
304
345
|
// Runs on --check too (reports availability); --yes applies without a prompt.
|
|
@@ -308,7 +349,7 @@ Examples:
|
|
|
308
349
|
|
|
309
350
|
if (opts.check && anyAvailable) process.exitCode = 10
|
|
310
351
|
} catch (e) {
|
|
311
|
-
fatal(e)
|
|
352
|
+
fatal(e, opts)
|
|
312
353
|
}
|
|
313
354
|
},
|
|
314
355
|
} satisfies CommandDefinition
|