@astrale-os/cli 1.0.0-beta.0 → 1.0.0-beta.10
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 +23 -12
- package/dist/astrale.js +51494 -56307
- package/dist/public/connect-core.js +2028 -26846
- package/dist/public/keys/index.js +1755 -40694
- package/dist/public/paths/index.js +859 -39518
- package/dist/types/admin/binding.d.ts +19 -0
- package/dist/types/admin/instance/client.d.ts +22 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +5 -12
- 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 +6 -2
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +7 -0
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +10 -2
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/meta.d.ts +2 -2
- 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 +131 -0
- package/package.json +8 -10
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/__tests__/binding.test.ts +31 -0
- package/src/admin/__tests__/fixture.ts +101 -0
- package/src/admin/binding.ts +98 -0
- package/src/admin/catalog/.spec/api.d.ts +2 -2
- package/src/admin/catalog/__tests__/client.test.ts +20 -49
- package/src/admin/catalog/client.ts +36 -32
- package/src/admin/catalog/model.ts +3 -4
- 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 +2 -2
- package/src/admin/instance/__tests__/client.test.ts +40 -163
- package/src/admin/instance/client.ts +35 -137
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +11 -20
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/auth-login.test.ts +54 -1
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +5 -1
- package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
- package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
- package/src/commands/__tests__/domain-list.test.ts +63 -4
- package/src/commands/__tests__/install-identity-override.test.ts +19 -19
- 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__/read-commands.test.ts +35 -10
- package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
- package/src/commands/__tests__/update.test.ts +95 -0
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +43 -56
- package/src/commands/domain/install.ts +13 -17
- package/src/commands/domain/list.ts +18 -13
- package/src/commands/domain/publish.ts +14 -11
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +14 -15
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +5 -4
- 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 +9 -16
- package/src/commands/logs.ts +24 -25
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +27 -30
- package/src/commands/studio.ts +20 -0
- package/src/commands/token.ts +8 -7
- package/src/commands/update.ts +68 -22
- package/src/commands/view.ts +7 -6
- package/src/connection/.spec/api.d.ts +7 -8
- package/src/connection/.spec/architecture.md +5 -4
- 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__/credential.test.ts +20 -1
- package/src/connection/__tests__/errors.test.ts +43 -32
- package/src/connection/__tests__/exchange.test.ts +36 -6
- 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 +3 -3
- package/src/connection/__tests__/target.test.ts +1 -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 +52 -27
- 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 +19 -8
- 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__/registration.test.ts +1 -1
- package/src/identity/registration.ts +3 -3
- 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__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/domain-publication.test.ts +138 -0
- package/src/lib/__tests__/idp-session.test.ts +22 -0
- package/src/lib/__tests__/idp.test.ts +36 -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__/instance.test.ts +6 -0
- package/src/lib/__tests__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
- package/src/lib/__tests__/update.test.ts +113 -8
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +1 -1
- package/src/lib/__tests__/view-session.test.ts +1 -1
- package/src/lib/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/domain-publication.ts +104 -0
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +39 -4
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +22 -12
- package/src/lib/log.ts +16 -9
- package/src/lib/login-flow.ts +13 -3
- package/src/lib/meta.ts +2 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/update.ts +124 -30
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/resolve.ts +1 -1
- package/src/program/__tests__/program.test.ts +20 -4
- package/src/program/build.ts +2 -2
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/studio/client/dist/assets/{elk-api-D2xgMJvi.js → elk-api-ByzoDZWH.js} +1 -1
- package/studio/client/dist/assets/index-B0RCgUOT.js +8 -0
- package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
- package/studio/client/dist/assets/index-N8J8EKlB.js +81 -0
- package/studio/client/dist/index.html +2 -2
- package/studio/package.json +5 -10
- 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/bridge/stdio.ts +8 -1
- package/studio/server/agent/conversation.test.ts +10 -5
- package/studio/server/agent/conversation.ts +56 -8
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/codex/loadout.ts +18 -21
- package/studio/server/agent/harness/gateway/config.ts +20 -18
- package/studio/server/agent/harness/selection.ts +9 -1
- package/studio/server/agent/prompts/anchors.test.ts +32 -36
- package/studio/server/agent/prompts/anchors.ts +20 -49
- package/studio/server/agent/prompts/system.test.ts +3 -2
- package/studio/server/agent/prompts/system.ts +6 -5
- package/studio/server/agent/prompts/turn.ts +13 -4
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/completion.ts +2 -2
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/agent/run/preparation.ts +6 -5
- package/studio/server/agent/run/transcript.test.ts +35 -1
- package/studio/server/agent/run/transcript.ts +169 -3
- package/studio/server/agent/run/usage.test.ts +24 -0
- package/studio/server/agent/run/usage.ts +26 -1
- package/studio/server/api/canvas.ts +43 -0
- package/studio/server/api/comments.ts +85 -0
- package/studio/server/api/context.ts +61 -0
- package/studio/server/api/deployment.ts +39 -0
- package/studio/server/api/documents.ts +55 -0
- package/studio/server/api/domain.ts +59 -0
- package/studio/server/api/http.ts +45 -0
- package/studio/server/api/project.ts +57 -0
- package/studio/server/api/schema.ts +12 -0
- package/studio/server/api/views.ts +57 -0
- package/studio/server/api/workspace.ts +60 -0
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +147 -0
- package/studio/server/api.ts +20 -422
- package/studio/server/cache.test.ts +122 -0
- package/studio/server/cache.ts +162 -11
- package/studio/server/cli-consumers.test.ts +494 -0
- package/studio/server/cli.test.ts +88 -0
- package/studio/server/cli.ts +240 -0
- package/studio/server/client-package.ts +25 -1
- package/studio/server/domain.test.ts +50 -40
- package/studio/server/domain.ts +83 -52
- package/studio/server/environment/dotenv-preview.test.ts +39 -0
- package/studio/server/environment/dotenv-preview.ts +27 -0
- package/studio/server/environment/files.test.ts +53 -0
- package/studio/server/{state/env.ts → environment/files.ts} +7 -48
- package/studio/server/{state → handoff}/copy.ts +21 -6
- package/studio/server/handoff/service.test.ts +22 -0
- package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/active.ts +72 -0
- package/studio/server/instances/deploy-record.test.ts +31 -0
- package/studio/server/instances/deploy-record.ts +37 -0
- package/studio/server/instances/deploy.ts +56 -0
- package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
- package/studio/server/instances/probe.ts +67 -0
- package/studio/server/instances/status.test.ts +12 -0
- package/studio/server/instances/status.ts +49 -0
- package/studio/server/introspect/anatomy/client-tree.ts +57 -0
- package/studio/server/introspect/anatomy/env-fields.ts +66 -0
- package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
- package/studio/server/introspect/anatomy/source.ts +181 -0
- package/studio/server/introspect/anatomy/views/routes.ts +114 -0
- package/studio/server/introspect/anatomy/views.ts +53 -0
- package/studio/server/introspect/anatomy-extras.test.ts +106 -35
- package/studio/server/introspect/anatomy-extras.ts +7 -726
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +52 -28
- package/studio/server/introspect/bundle.ts +15 -9
- package/studio/server/introspect/canonical-schema.test.ts +93 -309
- package/studio/server/introspect/canonical-schema.ts +257 -425
- package/studio/server/introspect/config-preview.test.ts +32 -0
- package/studio/server/introspect/config-preview.ts +119 -0
- package/studio/server/introspect/core-extractor.ts +18 -127
- package/studio/server/introspect/core.ts +1 -2
- package/studio/server/introspect/diff.test.ts +18 -18
- package/studio/server/introspect/diff.ts +44 -90
- package/studio/server/introspect/extractor.ts +23 -116
- package/studio/server/introspect/hash.ts +5 -2
- package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
- package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
- package/studio/server/introspect/overlay.test.ts +26 -54
- package/studio/server/introspect/overlay.ts +10 -37
- package/studio/server/introspect/revision.test.ts +54 -0
- package/studio/server/introspect/revision.ts +49 -0
- package/studio/server/introspect/runtime.test.ts +83 -143
- package/studio/server/introspect/runtime.ts +40 -11
- package/studio/server/introspect/schema-ir-json.test.ts +70 -0
- package/studio/server/introspect/schema-ir-json.ts +151 -0
- 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/annotations.ts +14 -0
- package/studio/server/introspect/source-overlay/handlers.ts +161 -0
- package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
- package/studio/server/introspect/source-overlay/project.ts +248 -0
- package/studio/server/introspect/source-overlay/spans.ts +330 -0
- package/studio/server/json.ts +46 -0
- package/studio/server/lifecycle.ts +5 -1
- package/studio/server/sse.test.ts +26 -0
- package/studio/server/sse.ts +4 -1
- package/studio/server/state/baseline.test.ts +223 -7
- package/studio/server/state/baseline.ts +148 -34
- package/studio/server/state/comments.test.ts +66 -1
- package/studio/server/state/comments.ts +173 -10
- package/studio/server/state/context.ts +34 -2
- package/studio/server/state/documents.ts +42 -1
- package/studio/server/state/integrations.ts +27 -1
- package/studio/server/state/layout.test.ts +34 -0
- package/studio/server/state/layout.ts +44 -17
- package/studio/server/state/settings.ts +29 -22
- package/studio/server/state/store.test.ts +122 -0
- package/studio/server/state/store.ts +66 -17
- package/studio/server/state/visibility.ts +22 -11
- package/studio/server/views/model.test.ts +57 -0
- package/studio/server/views/model.ts +66 -0
- package/studio/server/views/runtime.ts +40 -0
- package/studio/server/views/selection-repository.test.ts +31 -0
- package/studio/server/views/selection-repository.ts +60 -0
- package/studio/server/views/session.test.ts +73 -0
- package/studio/server/views/session.ts +166 -0
- package/studio/server/views/target.test.ts +78 -0
- package/studio/server/views/target.ts +222 -0
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +9 -5
- package/studio/server/workspace/catalog.test.ts +17 -0
- package/studio/server/workspace/catalog.ts +43 -0
- package/studio/server/{state → workspace}/create.test.ts +1 -1
- package/studio/server/{state → workspace}/create.ts +1 -1
- package/studio/server/{state → workspace}/git.ts +1 -1
- package/studio/server/workspace/updates.ts +83 -0
- package/studio/server/workspace-state.ts +1 -1
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/README.md +16 -0
- package/studio/shared/contracts/agent.ts +270 -0
- package/studio/shared/contracts/runtime.ts +50 -0
- package/studio/shared/contracts/schema.ts +393 -0
- package/studio/shared/contracts/surface.test.ts +317 -0
- package/studio/shared/contracts/workspace.ts +265 -0
- package/studio/shared/layout.test.ts +116 -0
- package/studio/shared/schema/identity.test.ts +34 -0
- package/studio/shared/schema/identity.ts +68 -0
- package/studio/shared/types.ts +11 -1099
- package/studio/tsconfig.json +1 -1
- package/viewer/dist/main.js +40 -61
- package/.check-workspace.cjs +0 -40
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
- package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
- package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
- package/studio/server/state/catalog.ts +0 -117
- package/studio/server/state/instance.ts +0 -280
- package/studio/server/state/updates.ts +0 -63
- package/studio/server/state/views.test.ts +0 -286
- package/studio/server/state/views.ts +0 -535
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Path } from '@astrale-os/sdk/graph/path'
|
|
2
|
+
import type { ResolvedFunction, ResolvedMethod } from '@astrale-os/sdk/schema'
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { bundle, schema } from '@astrale-os/sdk/schema'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import { AstraleError } from '../errors'
|
|
6
7
|
|
|
7
8
|
export interface CallableDescription {
|
|
8
9
|
readonly path: string
|
|
@@ -18,40 +19,40 @@ export interface CallableDescription {
|
|
|
18
19
|
readonly candidates?: readonly CallableDescription[]
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
/** Resolve one callable
|
|
22
|
-
export function
|
|
22
|
+
/** Resolve one callable from an admitted installed Domain bundle. */
|
|
23
|
+
export function describeCallableFromBundle(
|
|
23
24
|
path: Path,
|
|
24
|
-
|
|
25
|
+
input: unknown,
|
|
25
26
|
): CallableDescription | undefined {
|
|
26
27
|
if (path.ast.anchor.kind !== 'domain') return undefined
|
|
27
28
|
const origin = path.ast.anchor.origin
|
|
28
29
|
const last = path.ast.steps.at(-1)
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
if (last === undefined) return undefined
|
|
31
|
+
const domain = schema.resolve(bundle.accept(input).root)
|
|
32
|
+
if (domain.origin !== origin) return undefined
|
|
31
33
|
|
|
32
34
|
if (last.kind === 'method') {
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
owner
|
|
36
|
-
(owner
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
const ownerStep = path.ast.steps.at(-2)
|
|
36
|
+
if (ownerStep?.kind === 'projection' && ownerStep.projection.kind === 'class') {
|
|
37
|
+
const owner = domain.classes[ownerStep.projection.name]
|
|
38
|
+
if (owner?.kind !== 'node') return undefined
|
|
39
|
+
const method = namedMethod(
|
|
40
|
+
last.dispatch === 'static' ? owner.static.methods : owner.methods,
|
|
41
|
+
last.name,
|
|
42
|
+
last.dispatch,
|
|
40
43
|
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return Object.freeze({
|
|
45
|
-
path: path.raw,
|
|
46
|
-
origin,
|
|
47
|
-
class: owner.projection.name,
|
|
48
|
-
method: last.name,
|
|
49
|
-
dispatch: last.dispatch,
|
|
50
|
-
...callableFields(method),
|
|
51
|
-
})
|
|
52
|
-
}
|
|
44
|
+
return method === undefined
|
|
45
|
+
? undefined
|
|
46
|
+
: description(path, origin, owner.ref.name, method, last.dispatch)
|
|
53
47
|
}
|
|
54
|
-
|
|
48
|
+
|
|
49
|
+
const matches = Object.values(domain.classes).flatMap((owner) => {
|
|
50
|
+
if (owner.kind !== 'node') return []
|
|
51
|
+
const method = namedMethod(owner.methods, last.name, last.dispatch)
|
|
52
|
+
return method === undefined
|
|
53
|
+
? []
|
|
54
|
+
: [description(path, origin, owner.ref.name, method, last.dispatch)]
|
|
55
|
+
})
|
|
55
56
|
if (matches.length === 1) return matches[0]
|
|
56
57
|
if (matches.length > 1) {
|
|
57
58
|
return Object.freeze({
|
|
@@ -66,13 +67,13 @@ export function describeCallableFromSchema(
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
if (last.kind === 'projection' && last.projection.kind === 'function') {
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
70
|
+
const callable = domain.functions[last.projection.name]
|
|
71
|
+
if (callable === undefined) return undefined
|
|
71
72
|
return Object.freeze({
|
|
72
73
|
path: path.raw,
|
|
73
74
|
origin,
|
|
74
|
-
function:
|
|
75
|
-
...callableFields(
|
|
75
|
+
function: callable.ref.name,
|
|
76
|
+
...callableFields(callable),
|
|
76
77
|
})
|
|
77
78
|
}
|
|
78
79
|
return undefined
|
|
@@ -82,50 +83,41 @@ export function missingCallableDescription(path: string): AstraleError {
|
|
|
82
83
|
return new AstraleError(
|
|
83
84
|
'CALL_DESCRIBE_UNAVAILABLE',
|
|
84
85
|
`No callable schema is installed for ${path}.`,
|
|
85
|
-
'Use a Domain-rooted Path such as /:
|
|
86
|
+
'Use a Domain-rooted Path such as /:kernel.astrale.ai:class.Identity:whois. Method Paths are not Function nodes.',
|
|
86
87
|
)
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
function
|
|
90
|
-
|
|
90
|
+
function namedMethod(
|
|
91
|
+
methods: Iterable<ResolvedMethod>,
|
|
92
|
+
name: string,
|
|
93
|
+
dispatch: 'static' | 'instance',
|
|
94
|
+
): ResolvedMethod | undefined {
|
|
95
|
+
const expectedStatic = dispatch === 'static'
|
|
96
|
+
return [...methods].find((method) => method.name === name && method.static === expectedStatic)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function description(
|
|
100
|
+
path: Path,
|
|
91
101
|
origin: string,
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
className: string,
|
|
103
|
+
callable: ResolvedMethod,
|
|
94
104
|
dispatch: 'static' | 'instance',
|
|
95
|
-
): CallableDescription
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Object.freeze({
|
|
105
|
-
path,
|
|
106
|
-
origin,
|
|
107
|
-
class: className,
|
|
108
|
-
method,
|
|
109
|
-
dispatch,
|
|
110
|
-
...callableFields(methodDef),
|
|
111
|
-
}),
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return matches
|
|
105
|
+
): CallableDescription {
|
|
106
|
+
return Object.freeze({
|
|
107
|
+
path: path.raw,
|
|
108
|
+
origin,
|
|
109
|
+
class: className,
|
|
110
|
+
method: callable.name,
|
|
111
|
+
dispatch,
|
|
112
|
+
...callableFields(callable),
|
|
113
|
+
})
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
function callableFields(
|
|
116
|
+
function callableFields(callable: ResolvedFunction | ResolvedMethod): Partial<CallableDescription> {
|
|
119
117
|
return {
|
|
120
|
-
...(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
...(callable.description === undefined ? {} : { description: callable.description }),
|
|
119
|
+
auth: callable.auth,
|
|
120
|
+
input: callable.input,
|
|
121
|
+
output: callable.output,
|
|
124
122
|
}
|
|
125
123
|
}
|
|
126
|
-
|
|
127
|
-
function asRecord(input: unknown): JsonRecord | undefined {
|
|
128
|
-
return input !== null && typeof input === 'object' && !Array.isArray(input)
|
|
129
|
-
? (input as JsonRecord)
|
|
130
|
-
: undefined
|
|
131
|
-
}
|
package/src/commands/call.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { CommandDefinition } from '../program/index'
|
|
|
5
5
|
|
|
6
6
|
import { createPathCall, expandSelfInCall, runKernelCommand, withSelfHint } from '../connection'
|
|
7
7
|
import { presentBinary } from '../lib/binary'
|
|
8
|
-
import {
|
|
8
|
+
import { failInput, log } from '../lib/log'
|
|
9
9
|
import { output, present } from '../lib/output'
|
|
10
10
|
|
|
11
11
|
type CallOpts = KernelCommandOpts & {
|
|
@@ -24,60 +24,47 @@ export async function callCommand(
|
|
|
24
24
|
rawParams: string[],
|
|
25
25
|
opts: CallOpts,
|
|
26
26
|
): 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
27
|
let params: Record<string, unknown>
|
|
43
28
|
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
|
|
29
|
+
Path.parse(path)
|
|
30
|
+
params = await parseParams(rawParams, opts.data)
|
|
31
|
+
} catch (error) {
|
|
32
|
+
failInput(error, opts)
|
|
53
33
|
}
|
|
54
34
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
35
|
+
await runKernelCommand<MaterializedCallResult | { readonly kind: 'dry'; readonly call: unknown }>(
|
|
36
|
+
{
|
|
37
|
+
opts,
|
|
38
|
+
label: path,
|
|
39
|
+
fn: async (ctx) => {
|
|
40
|
+
const expanded = await expandSelfInCall(path, params, ctx)
|
|
41
|
+
const request = createPathCall(expanded.path, expanded.parameters)
|
|
42
|
+
if (opts.dryRun) return { kind: 'dry', call: request }
|
|
43
|
+
return withSelfHint(
|
|
44
|
+
async () => materializeCallResult(await ctx.session.dispatch(request)),
|
|
45
|
+
expanded.meta,
|
|
46
|
+
)
|
|
47
|
+
},
|
|
48
|
+
format: async (result, fmtOpts) => {
|
|
49
|
+
switch (result.kind) {
|
|
50
|
+
case 'dry':
|
|
51
|
+
output(result.call, fmtOpts)
|
|
52
|
+
return
|
|
53
|
+
case 'value':
|
|
54
|
+
present(result.value, fmtOpts)
|
|
55
|
+
return
|
|
56
|
+
case 'binary':
|
|
57
|
+
await presentBinary(result.value, fmtOpts, { outFile: opts.output })
|
|
58
|
+
return
|
|
59
|
+
case 'stream':
|
|
60
|
+
output(result.values, fmtOpts)
|
|
61
|
+
return
|
|
62
|
+
case 'redirect':
|
|
63
|
+
throw new Error('Client Session returned an unresolved redirect.')
|
|
64
|
+
}
|
|
65
|
+
},
|
|
79
66
|
},
|
|
80
|
-
|
|
67
|
+
)
|
|
81
68
|
}
|
|
82
69
|
|
|
83
70
|
/** Drain a session-backed stream before the command-scoped Client Session closes. */
|
|
@@ -101,7 +88,7 @@ export async function parseParams(
|
|
|
101
88
|
try {
|
|
102
89
|
return JSON.parse(dataFlag)
|
|
103
90
|
} catch {
|
|
104
|
-
throw new
|
|
91
|
+
throw new TypeError(`Invalid JSON in --data: ${dataFlag}`)
|
|
105
92
|
}
|
|
106
93
|
}
|
|
107
94
|
|
|
@@ -114,7 +101,7 @@ export async function parseParams(
|
|
|
114
101
|
try {
|
|
115
102
|
return JSON.parse(stdin)
|
|
116
103
|
} catch {
|
|
117
|
-
throw new
|
|
104
|
+
throw new TypeError('Invalid JSON from stdin')
|
|
118
105
|
}
|
|
119
106
|
}
|
|
120
107
|
|
|
@@ -142,7 +129,7 @@ export function parseKeyValue(pairs: string[]): Record<string, unknown> {
|
|
|
142
129
|
for (const pair of pairs) {
|
|
143
130
|
const eqIdx = pair.indexOf('=')
|
|
144
131
|
if (eqIdx === -1) {
|
|
145
|
-
throw new
|
|
132
|
+
throw new TypeError(`Invalid param "${pair}" — expected key=value format`)
|
|
146
133
|
}
|
|
147
134
|
const key = pair.slice(0, eqIdx)
|
|
148
135
|
const raw = pair.slice(eqIdx + 1)
|
|
@@ -150,7 +137,7 @@ export function parseKeyValue(pairs: string[]): Record<string, unknown> {
|
|
|
150
137
|
const hint = key.endsWith(':')
|
|
151
138
|
? ` (looks like httpie's "key:=value" syntax — Astrale CLI doesn't support it; use --data '{"${key.slice(0, -1)}":<value>}' for nested values)`
|
|
152
139
|
: ` (keys must be identifier-shaped: letters, digits, underscore, hyphen)`
|
|
153
|
-
throw new
|
|
140
|
+
throw new TypeError(`Invalid param key "${key}" in "${pair}"${hint}`)
|
|
154
141
|
}
|
|
155
142
|
result[key] = coerceValue(raw)
|
|
156
143
|
}
|
|
@@ -194,7 +181,7 @@ Self-reference:
|
|
|
194
181
|
Callable input/output lives on astrale introspect <path>.
|
|
195
182
|
|
|
196
183
|
Examples:
|
|
197
|
-
$ astrale introspect /:
|
|
184
|
+
$ astrale introspect /:kernel.astrale.ai:class.Identity:whois
|
|
198
185
|
$ astrale call /:blog.acme.com:class.Author:list limit=10
|
|
199
186
|
$ astrale call '@self::deactivate'
|
|
200
187
|
$ astrale call /:kernel.astrale.ai:function.journal --data '{"limit":5}' --json
|
|
@@ -203,7 +190,7 @@ Examples:
|
|
|
203
190
|
{
|
|
204
191
|
name: 'path',
|
|
205
192
|
description:
|
|
206
|
-
'Operation path (e.g., /:
|
|
193
|
+
'Operation path (e.g., /:kernel.astrale.ai:class.Identity:whois or /node::method)',
|
|
207
194
|
},
|
|
208
195
|
{ name: 'params...', description: 'Params as key=value pairs', required: false },
|
|
209
196
|
],
|
|
@@ -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'
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from '../../lib/admin-domain'
|
|
16
16
|
import { listOwnedInstancesInContext, type OwnedInstanceInfo } from '../../lib/admin-instance'
|
|
17
17
|
import { ADMIN_TARGET_OPTIONS, type AdminTargetCommandOpts } from '../../lib/admin-target'
|
|
18
|
+
import { fetchDomainPublication } from '../../lib/domain-publication'
|
|
18
19
|
import { getActive } from '../../lib/instance'
|
|
19
20
|
import { fatal, log, withSpinner } from '../../lib/log'
|
|
20
21
|
import { isMachine, output } from '../../lib/output'
|
|
@@ -413,7 +414,7 @@ export async function installDirect(
|
|
|
413
414
|
fn: async ({ session }) =>
|
|
414
415
|
(await session.call(
|
|
415
416
|
createPathCall(
|
|
416
|
-
Path.project(
|
|
417
|
+
Path.project(K.functions.install.ref).raw,
|
|
417
418
|
directInstallCallInput(url, operation, opts.token),
|
|
418
419
|
),
|
|
419
420
|
)) as DirectInstallResult,
|
|
@@ -429,11 +430,11 @@ export async function installDirect(
|
|
|
429
430
|
log.dim(` operation: ${result.operation}`)
|
|
430
431
|
// Belt-and-braces: the kernel-confirmed origin is authoritative. If it
|
|
431
432
|
// aliases the host and the pre-install gate never consented to THAT
|
|
432
|
-
// origin (lying or
|
|
433
|
+
// origin (lying or unavailable Publication), say so loudly after the fact.
|
|
433
434
|
if (isIdentityOverride(installed.origin, host) && installed.origin !== consentedOrigin) {
|
|
434
435
|
log.warn(
|
|
435
436
|
`Installed origin "${installed.origin}" differs from the serving host "${host}" ` +
|
|
436
|
-
`and was not confirmed before install (the worker
|
|
437
|
+
`and was not confirmed before install (the worker Publication was unavailable). ` +
|
|
437
438
|
`Every ${installed.origin}/* call on this instance now routes to ${host}.`,
|
|
438
439
|
)
|
|
439
440
|
}
|
|
@@ -478,10 +479,10 @@ export function isIdentityOverride(origin: string, host: string): boolean {
|
|
|
478
479
|
* Claiming an origin that differs from the serving host is an explicit actAs
|
|
479
480
|
* and needs typed consent (or `--allow-identity-override` in scripts).
|
|
480
481
|
*
|
|
481
|
-
* The pre-install check reads the worker's
|
|
482
|
+
* The pre-install check reads the worker's canonical Publication origin,
|
|
482
483
|
* so it is consent UX, not enforcement — a hostile worker can lie here, and
|
|
483
484
|
* the kernel anchors the cryptographic identity (`iss`) on the real URL
|
|
484
|
-
* regardless. When
|
|
485
|
+
* regardless. When the Publication is unreachable or invalid, the gate
|
|
485
486
|
* degrades to a warning and the kernel-confirmed origin is re-checked after
|
|
486
487
|
* install (see `format` above).
|
|
487
488
|
*
|
|
@@ -496,7 +497,8 @@ async function ensureIdentityOverrideConsent(
|
|
|
496
497
|
const origin = await probeDeclaredOrigin(url)
|
|
497
498
|
if (origin === undefined) {
|
|
498
499
|
log.warn(
|
|
499
|
-
`Could not read a declared origin from
|
|
500
|
+
`Could not read a declared origin from ` +
|
|
501
|
+
`${new URL('/.well-known/astrale/domain.json', url).href} — ` +
|
|
500
502
|
`skipping the pre-install identity check (the installed origin is verified after install).`,
|
|
501
503
|
)
|
|
502
504
|
return undefined
|
|
@@ -534,19 +536,13 @@ async function ensureIdentityOverrideConsent(
|
|
|
534
536
|
return origin
|
|
535
537
|
}
|
|
536
538
|
|
|
537
|
-
/** Best-effort read of the worker's
|
|
539
|
+
/** Best-effort read of the worker's origin from its admitted canonical Publication. */
|
|
538
540
|
export async function probeDeclaredOrigin(url: string): Promise<string | undefined> {
|
|
539
541
|
try {
|
|
540
|
-
|
|
541
|
-
if (!res.ok) return undefined
|
|
542
|
-
// SDK workers serve `origin`; `domainName` is the pre-Kernel-V2 name, kept
|
|
543
|
-
// as a fallback for workers deployed before the rename.
|
|
544
|
-
const body = (await res.json()) as { origin?: unknown; domainName?: unknown }
|
|
545
|
-
const declared = body.origin ?? body.domainName
|
|
546
|
-
return typeof declared === 'string' && declared.length > 0 ? declared : undefined
|
|
542
|
+
return (await fetchDomainPublication(url, AbortSignal.timeout(10_000))).origin
|
|
547
543
|
} catch {
|
|
548
|
-
//
|
|
549
|
-
// itself will surface a dead worker with its own error.
|
|
544
|
+
// An unreachable or invalid Publication is not fatal here: the caller warns
|
|
545
|
+
// and the install itself will surface a dead worker with its own error.
|
|
550
546
|
return undefined
|
|
551
547
|
}
|
|
552
548
|
}
|
|
@@ -6,6 +6,7 @@ import type { CommandDefinition } from '../../program/index'
|
|
|
6
6
|
|
|
7
7
|
import { listAdminDomains, type DomainInfo } from '../../lib/admin-domain'
|
|
8
8
|
import { ADMIN_TARGET_OPTIONS, type AdminTargetCommandOpts } from '../../lib/admin-target'
|
|
9
|
+
import { fetchDomainPublication } from '../../lib/domain-publication'
|
|
9
10
|
import { fatal, withSpinner } from '../../lib/log'
|
|
10
11
|
import { isMachine, presentList } from '../../lib/output'
|
|
11
12
|
|
|
@@ -23,7 +24,7 @@ type ListOpts = KernelCommandOpts &
|
|
|
23
24
|
/** A catalog entry, optionally enriched with a live `--check` probe. */
|
|
24
25
|
export type DomainRow = DomainInfo & {
|
|
25
26
|
reachable?: boolean
|
|
26
|
-
|
|
27
|
+
schemaRevision?: string
|
|
27
28
|
checkError?: string | null
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -72,9 +73,9 @@ Behavior:
|
|
|
72
73
|
or with --json/--raw (agent-friendly — full DomainInfo objects). -q prints
|
|
73
74
|
one install URL per line (pipeable into \`domain install\`); --count prints
|
|
74
75
|
only the number. --default-only keeps the install-by-default entries (what
|
|
75
|
-
every new instance
|
|
76
|
-
|
|
77
|
-
machine output).
|
|
76
|
+
every new instance receives during Admin-managed provisioning). --check probes each published URL's
|
|
77
|
+
canonical Publication and adds a live/unreachable STATUS column
|
|
78
|
+
(+ reachable/schemaRevision in machine output).
|
|
78
79
|
|
|
79
80
|
The admin kernel is selected like every admin op — the configured default,
|
|
80
81
|
or --admin <bookmark> / --admin-url <url>.
|
|
@@ -87,7 +88,10 @@ Examples:
|
|
|
87
88
|
`,
|
|
88
89
|
options: [
|
|
89
90
|
...ADMIN_TARGET_OPTIONS,
|
|
90
|
-
{
|
|
91
|
+
{
|
|
92
|
+
flags: '--check',
|
|
93
|
+
description: "Probe each domain's canonical Publication + schema revision",
|
|
94
|
+
},
|
|
91
95
|
{ flags: '--default-only', description: 'Only show install-by-default domains' },
|
|
92
96
|
{ flags: '-q, --quiet', description: 'One install URL per line (unix-pipeable)' },
|
|
93
97
|
{ flags: '--count', description: 'Print only the number of published domains' },
|
|
@@ -103,7 +107,7 @@ Examples:
|
|
|
103
107
|
const filtered = opts.defaultOnly ? list.filter((d) => d.installByDefault) : list
|
|
104
108
|
filtered.sort(byDefaultThenName)
|
|
105
109
|
if (!opts.check) return filtered as DomainRow[]
|
|
106
|
-
// Reachability is a direct client-side
|
|
110
|
+
// Reachability is a direct client-side Publication fetch per entry, in
|
|
107
111
|
// parallel — no admin round-trip, and version-independent of the
|
|
108
112
|
// admin worker (mirrors `domain install`'s probeDeclaredOrigin).
|
|
109
113
|
return Promise.all(filtered.map(probe))
|
|
@@ -129,19 +133,20 @@ export function byDefaultThenName(a: DomainInfo, b: DomainInfo): number {
|
|
|
129
133
|
|
|
130
134
|
/**
|
|
131
135
|
* Enrich one entry with a reachability probe: fetch the published worker's
|
|
132
|
-
*
|
|
133
|
-
*
|
|
136
|
+
* canonical Publication and read its schema revision. A dead or missing URL is
|
|
137
|
+
* itself a result, not a throw.
|
|
134
138
|
*/
|
|
135
|
-
async function probe(d: DomainInfo): Promise<DomainRow> {
|
|
139
|
+
export async function probe(d: DomainInfo): Promise<DomainRow> {
|
|
136
140
|
if (!d.url) return { ...d, reachable: false, checkError: 'no url published' }
|
|
137
141
|
try {
|
|
138
|
-
const
|
|
139
|
-
if (
|
|
140
|
-
|
|
142
|
+
const deployed = await fetchDomainPublication(d.url, AbortSignal.timeout(10_000))
|
|
143
|
+
if (deployed.origin !== d.origin) {
|
|
144
|
+
throw new Error(`Domain origin mismatch: deployed=${deployed.origin} expected=${d.origin}`)
|
|
145
|
+
}
|
|
141
146
|
return {
|
|
142
147
|
...d,
|
|
143
148
|
reachable: true,
|
|
144
|
-
|
|
149
|
+
schemaRevision: deployed.schema.revision,
|
|
145
150
|
checkError: null,
|
|
146
151
|
}
|
|
147
152
|
} catch (err) {
|
|
@@ -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
|
}
|
|
@@ -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' }],
|