@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
package/src/commands/call.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type { ConnectionContext, KernelCommandOpts } from '../connection'
|
|
|
4
4
|
import type { CommandDefinition } from '../program/index'
|
|
5
5
|
|
|
6
6
|
import { createPathCall, expandSelfInCall, runKernelCommand, withSelfHint } from '../connection'
|
|
7
|
-
import { presentBinary } from '../lib/binary'
|
|
8
|
-
import {
|
|
7
|
+
import { presentBinary, readBinaryBody } from '../lib/binary'
|
|
8
|
+
import { failInput, log } from '../lib/log'
|
|
9
9
|
import { output, present } from '../lib/output'
|
|
10
10
|
|
|
11
11
|
type CallOpts = KernelCommandOpts & {
|
|
@@ -15,8 +15,20 @@ type CallOpts = KernelCommandOpts & {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
type CallResult = Awaited<ReturnType<ConnectionContext['session']['dispatch']>>
|
|
18
|
+
type BinaryCallResult = Extract<CallResult, { readonly kind: 'binary' }>
|
|
19
|
+
type BinaryCallInput = Omit<BinaryCallResult, 'value'> & {
|
|
20
|
+
readonly value: Omit<BinaryCallResult['value'], 'body' | 'status'> & {
|
|
21
|
+
readonly body: Uint8Array | AsyncIterable<Uint8Array>
|
|
22
|
+
readonly status?: number
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
type CallResultInput = Exclude<CallResult, { readonly kind: 'binary' }> | BinaryCallInput
|
|
26
|
+
type MaterializedBinaryCallResult = Omit<BinaryCallResult, 'value'> & {
|
|
27
|
+
readonly value: Omit<BinaryCallInput['value'], 'body'> & { readonly body: Uint8Array }
|
|
28
|
+
}
|
|
18
29
|
type MaterializedCallResult =
|
|
19
|
-
| Exclude<CallResult, { readonly kind: 'stream' }>
|
|
30
|
+
| Exclude<CallResult, { readonly kind: 'binary' | 'stream' }>
|
|
31
|
+
| MaterializedBinaryCallResult
|
|
20
32
|
| { readonly kind: 'stream'; readonly values: readonly unknown[] }
|
|
21
33
|
|
|
22
34
|
export async function callCommand(
|
|
@@ -24,64 +36,60 @@ export async function callCommand(
|
|
|
24
36
|
rawParams: string[],
|
|
25
37
|
opts: CallOpts,
|
|
26
38
|
): Promise<void> {
|
|
27
|
-
// Expand @self before describe/execute through authenticated Identity.whoami.
|
|
28
|
-
let expanded: Awaited<ReturnType<typeof expandSelfInCall>>
|
|
29
|
-
try {
|
|
30
|
-
expanded = await expandSelfInCall(path, rawParams, opts)
|
|
31
|
-
} catch (error) {
|
|
32
|
-
failClosed(error, opts)
|
|
33
|
-
}
|
|
34
|
-
const expandedPath = expanded.path
|
|
35
|
-
try {
|
|
36
|
-
Path.parse(expandedPath)
|
|
37
|
-
} catch (error) {
|
|
38
|
-
failClosed(error, opts)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// ── Parse params ────────────────────────────────────────
|
|
42
39
|
let params: Record<string, unknown>
|
|
43
40
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
// ── Dry-run: show what would be sent ─────────────────────
|
|
50
|
-
if (opts.dryRun) {
|
|
51
|
-
output({ method: expandedPath, params }, opts)
|
|
52
|
-
return
|
|
41
|
+
Path.parse(path)
|
|
42
|
+
params = await parseParams(rawParams, opts.data)
|
|
43
|
+
} catch (error) {
|
|
44
|
+
failInput(error, opts)
|
|
53
45
|
}
|
|
54
46
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
47
|
+
await runKernelCommand<MaterializedCallResult | { readonly kind: 'dry'; readonly call: unknown }>(
|
|
48
|
+
{
|
|
49
|
+
opts,
|
|
50
|
+
label: path,
|
|
51
|
+
fn: async (ctx) => {
|
|
52
|
+
const expanded = await expandSelfInCall(path, params, ctx)
|
|
53
|
+
const request = createPathCall(expanded.path, expanded.parameters)
|
|
54
|
+
if (opts.dryRun) return { kind: 'dry', call: request }
|
|
55
|
+
return withSelfHint(
|
|
56
|
+
async () => materializeCallResult(await ctx.session.dispatch(request)),
|
|
57
|
+
expanded.meta,
|
|
58
|
+
)
|
|
59
|
+
},
|
|
60
|
+
format: async (result, fmtOpts) => {
|
|
61
|
+
switch (result.kind) {
|
|
62
|
+
case 'dry':
|
|
63
|
+
output(result.call, fmtOpts)
|
|
64
|
+
return
|
|
65
|
+
case 'value':
|
|
66
|
+
present(result.value, fmtOpts)
|
|
67
|
+
return
|
|
68
|
+
case 'binary':
|
|
69
|
+
await presentBinary(result.value, fmtOpts, { outFile: opts.output })
|
|
70
|
+
return
|
|
71
|
+
case 'stream':
|
|
72
|
+
output(result.values, fmtOpts)
|
|
73
|
+
return
|
|
74
|
+
case 'redirect':
|
|
75
|
+
throw new Error('Client Session returned an unresolved redirect.')
|
|
76
|
+
}
|
|
77
|
+
},
|
|
79
78
|
},
|
|
80
|
-
|
|
79
|
+
)
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/** Drain a session-backed stream before the command-scoped Client Session closes. */
|
|
84
|
-
export async function materializeCallResult(
|
|
83
|
+
export async function materializeCallResult(
|
|
84
|
+
result: CallResultInput,
|
|
85
|
+
): Promise<MaterializedCallResult> {
|
|
86
|
+
if (result.kind === 'binary') {
|
|
87
|
+
const body = await readBinaryBody(result.value.body)
|
|
88
|
+
return Object.freeze({
|
|
89
|
+
...result,
|
|
90
|
+
value: Object.freeze({ ...result.value, body }),
|
|
91
|
+
})
|
|
92
|
+
}
|
|
85
93
|
if (result.kind !== 'stream') return result
|
|
86
94
|
const values: unknown[] = []
|
|
87
95
|
for await (const value of result.stream) values.push(value)
|
|
@@ -101,7 +109,7 @@ export async function parseParams(
|
|
|
101
109
|
try {
|
|
102
110
|
return JSON.parse(dataFlag)
|
|
103
111
|
} catch {
|
|
104
|
-
throw new
|
|
112
|
+
throw new TypeError(`Invalid JSON in --data: ${dataFlag}`)
|
|
105
113
|
}
|
|
106
114
|
}
|
|
107
115
|
|
|
@@ -114,7 +122,7 @@ export async function parseParams(
|
|
|
114
122
|
try {
|
|
115
123
|
return JSON.parse(stdin)
|
|
116
124
|
} catch {
|
|
117
|
-
throw new
|
|
125
|
+
throw new TypeError('Invalid JSON from stdin')
|
|
118
126
|
}
|
|
119
127
|
}
|
|
120
128
|
|
|
@@ -142,7 +150,7 @@ export function parseKeyValue(pairs: string[]): Record<string, unknown> {
|
|
|
142
150
|
for (const pair of pairs) {
|
|
143
151
|
const eqIdx = pair.indexOf('=')
|
|
144
152
|
if (eqIdx === -1) {
|
|
145
|
-
throw new
|
|
153
|
+
throw new TypeError(`Invalid param "${pair}" — expected key=value format`)
|
|
146
154
|
}
|
|
147
155
|
const key = pair.slice(0, eqIdx)
|
|
148
156
|
const raw = pair.slice(eqIdx + 1)
|
|
@@ -150,7 +158,7 @@ export function parseKeyValue(pairs: string[]): Record<string, unknown> {
|
|
|
150
158
|
const hint = key.endsWith(':')
|
|
151
159
|
? ` (looks like httpie's "key:=value" syntax — Astrale CLI doesn't support it; use --data '{"${key.slice(0, -1)}":<value>}' for nested values)`
|
|
152
160
|
: ` (keys must be identifier-shaped: letters, digits, underscore, hyphen)`
|
|
153
|
-
throw new
|
|
161
|
+
throw new TypeError(`Invalid param key "${key}" in "${pair}"${hint}`)
|
|
154
162
|
}
|
|
155
163
|
result[key] = coerceValue(raw)
|
|
156
164
|
}
|
|
@@ -184,6 +192,10 @@ Behavior:
|
|
|
184
192
|
input without executing. Remote-bound functions auto-mint a
|
|
185
193
|
worker-scoped credential; --creds overrides it.
|
|
186
194
|
|
|
195
|
+
Streaming binary bodies are consumed while the Client session remains live,
|
|
196
|
+
then presented through the same --output, --raw, and --json paths as buffered
|
|
197
|
+
binary. JSON retains the application HTTP status and text/base64 body.
|
|
198
|
+
|
|
187
199
|
Self-reference:
|
|
188
200
|
@self expands to your nodeId on the active instance (path head or
|
|
189
201
|
bare param value, e.g. node=@self). --data and stdin payloads are
|
|
@@ -194,7 +206,7 @@ Self-reference:
|
|
|
194
206
|
Callable input/output lives on astrale introspect <path>.
|
|
195
207
|
|
|
196
208
|
Examples:
|
|
197
|
-
$ astrale introspect /:
|
|
209
|
+
$ astrale introspect /:kernel.astrale.ai:class.Identity:whois
|
|
198
210
|
$ astrale call /:blog.acme.com:class.Author:list limit=10
|
|
199
211
|
$ astrale call '@self::deactivate'
|
|
200
212
|
$ astrale call /:kernel.astrale.ai:function.journal --data '{"limit":5}' --json
|
|
@@ -203,7 +215,7 @@ Examples:
|
|
|
203
215
|
{
|
|
204
216
|
name: 'path',
|
|
205
217
|
description:
|
|
206
|
-
'Operation path (e.g., /:
|
|
218
|
+
'Operation path (e.g., /:kernel.astrale.ai:class.Identity:whois or /node::method)',
|
|
207
219
|
},
|
|
208
220
|
{ name: 'params...', description: 'Params as key=value pairs', required: false },
|
|
209
221
|
],
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import type { InstallRequest, InstallResult, OperationId } from '@astrale-os/sdk/client/schema'
|
|
2
|
+
|
|
3
3
|
import chalk from 'chalk'
|
|
4
4
|
|
|
5
5
|
import type { KernelCommandOpts } from '../../connection'
|
|
6
6
|
import type { CommandDefinition } from '../../program/index'
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { runKernelCommand, withAdminClientSession } from '../../connection'
|
|
9
9
|
import { formatKernelError } from '../../connection/errors'
|
|
10
10
|
import { AstraleError } from '../../errors'
|
|
11
11
|
import {
|
|
@@ -23,35 +23,61 @@ import { confirmWithInput, promptText, selectFrom } from '../../lib/prompt'
|
|
|
23
23
|
import { isHttpUrl } from '../../lib/validation'
|
|
24
24
|
|
|
25
25
|
/** Public Kernel install syscall input for one remote URL. */
|
|
26
|
-
export function directInstallCallInput(
|
|
26
|
+
export function directInstallCallInput(
|
|
27
|
+
url: string,
|
|
28
|
+
operation: string,
|
|
29
|
+
token?: string,
|
|
30
|
+
): InstallRequest {
|
|
31
|
+
const domain = Object.freeze({
|
|
32
|
+
publication: Object.freeze({
|
|
33
|
+
url,
|
|
34
|
+
...(token === undefined ? {} : { token }),
|
|
35
|
+
}),
|
|
36
|
+
})
|
|
27
37
|
return Object.freeze({
|
|
28
|
-
operation,
|
|
29
|
-
domains: [
|
|
30
|
-
Object.freeze({
|
|
31
|
-
source: Object.freeze({
|
|
32
|
-
kind: 'remote' as const,
|
|
33
|
-
url,
|
|
34
|
-
...(token === undefined ? {} : { token }),
|
|
35
|
-
}),
|
|
36
|
-
}),
|
|
37
|
-
],
|
|
38
|
+
operation: acceptOperationId(operation),
|
|
39
|
+
domains: Object.freeze([domain] as const),
|
|
38
40
|
})
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
export interface DirectInstallPresentation {
|
|
42
44
|
readonly operation: string
|
|
43
|
-
readonly
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
readonly origin: string
|
|
46
|
+
readonly revision: string
|
|
47
|
+
readonly status: 'installed' | 'already current'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Stable CLI presentation derived from the canonical binary install result. */
|
|
51
|
+
export function directInstallPresentation(
|
|
52
|
+
result: InstallResult,
|
|
53
|
+
requestedOperation: string,
|
|
54
|
+
): DirectInstallPresentation {
|
|
55
|
+
if (result.changed) {
|
|
56
|
+
const installed = result.receipt.transitions[0]?.intent
|
|
57
|
+
if (!installed) throw new Error('Kernel install returned no committed Domain transition.')
|
|
58
|
+
if (!installed.generation) {
|
|
59
|
+
throw new Error('Kernel install returned a committed transition without a Domain generation.')
|
|
47
60
|
}
|
|
48
|
-
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
operation: result.receipt.operation,
|
|
63
|
+
origin: installed.origin,
|
|
64
|
+
revision: installed.generation.revision,
|
|
65
|
+
status: 'installed' as const,
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
const installed = result.domains[0]
|
|
69
|
+
return Object.freeze({
|
|
70
|
+
operation: requestedOperation,
|
|
71
|
+
origin: installed.origin,
|
|
72
|
+
revision: installed.revision,
|
|
73
|
+
status: 'already current' as const,
|
|
74
|
+
})
|
|
49
75
|
}
|
|
50
76
|
|
|
51
77
|
const OPERATION_ID_PATTERN =
|
|
52
78
|
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u
|
|
53
79
|
|
|
54
|
-
function acceptOperationId(input: unknown):
|
|
80
|
+
function acceptOperationId(input: unknown): OperationId {
|
|
55
81
|
if (typeof input !== 'string' || !OPERATION_ID_PATTERN.test(input)) {
|
|
56
82
|
throw new AstraleError(
|
|
57
83
|
'INVALID_FLAG',
|
|
@@ -59,10 +85,10 @@ function acceptOperationId(input: unknown): string {
|
|
|
59
85
|
'Omit --operation for a fresh install; use it only with the exact UUID printed for recovery.',
|
|
60
86
|
)
|
|
61
87
|
}
|
|
62
|
-
return input
|
|
88
|
+
return input as OperationId
|
|
63
89
|
}
|
|
64
90
|
|
|
65
|
-
function createOperationId():
|
|
91
|
+
function createOperationId(): OperationId {
|
|
66
92
|
return acceptOperationId(globalThis.crypto.randomUUID())
|
|
67
93
|
}
|
|
68
94
|
|
|
@@ -400,6 +426,7 @@ export async function installDirect(
|
|
|
400
426
|
target,
|
|
401
427
|
host,
|
|
402
428
|
opts.allowIdentityOverride ?? false,
|
|
429
|
+
isMachine(opts),
|
|
403
430
|
)
|
|
404
431
|
} catch (e) {
|
|
405
432
|
fatal(e, opts)
|
|
@@ -407,36 +434,31 @@ export async function installDirect(
|
|
|
407
434
|
const url = target as string
|
|
408
435
|
const retry = directInstallRetry(url, operation, opts)
|
|
409
436
|
|
|
410
|
-
await direct.runKernelCommand<
|
|
437
|
+
await direct.runKernelCommand<InstallResult>({
|
|
411
438
|
opts,
|
|
412
439
|
label: `Installing domain from ${url} (operation ${operation})`,
|
|
413
440
|
recovery: { operation, retry },
|
|
414
441
|
fn: async ({ session }) =>
|
|
415
|
-
(
|
|
416
|
-
createPathCall(
|
|
417
|
-
Path.project(syscalls.install.ref).raw,
|
|
418
|
-
directInstallCallInput(url, operation, opts.token),
|
|
419
|
-
),
|
|
420
|
-
)) as DirectInstallResult,
|
|
442
|
+
session.schema.install(directInstallCallInput(url, operation, opts.token)),
|
|
421
443
|
format: (result, fmtOpts, isRaw) => {
|
|
422
444
|
if (isRaw) {
|
|
423
445
|
output(result, fmtOpts)
|
|
424
446
|
return
|
|
425
447
|
}
|
|
426
|
-
const installed = result
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
log.success(`Domain installed: ${installed.origin}@${revision}`)
|
|
430
|
-
log.dim(` operation: ${result.operation}`)
|
|
448
|
+
const installed = directInstallPresentation(result, operation)
|
|
449
|
+
log.success(`Domain ${installed.status}: ${installed.origin}@${installed.revision}`)
|
|
450
|
+
log.dim(` operation: ${installed.operation}`)
|
|
431
451
|
// Belt-and-braces: the kernel-confirmed origin is authoritative. If it
|
|
432
452
|
// aliases the host and the pre-install gate never consented to THAT
|
|
433
453
|
// origin (lying or unavailable Publication), say so loudly after the fact.
|
|
434
454
|
if (isIdentityOverride(installed.origin, host) && installed.origin !== consentedOrigin) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
`
|
|
438
|
-
|
|
439
|
-
|
|
455
|
+
if (!isMachine(fmtOpts)) {
|
|
456
|
+
log.warn(
|
|
457
|
+
`Installed origin "${installed.origin}" differs from the serving host "${host}" ` +
|
|
458
|
+
`and was not confirmed before install (the worker Publication was unavailable). ` +
|
|
459
|
+
`Every ${installed.origin}/* call on this instance now routes to ${host}.`,
|
|
460
|
+
)
|
|
461
|
+
}
|
|
440
462
|
}
|
|
441
463
|
},
|
|
442
464
|
})
|
|
@@ -493,20 +515,25 @@ async function ensureIdentityOverrideConsent(
|
|
|
493
515
|
url: string,
|
|
494
516
|
host: string,
|
|
495
517
|
allow: boolean,
|
|
518
|
+
machine: boolean,
|
|
496
519
|
): Promise<string | undefined> {
|
|
497
520
|
const origin = await probeDeclaredOrigin(url)
|
|
498
521
|
if (origin === undefined) {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
522
|
+
if (!machine) {
|
|
523
|
+
log.warn(
|
|
524
|
+
`Could not read a declared origin from ` +
|
|
525
|
+
`${new URL('/.well-known/astrale/domain.json', url).href} — ` +
|
|
526
|
+
`skipping the pre-install identity check (the installed origin is verified after install).`,
|
|
527
|
+
)
|
|
528
|
+
}
|
|
504
529
|
return undefined
|
|
505
530
|
}
|
|
506
531
|
if (!isIdentityOverride(origin, host)) return undefined
|
|
507
532
|
|
|
508
533
|
if (allow) {
|
|
509
|
-
|
|
534
|
+
if (!machine) {
|
|
535
|
+
log.warn(`Identity override consented via --allow-identity-override: ${origin} ← ${host}`)
|
|
536
|
+
}
|
|
510
537
|
return origin
|
|
511
538
|
}
|
|
512
539
|
|
|
@@ -73,7 +73,7 @@ Behavior:
|
|
|
73
73
|
or with --json/--raw (agent-friendly — full DomainInfo objects). -q prints
|
|
74
74
|
one install URL per line (pipeable into \`domain install\`); --count prints
|
|
75
75
|
only the number. --default-only keeps the install-by-default entries (what
|
|
76
|
-
every new instance
|
|
76
|
+
every new instance receives during Admin-managed provisioning). --check probes each published URL's
|
|
77
77
|
canonical Publication and adds a live/unreachable STATUS column
|
|
78
78
|
(+ reachable/schemaRevision in machine output).
|
|
79
79
|
|
|
@@ -3,9 +3,11 @@ import chalk from 'chalk'
|
|
|
3
3
|
import type { KernelCommandOpts } from '../../connection'
|
|
4
4
|
import type { CommandDefinition } from '../../program/index'
|
|
5
5
|
|
|
6
|
+
import { formatKernelError } from '../../connection/errors'
|
|
6
7
|
import { publishAdminDomain } from '../../lib/admin-domain'
|
|
7
8
|
import { ADMIN_TARGET_OPTIONS, type AdminTargetCommandOpts } from '../../lib/admin-target'
|
|
8
|
-
import {
|
|
9
|
+
import { domainPublicationUrl } from '../../lib/domain-publication'
|
|
10
|
+
import { withSpinner } from '../../lib/log'
|
|
9
11
|
import { isMachine, output } from '../../lib/output'
|
|
10
12
|
import { promptText } from '../../lib/prompt'
|
|
11
13
|
import { isHttpUrl, validateName, validateUrl } from '../../lib/validation'
|
|
@@ -48,9 +50,9 @@ Behavior:
|
|
|
48
50
|
|
|
49
51
|
Publishing only makes the domain INSTALLABLE. Mount it on an instance with
|
|
50
52
|
\`astrale domain install <url>\` (or rely on the admin's install-by-default
|
|
51
|
-
policy).
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
policy). Deployment and catalog publication are separate owners: run the
|
|
54
|
+
project's \`astrale-domain deploy <environment>\`, then publish its observed
|
|
55
|
+
public URL with this command.
|
|
54
56
|
|
|
55
57
|
Run in a terminal with flags omitted and it PROMPTS for origin / name /
|
|
56
58
|
public-url (origin defaults to the URL host, name to the origin's first
|
|
@@ -68,17 +70,16 @@ Examples:
|
|
|
68
70
|
{ flags: '--description <text>', description: 'Optional human description for the catalog' },
|
|
69
71
|
{
|
|
70
72
|
flags: '--install-by-default',
|
|
71
|
-
description: 'Mark the domain for install on every new instance
|
|
73
|
+
description: 'Mark the domain for install on every new instance',
|
|
72
74
|
},
|
|
73
75
|
],
|
|
74
76
|
// No positional arguments → Commander passes (opts, command); `opts` is first.
|
|
75
77
|
action: async (opts: PublishOpts) => {
|
|
76
78
|
try {
|
|
77
79
|
// Interactive fill (TTY only): a human running this by hand is prompted for
|
|
78
|
-
// any missing field.
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
// so a piped / agent / LLM run fails fast instead of hanging on a read.
|
|
80
|
+
// any missing field. Automation passes every flag. No TTY / --ci /
|
|
81
|
+
// --no-prompt / CI env means no prompt: fall straight through to the
|
|
82
|
+
// required-flag error below so a piped or agent run fails fast.
|
|
82
83
|
const interactive = !!process.stdin.isTTY && !(opts.ci || opts.noPrompt || process.env.CI)
|
|
83
84
|
let { origin, name, publicUrl } = opts
|
|
84
85
|
if (interactive) {
|
|
@@ -102,6 +103,7 @@ Examples:
|
|
|
102
103
|
validateName(origin, 'origin')
|
|
103
104
|
validateName(name, 'domain')
|
|
104
105
|
validateUrl(publicUrl)
|
|
106
|
+
const discoveryUrl = domainPublicationUrl(publicUrl).href
|
|
105
107
|
|
|
106
108
|
const result = await withSpinner(
|
|
107
109
|
`Publishing ${name} → ${publicUrl}`,
|
|
@@ -110,7 +112,7 @@ Examples:
|
|
|
110
112
|
publishAdminDomain(opts, {
|
|
111
113
|
origin,
|
|
112
114
|
name,
|
|
113
|
-
url:
|
|
115
|
+
url: discoveryUrl,
|
|
114
116
|
...(opts.description ? { description: opts.description } : {}),
|
|
115
117
|
...(opts.installByDefault ? { installByDefault: true } : {}),
|
|
116
118
|
}),
|
|
@@ -127,7 +129,8 @@ Examples:
|
|
|
127
129
|
return
|
|
128
130
|
}
|
|
129
131
|
} catch (e) {
|
|
130
|
-
|
|
132
|
+
await formatKernelError(e, isMachine(opts), undefined, opts.debug)
|
|
133
|
+
process.exit(1)
|
|
131
134
|
}
|
|
132
135
|
},
|
|
133
136
|
} satisfies CommandDefinition
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Path } from '@astrale-os/sdk/graph/path'
|
|
2
|
-
import {
|
|
2
|
+
import { K } from '@astrale-os/sdk/schema'
|
|
3
3
|
import chalk from 'chalk'
|
|
4
4
|
|
|
5
5
|
import type { KernelCommandOpts } from '../../connection'
|
|
@@ -77,7 +77,7 @@ Examples:
|
|
|
77
77
|
label: `Uninstalling domain ${origin}`,
|
|
78
78
|
fn: async ({ session }) =>
|
|
79
79
|
(await session.call(
|
|
80
|
-
createPathCall(Path.project(
|
|
80
|
+
createPathCall(Path.project(K.functions.uninstall.ref).raw, uninstallCallInput(origin)),
|
|
81
81
|
)) as UninstallResult,
|
|
82
82
|
format: (result, formatOpts, machine) => {
|
|
83
83
|
if (machine) {
|
package/src/commands/get.ts
CHANGED
|
@@ -4,40 +4,39 @@ import type { KernelCommandOpts } from '../connection'
|
|
|
4
4
|
import type { CommandDefinition } from '../program/index'
|
|
5
5
|
|
|
6
6
|
import { expandSelfInPath, runKernelCommand, withSelfHint } from '../connection'
|
|
7
|
-
import { formatKernelError } from '../connection/errors'
|
|
8
7
|
import { AstraleError } from '../errors'
|
|
9
|
-
import {
|
|
8
|
+
import { failInput, fatal } from '../lib/log'
|
|
9
|
+
import { denoise, output } from '../lib/output'
|
|
10
10
|
|
|
11
11
|
type GetOpts = KernelCommandOpts & { schema?: boolean }
|
|
12
12
|
|
|
13
13
|
/** Read one exact canonical Node. The caller's Path is not fabricated into the Node value. */
|
|
14
14
|
export async function getCommand(target: string, opts: GetOpts): Promise<void> {
|
|
15
|
-
let path: string
|
|
16
|
-
let meta
|
|
17
15
|
let parsed
|
|
18
16
|
try {
|
|
19
|
-
|
|
20
|
-
parsed = Path.parse(path)
|
|
17
|
+
parsed = Path.parse(target)
|
|
21
18
|
} catch (error) {
|
|
22
|
-
|
|
23
|
-
process.exit(1)
|
|
19
|
+
failInput(error, opts)
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
const last = parsed.ast.steps.at(-1)
|
|
27
23
|
if (last?.kind === 'method') {
|
|
28
24
|
const error = new AstraleError(
|
|
29
25
|
'NOT_A_NODE',
|
|
30
|
-
`${
|
|
31
|
-
`Use \`astrale call ${
|
|
26
|
+
`${target} is a callable Path, not a Node.`,
|
|
27
|
+
`Use \`astrale call ${target}\` or \`astrale introspect ${target}\`.`,
|
|
32
28
|
)
|
|
33
|
-
|
|
34
|
-
process.exit(1)
|
|
29
|
+
fatal(error, opts)
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
await runKernelCommand({
|
|
38
33
|
opts,
|
|
39
|
-
label: `Node ${
|
|
40
|
-
fn:
|
|
34
|
+
label: `Node ${target}`,
|
|
35
|
+
fn: async (context) => {
|
|
36
|
+
const { path, meta } = await expandSelfInPath(target, context)
|
|
37
|
+
const resolved = meta === undefined ? parsed : Path.parse(path)
|
|
38
|
+
return withSelfHint(() => context.graph.getOrThrow(resolved), meta)
|
|
39
|
+
},
|
|
41
40
|
format: (node, format) => output(opts.schema === true ? node : denoise(node), format),
|
|
42
41
|
})
|
|
43
42
|
}
|
|
@@ -47,7 +46,7 @@ export default {
|
|
|
47
46
|
description: 'Get one canonical node by Path or ID',
|
|
48
47
|
afterHelpText: `
|
|
49
48
|
Behavior:
|
|
50
|
-
Resolves one exact Kernel
|
|
49
|
+
Resolves one exact Kernel Path and prints the canonical Node
|
|
51
50
|
{ id, class, props }. Missing and authorization-masked nodes remain
|
|
52
51
|
intentionally indistinguishable. @self is expanded before dispatch.
|
|
53
52
|
|
|
@@ -60,7 +59,7 @@ Examples:
|
|
|
60
59
|
$ astrale get /:notes.example.dev:class.Note
|
|
61
60
|
$ astrale get @abc123 --json
|
|
62
61
|
$ astrale get @self
|
|
63
|
-
$ astrale get /:
|
|
62
|
+
$ astrale get /:kernel.astrale.ai --schema
|
|
64
63
|
`,
|
|
65
64
|
arguments: [{ name: 'target', description: 'Canonical Node Path or @id' }],
|
|
66
65
|
options: [{ flags: '--schema', description: 'Include schema-valued properties' }],
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { issuer, jwk, provision } from '@astrale-os/sdk/auth'
|
|
2
|
-
import { ClassPath } from '@astrale-os/sdk/graph/class'
|
|
3
2
|
import { normalizeProperties } from '@astrale-os/sdk/graph/properties'
|
|
4
3
|
import { expect, mock, test } from 'bun:test'
|
|
5
4
|
import { exportJWK, generateKeyPair, jwtVerify } from 'jose'
|
|
6
5
|
|
|
6
|
+
import { classKey } from '../../../graph'
|
|
7
7
|
import { formatIdentityRegistration, prepareIdentityProvision } from '../register'
|
|
8
8
|
|
|
9
9
|
/** @evidence TEST-CLI-IDENTITY-REGISTER-JSON-EXACT */
|
|
@@ -46,7 +46,7 @@ test('builds one exact Mutation V3 identity birth bound to a self proof', async
|
|
|
46
46
|
kid: 'alice-key',
|
|
47
47
|
})
|
|
48
48
|
const kernelIssuer = issuer.accept('https://kernel.example')
|
|
49
|
-
const classPath =
|
|
49
|
+
const classPath = classKey('/:accounts.example:class.User', '--class')
|
|
50
50
|
const properties = normalizeProperties({
|
|
51
51
|
'accounts.example:class.User.property.name': 'Alice',
|
|
52
52
|
})
|
|
@@ -70,7 +70,7 @@ test('builds one exact Mutation V3 identity birth bound to a self proof', async
|
|
|
70
70
|
{
|
|
71
71
|
op: 'node.create',
|
|
72
72
|
as: 'identity',
|
|
73
|
-
class: '
|
|
73
|
+
class: 'accounts.example:class.User',
|
|
74
74
|
props: { 'accounts.example:class.User.property.name': 'Alice' },
|
|
75
75
|
},
|
|
76
76
|
],
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { IssuerId, JsonWebKey, ProvisionRequest } from '@astrale-os/sdk/auth'
|
|
2
|
+
import type { ClassKey as ClassKeyValue } from '@astrale-os/sdk/graph/class'
|
|
2
3
|
import type { JWK } from 'jose'
|
|
3
4
|
|
|
4
5
|
import { provision, jwk } from '@astrale-os/sdk/auth'
|
|
5
|
-
import {
|
|
6
|
-
import { LocalBinding } from '@astrale-os/sdk/graph/model'
|
|
6
|
+
import { LocalBinding } from '@astrale-os/sdk/graph'
|
|
7
7
|
import { normalizeProperties } from '@astrale-os/sdk/graph/properties'
|
|
8
8
|
import { MutationAST } from '@astrale-os/sdk/mutation'
|
|
9
9
|
import { importJWK, SignJWT } from 'jose'
|
|
@@ -14,6 +14,7 @@ import type { IdentityRegistrationResult } from '../../identity/index'
|
|
|
14
14
|
import type { CommandDefinition } from '../../program/index'
|
|
15
15
|
|
|
16
16
|
import { registrationKeyForTarget, runKernelCommand } from '../../connection'
|
|
17
|
+
import { classKey } from '../../graph'
|
|
17
18
|
import { getIdentity, setRegistration, submitIdentityProvision } from '../../identity/index'
|
|
18
19
|
import { fileExists, keypairPaths } from '../../keys/index'
|
|
19
20
|
import { fatal, log } from '../../lib/log'
|
|
@@ -44,10 +45,9 @@ Behavior:
|
|
|
44
45
|
its result and stores the same target-bound registration. The callable owns
|
|
45
46
|
authorization; the CLI never receives installed Domain authority.
|
|
46
47
|
|
|
47
|
-
Kernel
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
the returned (issuer, subject) for subsequent calls.
|
|
48
|
+
The Kernel assigns each Node ID; callers do not choose a storage path. The
|
|
49
|
+
CLI binds the key proof to the exact provision fingerprint and target Kernel
|
|
50
|
+
audience, then caches the returned (issuer, subject) for subsequent calls.
|
|
51
51
|
|
|
52
52
|
Example:
|
|
53
53
|
$ astrale identity register alice --class /:accounts.example:class.User \
|
|
@@ -83,7 +83,7 @@ Example:
|
|
|
83
83
|
|
|
84
84
|
const privateKey = await readJwk(privatePath)
|
|
85
85
|
const publicKey = jwk.acceptPublic(await readJwk(publicPath))
|
|
86
|
-
const classPath =
|
|
86
|
+
const classPath = classKey(opts.class, '--class')
|
|
87
87
|
const properties = normalizeProperties(opts.props ? JSON.parse(opts.props) : {})
|
|
88
88
|
|
|
89
89
|
await runKernelCommand<IdentityRegistrationResult>({
|
|
@@ -142,7 +142,7 @@ export function formatIdentityRegistration(
|
|
|
142
142
|
/** Build and self-prove one exact canonical provision request for the target Kernel. */
|
|
143
143
|
export async function prepareIdentityProvision(input: {
|
|
144
144
|
readonly name: string
|
|
145
|
-
readonly classPath:
|
|
145
|
+
readonly classPath: ClassKeyValue
|
|
146
146
|
readonly properties: ReturnType<typeof normalizeProperties>
|
|
147
147
|
readonly privateKey: JWK
|
|
148
148
|
readonly publicKey: JsonWebKey
|