@astrale-os/cli 1.0.0-beta.3 → 1.0.0-beta.31
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 +84 -6
- package/dist/astrale.js +57586 -60753
- 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 +119 -11
- 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 +39 -36
- 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 +90 -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 +13 -6
- package/src/graph/.spec/laws/documents.ts +7 -7
- package/src/graph/.spec/layout.ts +9 -1
- package/src/graph/__tests__/mutation.test.ts +2 -2
- package/src/graph/__tests__/query.test.ts +35 -9
- package/src/graph/class.ts +30 -0
- package/src/graph/index.ts +1 -0
- package/src/graph/query.ts +27 -40
- 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 +834 -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 +878 -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 +201 -7
- 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 +32 -4
- package/studio/server/cli.test.ts +2 -2
- 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 +25 -51
- 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
|
@@ -6,6 +6,12 @@ type GraphContext = {
|
|
|
6
6
|
getOrThrow: typeof getOrThrowMock
|
|
7
7
|
mutate: typeof mutateMock
|
|
8
8
|
}
|
|
9
|
+
session: {
|
|
10
|
+
schema: {
|
|
11
|
+
inspect: typeof inspectMock
|
|
12
|
+
bundle: typeof bundleMock
|
|
13
|
+
}
|
|
14
|
+
}
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
type RunOpts = {
|
|
@@ -36,6 +42,10 @@ let mutations: unknown[] = []
|
|
|
36
42
|
let queryResult: unknown
|
|
37
43
|
let getResult: unknown
|
|
38
44
|
let mutationResult: unknown
|
|
45
|
+
let inspectResult: unknown
|
|
46
|
+
let bundleResult: unknown
|
|
47
|
+
let selfFailure: unknown
|
|
48
|
+
let selfContexts: unknown[] = []
|
|
39
49
|
|
|
40
50
|
const queryMock = mock(async (ast: unknown, options?: unknown) => {
|
|
41
51
|
queryCalls.push({ ast, options })
|
|
@@ -49,7 +59,11 @@ const mutateMock = mock(async (mutation: unknown) => {
|
|
|
49
59
|
mutations.push(mutation)
|
|
50
60
|
return mutationResult
|
|
51
61
|
})
|
|
52
|
-
const
|
|
62
|
+
const inspectMock = mock(async (_origin: string) => inspectResult)
|
|
63
|
+
const bundleMock = mock(async (_origin: string) => bundleResult)
|
|
64
|
+
const expandSelfInPathMock = mock(async (path: string, context: unknown) => {
|
|
65
|
+
selfContexts.push(context)
|
|
66
|
+
if (selfFailure !== undefined) throw selfFailure
|
|
53
67
|
if (path === '@self') {
|
|
54
68
|
return {
|
|
55
69
|
path: '@expanded-self',
|
|
@@ -59,10 +73,12 @@ const expandSelfInPathMock = mock(async (path: string) => {
|
|
|
59
73
|
return { path, meta: undefined }
|
|
60
74
|
})
|
|
61
75
|
const withSelfHintMock = mock(async (action: () => Promise<unknown>) => action())
|
|
76
|
+
const commandContext = {
|
|
77
|
+
graph: { query: queryMock, getOrThrow: getOrThrowMock, mutate: mutateMock },
|
|
78
|
+
session: { schema: { inspect: inspectMock, bundle: bundleMock } },
|
|
79
|
+
}
|
|
62
80
|
const runKernelCommandMock = mock(async (run: RunOpts) => {
|
|
63
|
-
const result = await run.fn(
|
|
64
|
-
graph: { query: queryMock, getOrThrow: getOrThrowMock, mutate: mutateMock },
|
|
65
|
-
})
|
|
81
|
+
const result = await run.fn(commandContext)
|
|
66
82
|
await run.format?.(result, run.opts, true)
|
|
67
83
|
})
|
|
68
84
|
|
|
@@ -88,9 +104,22 @@ beforeEach(() => {
|
|
|
88
104
|
}
|
|
89
105
|
getResult = undefined
|
|
90
106
|
mutationResult = { createdNodes: {} }
|
|
107
|
+
inspectResult = {
|
|
108
|
+
origin: 'notes.example.dev',
|
|
109
|
+
revision: 'notes-v1',
|
|
110
|
+
generation: 'sha256:generation',
|
|
111
|
+
}
|
|
112
|
+
bundleResult = {
|
|
113
|
+
domain: inspectResult,
|
|
114
|
+
bundle: { origin: 'notes.example.dev', revision: 'notes-v1' },
|
|
115
|
+
}
|
|
116
|
+
selfFailure = undefined
|
|
117
|
+
selfContexts = []
|
|
91
118
|
queryMock.mockClear()
|
|
92
119
|
getOrThrowMock.mockClear()
|
|
93
120
|
mutateMock.mockClear()
|
|
121
|
+
inspectMock.mockClear()
|
|
122
|
+
bundleMock.mockClear()
|
|
94
123
|
expandSelfInPathMock.mockClear()
|
|
95
124
|
withSelfHintMock.mockClear()
|
|
96
125
|
runKernelCommandMock.mockClear()
|
|
@@ -161,12 +190,12 @@ describe('query command', () => {
|
|
|
161
190
|
])
|
|
162
191
|
})
|
|
163
192
|
|
|
164
|
-
test('authors a
|
|
193
|
+
test('authors a Class source through the same canonical Query V6 call', async () => {
|
|
165
194
|
const { queryCommand } = await import('../query')
|
|
166
195
|
|
|
167
196
|
await queryCommand([], {
|
|
168
197
|
json: true,
|
|
169
|
-
|
|
198
|
+
class: '/:issues.astrale.ai:class.Issue',
|
|
170
199
|
limit: '20',
|
|
171
200
|
})
|
|
172
201
|
|
|
@@ -179,8 +208,8 @@ describe('query command', () => {
|
|
|
179
208
|
kind: 'node',
|
|
180
209
|
terms: [
|
|
181
210
|
{
|
|
182
|
-
kind: '
|
|
183
|
-
|
|
211
|
+
kind: 'class',
|
|
212
|
+
class: { origin: 'issues.astrale.ai', kind: 'class', name: 'Issue' },
|
|
184
213
|
},
|
|
185
214
|
],
|
|
186
215
|
binding: 'n0',
|
|
@@ -193,6 +222,44 @@ describe('query command', () => {
|
|
|
193
222
|
])
|
|
194
223
|
})
|
|
195
224
|
|
|
225
|
+
test('retains the opaque continuation in machine output without wrapping the graph result', async () => {
|
|
226
|
+
const { queryCommand } = await import('../query')
|
|
227
|
+
const result = {
|
|
228
|
+
kind: 'graph' as const,
|
|
229
|
+
graph: {
|
|
230
|
+
nodes: [{ id: 'issue-1', class: 'issues.astrale.ai:class.Issue', props: {} }],
|
|
231
|
+
edges: [],
|
|
232
|
+
},
|
|
233
|
+
selection: { kind: 'node' as const, ids: ['issue-1'] },
|
|
234
|
+
}
|
|
235
|
+
queryResult = {
|
|
236
|
+
result,
|
|
237
|
+
page: { next: 'opaque-next-page' },
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await queryCommand([], {
|
|
241
|
+
json: true,
|
|
242
|
+
class: '/:issues.astrale.ai:class.Issue',
|
|
243
|
+
limit: '1',
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
expect(JSON.parse(stdout)).toEqual({
|
|
247
|
+
...result,
|
|
248
|
+
page: { next: 'opaque-next-page' },
|
|
249
|
+
})
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
test('resolves @self inside the command session and never relabels transport failure as input', async () => {
|
|
253
|
+
const { queryCommand } = await import('../query')
|
|
254
|
+
await queryCommand(['@self'], { json: true, limit: '2' })
|
|
255
|
+
expect(selfContexts).toEqual([commandContext])
|
|
256
|
+
|
|
257
|
+
const aggregate = new AggregateError([], '')
|
|
258
|
+
selfFailure = aggregate
|
|
259
|
+
await expect(queryCommand(['@self'], { json: true, limit: '2' })).rejects.toBe(aggregate)
|
|
260
|
+
expect(errors.join('\n')).not.toContain('INVALID_INPUT')
|
|
261
|
+
})
|
|
262
|
+
|
|
196
263
|
/** @evidence TEST-CLI-QUERY-REJECTS-V1-BEFORE-CONNECTION */
|
|
197
264
|
test('rejects a legacy AST before opening the command connection', async () => {
|
|
198
265
|
const { queryCommand } = await import('../query')
|
|
@@ -215,7 +282,7 @@ describe('get command', () => {
|
|
|
215
282
|
const { getCommand } = await import('../get')
|
|
216
283
|
getResult = {
|
|
217
284
|
id: 'note-1',
|
|
218
|
-
class: '
|
|
285
|
+
class: 'notes.example.dev:class.Note',
|
|
219
286
|
props: { 'notes.example.dev:class.Note.property.title': 'Hello' },
|
|
220
287
|
}
|
|
221
288
|
|
|
@@ -226,6 +293,47 @@ describe('get command', () => {
|
|
|
226
293
|
expect(stdout).not.toContain('__labels')
|
|
227
294
|
expect(stdout).not.toContain('classId')
|
|
228
295
|
})
|
|
296
|
+
|
|
297
|
+
test('resolves @self through the same point-read command context', async () => {
|
|
298
|
+
const { getCommand } = await import('../get')
|
|
299
|
+
await getCommand('@self', { json: true })
|
|
300
|
+
expect(selfContexts).toEqual([commandContext])
|
|
301
|
+
expect(getTargets).toEqual(['@expanded-self'])
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
describe('introspect command', () => {
|
|
306
|
+
test('uses the split SDK Schema API without recreating the retired introspection request', async () => {
|
|
307
|
+
const { introspectCommand } = await import('../introspect')
|
|
308
|
+
|
|
309
|
+
await introspectCommand(
|
|
310
|
+
'notes.example.dev',
|
|
311
|
+
{ json: true },
|
|
312
|
+
{
|
|
313
|
+
runKernelCommand: runKernelCommandMock as never,
|
|
314
|
+
},
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
expect(inspectMock).toHaveBeenCalledWith('notes.example.dev')
|
|
318
|
+
expect(bundleMock).not.toHaveBeenCalled()
|
|
319
|
+
expect(JSON.parse(stdout)).toEqual(inspectResult)
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
test('requests the immutable bundle only when explicitly selected', async () => {
|
|
323
|
+
const { introspectCommand } = await import('../introspect')
|
|
324
|
+
|
|
325
|
+
await introspectCommand(
|
|
326
|
+
'notes.example.dev',
|
|
327
|
+
{ json: true, bundle: true },
|
|
328
|
+
{
|
|
329
|
+
runKernelCommand: runKernelCommandMock as never,
|
|
330
|
+
},
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
expect(bundleMock).toHaveBeenCalledWith('notes.example.dev')
|
|
334
|
+
expect(inspectMock).not.toHaveBeenCalled()
|
|
335
|
+
expect(JSON.parse(stdout)).toEqual(bundleResult)
|
|
336
|
+
})
|
|
229
337
|
})
|
|
230
338
|
|
|
231
339
|
describe('mutate command', () => {
|
|
@@ -242,7 +350,7 @@ describe('mutate command', () => {
|
|
|
242
350
|
{
|
|
243
351
|
op: 'node.create',
|
|
244
352
|
as: 'note',
|
|
245
|
-
class: '
|
|
353
|
+
class: 'notes.example.dev:class.Note',
|
|
246
354
|
props: {},
|
|
247
355
|
},
|
|
248
356
|
],
|
|
@@ -258,7 +366,7 @@ describe('mutate command', () => {
|
|
|
258
366
|
{
|
|
259
367
|
op: 'node.create',
|
|
260
368
|
as: 'note',
|
|
261
|
-
class: '
|
|
369
|
+
class: 'notes.example.dev:class.Note',
|
|
262
370
|
props: {},
|
|
263
371
|
},
|
|
264
372
|
],
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AuthApi, Identity, IssuerId, MintedCredential } from '@astrale-os/sdk/auth'
|
|
2
|
+
|
|
3
|
+
import { describe, expect, mock, test } from 'bun:test'
|
|
2
4
|
|
|
3
5
|
import { AstraleError } from '../../errors'
|
|
4
|
-
import { parseTtl } from '../token'
|
|
6
|
+
import { issueToken, parseTtl } from '../token'
|
|
5
7
|
|
|
6
8
|
describe('parseTtl', () => {
|
|
7
|
-
test('defaults
|
|
8
|
-
expect(parseTtl(undefined)).toBe(
|
|
9
|
+
test('defaults below the five-minute local source-credential lifetime', () => {
|
|
10
|
+
expect(parseTtl(undefined)).toBe(240)
|
|
9
11
|
})
|
|
10
12
|
|
|
11
13
|
test('rejects non-positive and non-integer values', () => {
|
|
@@ -19,3 +21,46 @@ describe('parseTtl', () => {
|
|
|
19
21
|
expect(parseTtl('90')).toBe(90)
|
|
20
22
|
})
|
|
21
23
|
})
|
|
24
|
+
|
|
25
|
+
describe('issueToken', () => {
|
|
26
|
+
const kernel = 'https://kernel.test' as IssuerId
|
|
27
|
+
const identity = {
|
|
28
|
+
id: 'caller' as Identity['id'],
|
|
29
|
+
issuer: 'https://issuer.test' as Identity['issuer'],
|
|
30
|
+
subject: 'caller' as Identity['subject'],
|
|
31
|
+
frozen: false,
|
|
32
|
+
requiredClaims: [],
|
|
33
|
+
} satisfies Identity
|
|
34
|
+
|
|
35
|
+
test('mints a reusable top-level credential for the Kernel audience', async () => {
|
|
36
|
+
const mint = mock(async () => 'kernel-token' as MintedCredential)
|
|
37
|
+
const delegate = mock(async () => 'delegated-token' as MintedCredential)
|
|
38
|
+
const whoami = mock(async () => identity)
|
|
39
|
+
const auth = { mint, delegate, whoami } satisfies Pick<AuthApi, 'delegate' | 'mint' | 'whoami'>
|
|
40
|
+
|
|
41
|
+
await expect(issueToken(auth, kernel, kernel, 90)).resolves.toBe(
|
|
42
|
+
'kernel-token' as MintedCredential,
|
|
43
|
+
)
|
|
44
|
+
expect(mint).toHaveBeenCalledWith({ ttlSeconds: 90 })
|
|
45
|
+
expect(whoami).not.toHaveBeenCalled()
|
|
46
|
+
expect(delegate).not.toHaveBeenCalled()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('delegates the selected identity only for an external audience', async () => {
|
|
50
|
+
const mint = mock(async () => 'kernel-token' as MintedCredential)
|
|
51
|
+
const delegate = mock(async () => 'delegated-token' as MintedCredential)
|
|
52
|
+
const whoami = mock(async () => identity)
|
|
53
|
+
const auth = { mint, delegate, whoami } satisfies Pick<AuthApi, 'delegate' | 'mint' | 'whoami'>
|
|
54
|
+
|
|
55
|
+
await expect(issueToken(auth, kernel, 'https://service.test' as IssuerId, 120)).resolves.toBe(
|
|
56
|
+
'delegated-token' as MintedCredential,
|
|
57
|
+
)
|
|
58
|
+
expect(mint).not.toHaveBeenCalled()
|
|
59
|
+
expect(whoami).toHaveBeenCalledTimes(1)
|
|
60
|
+
expect(delegate).toHaveBeenCalledWith(identity.id, {
|
|
61
|
+
audience: 'https://service.test',
|
|
62
|
+
ttlSeconds: 120,
|
|
63
|
+
attenuation: { kind: 'identity', self: true },
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
@@ -35,9 +35,11 @@ describe('CLI update staleness', () => {
|
|
|
35
35
|
const result = await cliStale(
|
|
36
36
|
{ channel: 'canary' },
|
|
37
37
|
{
|
|
38
|
-
update: async () => {
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
update: async () => ({
|
|
39
|
+
status: 'managed',
|
|
40
|
+
currentVersion: '1.0.0-beta.0',
|
|
41
|
+
executable: '/opt/homebrew/bin/node',
|
|
42
|
+
}),
|
|
41
43
|
fetchPackageVersion: async ({ channel }) => {
|
|
42
44
|
expect(channel).toBe('canary')
|
|
43
45
|
return '1.0.0-canary.0'
|
|
@@ -52,6 +54,26 @@ describe('CLI update staleness', () => {
|
|
|
52
54
|
})
|
|
53
55
|
})
|
|
54
56
|
|
|
57
|
+
test('does not misclassify a script update failure as package-managed', async () => {
|
|
58
|
+
const fetchPackageVersion = mock(async () => '9.9.9')
|
|
59
|
+
const result = await cliStale(
|
|
60
|
+
{},
|
|
61
|
+
{
|
|
62
|
+
update: async () => {
|
|
63
|
+
throw new Error('release endpoint unavailable')
|
|
64
|
+
},
|
|
65
|
+
fetchPackageVersion,
|
|
66
|
+
},
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
expect(result).toMatchObject({
|
|
70
|
+
stale: false,
|
|
71
|
+
managed: false,
|
|
72
|
+
error: 'release endpoint unavailable',
|
|
73
|
+
})
|
|
74
|
+
expect(fetchPackageVersion).not.toHaveBeenCalled()
|
|
75
|
+
})
|
|
76
|
+
|
|
55
77
|
test('maps the default to beta and the stable channel to npm latest', async () => {
|
|
56
78
|
const originalFetch = globalThis.fetch
|
|
57
79
|
const fetchMock = mock(async (input: RequestInfo | URL) => {
|
|
@@ -52,7 +52,6 @@ const resolved = [
|
|
|
52
52
|
kind: 'definition' as const,
|
|
53
53
|
definitions: [{ origin: 'ai-gateway.astrale.ai', kind: 'class' as const, name: 'Model' }],
|
|
54
54
|
},
|
|
55
|
-
auth: 'required' as const,
|
|
56
55
|
},
|
|
57
56
|
}),
|
|
58
57
|
route({
|
|
@@ -62,7 +61,7 @@ const resolved = [
|
|
|
62
61
|
issuer: 'https://ai-gateway.astrale.ai',
|
|
63
62
|
etag: `sha256:${'c'.repeat(64)}`,
|
|
64
63
|
revision: `sha256:${'d'.repeat(64)}`,
|
|
65
|
-
declaration: { target: { kind: 'domain' as const }
|
|
64
|
+
declaration: { target: { kind: 'domain' as const } },
|
|
66
65
|
}),
|
|
67
66
|
]
|
|
68
67
|
|
|
@@ -147,3 +146,52 @@ describe('view capture timing', () => {
|
|
|
147
146
|
expect(commands.length).toBeGreaterThan(2)
|
|
148
147
|
})
|
|
149
148
|
})
|
|
149
|
+
|
|
150
|
+
describe('view session runtime', () => {
|
|
151
|
+
test('builds one serve config with the admitted operator origin grant', async () => {
|
|
152
|
+
const { createViewServeConfig } = await import('../view')
|
|
153
|
+
const record = {
|
|
154
|
+
id: 'v-proof',
|
|
155
|
+
pid: 0,
|
|
156
|
+
port: 4419,
|
|
157
|
+
nonce: 'proof',
|
|
158
|
+
pageUrl: 'http://127.0.0.1:4419/s/proof/',
|
|
159
|
+
view: { target: Path.parse('/:ai-gateway.astrale.ai').raw, route: resolved[0] },
|
|
160
|
+
createdAt: '2026-08-26T00:00:00.000Z',
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const config = createViewServeConfig(
|
|
164
|
+
record,
|
|
165
|
+
{ allowExternalOrigin: ['https://connect.nango.dev/'] },
|
|
166
|
+
{ url: 'https://kernel.test', kernelIssuer: 'https://kernel.test' },
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
expect(config.session).toBe(record)
|
|
170
|
+
expect(config.externalOrigins).toEqual(['https://connect.nango.dev'])
|
|
171
|
+
expect(config.proxy).toEqual({
|
|
172
|
+
kernelUrl: 'https://kernel.test',
|
|
173
|
+
issuer: 'https://kernel.test',
|
|
174
|
+
caFile: undefined,
|
|
175
|
+
direct: true,
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
test('spawns the detached server from a compiled executable without its virtual Bun entry', async () => {
|
|
180
|
+
const { resolveServeRuntime, viewServeInvocation } = await import('../view')
|
|
181
|
+
|
|
182
|
+
const runtime = await resolveServeRuntime({
|
|
183
|
+
executable: '/opt/astrale/bin/astrale',
|
|
184
|
+
entry: '/$bunfs/root/astrale',
|
|
185
|
+
exists: () => true,
|
|
186
|
+
find: async () => '/usr/bin/node',
|
|
187
|
+
})
|
|
188
|
+
expect(runtime).toEqual({
|
|
189
|
+
file: '/opt/astrale/bin/astrale',
|
|
190
|
+
args: [],
|
|
191
|
+
})
|
|
192
|
+
expect(viewServeInvocation(runtime, '/tmp/view.config.json')).toEqual({
|
|
193
|
+
file: '/opt/astrale/bin/astrale',
|
|
194
|
+
args: ['__view-serve', '--config', '/tmp/view.config.json'],
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
})
|
|
@@ -4,7 +4,7 @@ import { getDefault, readIdentities } from '../../identity/index'
|
|
|
4
4
|
import { deleteIdpSession, listIdpSessions } from '../../lib/idp'
|
|
5
5
|
import { log } from '../../lib/log'
|
|
6
6
|
import { output, RAW_OUTPUT_OPTIONS } from '../../lib/output'
|
|
7
|
-
import { ExchangeCredentialCache } from '../../state/index'
|
|
7
|
+
import { ExchangeCredentialCache, SESSION_ROUTE_STORE } from '../../state/index'
|
|
8
8
|
|
|
9
9
|
export default {
|
|
10
10
|
name: 'logout',
|
|
@@ -30,6 +30,7 @@ export default {
|
|
|
30
30
|
|
|
31
31
|
for (const name of names) await deleteIdpSession(name)
|
|
32
32
|
await new ExchangeCredentialCache().clear()
|
|
33
|
+
SESSION_ROUTE_STORE.clear()
|
|
33
34
|
|
|
34
35
|
if (opts.raw || opts.json) {
|
|
35
36
|
output({ cleared: names }, opts)
|
package/src/commands/browser.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
profileDirFor,
|
|
14
14
|
saveSession,
|
|
15
15
|
} from '../lib/browser'
|
|
16
|
+
import { sweepBrowserProfiles } from '../lib/browser-retention'
|
|
16
17
|
import { readLocalStatus } from '../lib/local-status'
|
|
17
18
|
import { fatal, log } from '../lib/log'
|
|
18
19
|
import { isMachine, output, RAW_OUTPUT_OPTIONS, type RawOutputOpts } from '../lib/output'
|
|
@@ -25,6 +26,29 @@ type BrowserOpts = RawOutputOpts & {
|
|
|
25
26
|
check?: boolean
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Opportunistic profile retention, the same `git gc --auto` shape the session
|
|
31
|
+
* store uses: no daemon, no cron, it just rides on the command that created the
|
|
32
|
+
* mess. Silent when there is nothing to do, and never fatal — losing a sweep is
|
|
33
|
+
* strictly better than losing the browser command.
|
|
34
|
+
*/
|
|
35
|
+
async function reportSweep(machine: boolean): Promise<void> {
|
|
36
|
+
try {
|
|
37
|
+
const swept = await sweepBrowserProfiles()
|
|
38
|
+
if (machine || swept.bytesFreed === 0) return
|
|
39
|
+
const freed = `${(swept.bytesFreed / 1024 / 1024).toFixed(0)} MB`
|
|
40
|
+
const what = [
|
|
41
|
+
swept.removed.length > 0 ? `${swept.removed.length} dormant profile(s) removed` : null,
|
|
42
|
+
swept.purged.length > 0 ? `${swept.purged.length} cache(s) trimmed` : null,
|
|
43
|
+
]
|
|
44
|
+
.filter(Boolean)
|
|
45
|
+
.join(', ')
|
|
46
|
+
log.dim(`retention: ${what} — ${freed} freed`)
|
|
47
|
+
} catch {
|
|
48
|
+
/* retention must never break the browser command */
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
28
52
|
const LOGIN_TIMEOUT_MS = 180_000
|
|
29
53
|
const POLL_INTERVAL_MS = 2500
|
|
30
54
|
|
|
@@ -125,6 +149,11 @@ Examples:
|
|
|
125
149
|
const host = new URL(gui).host
|
|
126
150
|
await requireAgentBrowser(machine, opts)
|
|
127
151
|
|
|
152
|
+
// Retention runs BEFORE anything launches, so no profile we touch can be in
|
|
153
|
+
// use by a browser this command started. Profiles held by someone else's
|
|
154
|
+
// live browser are skipped by the sweep itself.
|
|
155
|
+
await reportSweep(machine)
|
|
156
|
+
|
|
128
157
|
const usingCdp = !!opts.cdp
|
|
129
158
|
const profile = usingCdp ? null : (opts.profile ?? profileDirFor(host))
|
|
130
159
|
const target = usingCdp ? { cdp: opts.cdp } : { profile: profile! }
|
|
@@ -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
|
-
}
|