@astrale-os/cli 1.0.0-beta.1 → 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 +51471 -56290
- 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 +39 -164
- package/src/admin/instance/client.ts +35 -124
- 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 +48 -19
- 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 +38 -14
- 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,11 +1,19 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ClientSession } from '@astrale-os/kernel-client/session'
|
|
1
|
+
import type { ClientSession } from '@astrale-os/sdk/client/session'
|
|
3
2
|
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
3
|
+
import type { ResolvedClass } from '@astrale-os/sdk/schema'
|
|
4
4
|
|
|
5
|
-
import { bind } from '@astrale-os/kernel-client/domain'
|
|
6
5
|
import { Path } from '@astrale-os/sdk/graph/path'
|
|
7
6
|
import { Query } from '@astrale-os/sdk/query'
|
|
8
7
|
|
|
8
|
+
import {
|
|
9
|
+
bindAdmin,
|
|
10
|
+
invokeAdminMethod,
|
|
11
|
+
requireAdminBinding,
|
|
12
|
+
requireAdminClass,
|
|
13
|
+
requireAdminCore,
|
|
14
|
+
requireAdminProperty,
|
|
15
|
+
type AdminBinding,
|
|
16
|
+
} from '../binding'
|
|
9
17
|
import { readAllNodes, type AdminGraphApi } from '../graph'
|
|
10
18
|
import {
|
|
11
19
|
AdminDomainNotFoundError,
|
|
@@ -14,16 +22,9 @@ import {
|
|
|
14
22
|
type PublishDomainResult,
|
|
15
23
|
} from './model'
|
|
16
24
|
|
|
17
|
-
const ADMIN_ORIGIN = 'admin.astrale.ai'
|
|
18
25
|
const PAGE_SIZE = 256
|
|
19
26
|
const MAXIMUM_DOMAINS = 10_000
|
|
20
27
|
const MAXIMUM_PAGES = Math.ceil(MAXIMUM_DOMAINS / PAGE_SIZE) + 1
|
|
21
|
-
const DomainRef = Object.freeze({ origin: ADMIN_ORIGIN, kind: 'class' as const, name: 'Domain' })
|
|
22
|
-
const fleetInstallsByDefault = Object.freeze({
|
|
23
|
-
origin: ADMIN_ORIGIN,
|
|
24
|
-
kind: 'class' as const,
|
|
25
|
-
name: 'fleet_installs_domain_by_default',
|
|
26
|
-
})
|
|
27
28
|
|
|
28
29
|
export interface AdminCatalogContext {
|
|
29
30
|
readonly session: ClientSession
|
|
@@ -37,7 +38,7 @@ export interface AdminCatalogApi {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export interface AdminCatalogDependencies {
|
|
40
|
-
readonly bind?: (session: ClientSession) => Promise<
|
|
41
|
+
readonly bind?: (session: ClientSession) => Promise<AdminBinding>
|
|
41
42
|
readonly operationId?: (kind: 'publish' | 'configure-default') => string
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -46,21 +47,22 @@ export async function connectAdminCatalog(
|
|
|
46
47
|
context: AdminCatalogContext,
|
|
47
48
|
dependencies: AdminCatalogDependencies = {},
|
|
48
49
|
): Promise<AdminCatalogApi> {
|
|
49
|
-
const binding = await (dependencies.bind ??
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
const binding = requireAdminBinding(await (dependencies.bind ?? bindAdmin)(context.session))
|
|
51
|
+
const Domain = requireAdminClass(binding, 'Domain', 'node')
|
|
52
|
+
const Fleet = requireAdminClass(binding, 'Fleet', 'node')
|
|
53
|
+
const fleetInstallsByDefault = requireAdminClass(
|
|
54
|
+
binding,
|
|
55
|
+
'fleet_installs_domain_by_default',
|
|
56
|
+
'edge',
|
|
57
|
+
)
|
|
58
|
+
const fleet = requireAdminCore(binding, 'fleet')
|
|
57
59
|
const operationId = dependencies.operationId ?? defaultOperationId
|
|
58
60
|
|
|
59
61
|
const list = async (): Promise<DomainInfo[]> => {
|
|
60
62
|
const [nodes, defaultsPage] = await Promise.all([
|
|
61
63
|
readAllNodes(
|
|
62
64
|
context.graph,
|
|
63
|
-
Query.from({
|
|
65
|
+
Query.from({ nodes: [Domain] }).select({
|
|
64
66
|
kind: 'nodes',
|
|
65
67
|
projection: { kind: 'value' },
|
|
66
68
|
}),
|
|
@@ -108,13 +110,13 @@ export async function connectAdminCatalog(
|
|
|
108
110
|
let entry = existing
|
|
109
111
|
if (registryChanged) {
|
|
110
112
|
entry = domainFromSummary(
|
|
111
|
-
await binding
|
|
113
|
+
await invokeAdminMethod(context.session, binding, Fleet, 'publishDomain', fleet, {
|
|
112
114
|
operationId: operationId('publish'),
|
|
113
115
|
origin: input.origin,
|
|
114
116
|
name: input.name,
|
|
115
117
|
discoveryUrl: input.url,
|
|
116
118
|
...(description === undefined ? {} : { description }),
|
|
117
|
-
}
|
|
119
|
+
}),
|
|
118
120
|
existing?.installByDefault === true,
|
|
119
121
|
)
|
|
120
122
|
}
|
|
@@ -125,13 +127,16 @@ export async function connectAdminCatalog(
|
|
|
125
127
|
(entry.installByDefault ?? false) !== input.installByDefault
|
|
126
128
|
if (defaultChanged) {
|
|
127
129
|
entry = domainFromSummary(
|
|
128
|
-
await
|
|
129
|
-
|
|
130
|
+
await invokeAdminMethod(
|
|
131
|
+
context.session,
|
|
132
|
+
binding,
|
|
133
|
+
Domain,
|
|
134
|
+
'configureDefault',
|
|
130
135
|
Path.parse(entry.id),
|
|
131
136
|
{
|
|
132
137
|
operationId: operationId('configure-default'),
|
|
133
138
|
enabled: input.installByDefault,
|
|
134
|
-
}
|
|
139
|
+
},
|
|
135
140
|
),
|
|
136
141
|
input.installByDefault === true,
|
|
137
142
|
)
|
|
@@ -145,11 +150,7 @@ export async function connectAdminCatalog(
|
|
|
145
150
|
})
|
|
146
151
|
}
|
|
147
152
|
|
|
148
|
-
|
|
149
|
-
return bind(session, await session.installed(ADMIN_ORIGIN))
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
type DynamicDefinition = ReturnType<DomainBinding['$']['class']>
|
|
153
|
+
type DynamicDefinition = ResolvedClass<'node'>
|
|
153
154
|
|
|
154
155
|
function domainFromNode(
|
|
155
156
|
definition: DynamicDefinition,
|
|
@@ -185,7 +186,10 @@ function domainFromSummary(input: unknown, installByDefault: boolean): DomainInf
|
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
function requiredProperty(definition: DynamicDefinition, node: Node, name: string): string {
|
|
188
|
-
return requiredString(
|
|
189
|
+
return requiredString(
|
|
190
|
+
node.props[requireAdminProperty(definition, name).key],
|
|
191
|
+
`Admin Domain.${name}`,
|
|
192
|
+
)
|
|
189
193
|
}
|
|
190
194
|
|
|
191
195
|
function optionalProperty(
|
|
@@ -193,7 +197,7 @@ function optionalProperty(
|
|
|
193
197
|
node: Node,
|
|
194
198
|
name: string,
|
|
195
199
|
): Readonly<Record<string, string>> {
|
|
196
|
-
const value = node.props[definition
|
|
200
|
+
const value = node.props[requireAdminProperty(definition, name).key]
|
|
197
201
|
return value === undefined ? {} : { [name]: requiredString(value, `Admin Domain.${name}`) }
|
|
198
202
|
}
|
|
199
203
|
|
|
@@ -33,10 +33,9 @@ export interface InstallDomainResult {
|
|
|
33
33
|
readonly error?: string | null
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export class AdminDomainNotFoundError extends
|
|
37
|
-
readonly name = 'NotFoundError'
|
|
38
|
-
|
|
36
|
+
export class AdminDomainNotFoundError extends AstraleError {
|
|
39
37
|
constructor(readonly identifier: string) {
|
|
40
|
-
super(`No visible Admin Domain matches ${JSON.stringify(identifier)}.`)
|
|
38
|
+
super('DOMAIN_NOT_FOUND', `No visible Admin Domain matches ${JSON.stringify(identifier)}.`)
|
|
41
39
|
}
|
|
42
40
|
}
|
|
41
|
+
import { AstraleError } from '../../errors'
|
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ClassPath } from '@astrale-os/sdk/graph/class'
|
|
1
|
+
import type { GraphApi } from '@astrale-os/sdk/client'
|
|
3
2
|
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
4
|
-
import type {
|
|
5
|
-
import type { QueryAST, QueryResult } from '@astrale-os/sdk/query'
|
|
3
|
+
import type { QueryAST } from '@astrale-os/sdk/query'
|
|
6
4
|
|
|
7
5
|
/** Smallest Kernel graph capability needed by bounded Admin graph reads. */
|
|
8
|
-
export
|
|
9
|
-
query(ast: QueryAST, options?: GraphQueryOptions): Promise<QueryResult>
|
|
10
|
-
}
|
|
6
|
+
export type AdminGraphQueryApi = Pick<GraphApi, 'query'>
|
|
11
7
|
|
|
12
8
|
/** Caller-scoped graph reads shared by the Admin catalog and Instance journeys. */
|
|
13
|
-
export
|
|
14
|
-
neighbors(source: PathLike, edge: ClassPath, options: NeighborsOptions): Promise<NodePage>
|
|
15
|
-
}
|
|
9
|
+
export type AdminGraphApi = Pick<GraphApi, 'query' | 'neighbors'>
|
|
16
10
|
|
|
17
11
|
export interface ReadAllNodesOptions {
|
|
18
12
|
readonly label: string
|
package/src/admin/graph/nodes.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { ClientSession } from '@astrale-os/sdk/client/session'
|
|
2
|
+
import type { DomainBinding } from '@astrale-os/shell'
|
|
3
3
|
|
|
4
4
|
import type { AdminGraphApi } from '../../graph/.spec/api.js'
|
|
5
5
|
|
|
@@ -1,103 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
3
|
-
import type { QueryAST } from '@astrale-os/sdk/query'
|
|
4
|
-
|
|
5
|
-
import { ClassPath } from '@astrale-os/sdk/graph/class'
|
|
6
|
-
import { NodeId } from '@astrale-os/sdk/graph/node'
|
|
7
|
-
import { Path } from '@astrale-os/sdk/graph/path'
|
|
8
|
-
import { describe, expect, mock, test } from 'bun:test'
|
|
9
|
-
|
|
10
|
-
import type { AdminGraphApi } from '../../graph'
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
11
2
|
|
|
3
|
+
import { adminBinding, adminSession } from '../../__tests__/fixture'
|
|
12
4
|
import { connectAdminInstances } from '../client'
|
|
13
5
|
|
|
14
|
-
const methods: Array<{ owner: string; name: string }> = []
|
|
15
|
-
|
|
16
|
-
function definition(name: string) {
|
|
17
|
-
return {
|
|
18
|
-
name,
|
|
19
|
-
$: {
|
|
20
|
-
method(method: string) {
|
|
21
|
-
const value = { owner: name, name: method }
|
|
22
|
-
methods.push(value)
|
|
23
|
-
return value
|
|
24
|
-
},
|
|
25
|
-
property(property: string) {
|
|
26
|
-
return { key: property }
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function node(id: string, props: Record<string, unknown>): Node {
|
|
33
|
-
return {
|
|
34
|
-
id: NodeId(id),
|
|
35
|
-
class: ClassPath.from('admin.astrale.ai', 'Instance'),
|
|
36
|
-
props: props as never,
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function graphResult(nodes: readonly Node[], cursor?: string) {
|
|
41
|
-
return {
|
|
42
|
-
result: {
|
|
43
|
-
kind: 'nodes' as const,
|
|
44
|
-
nodes: nodes.map((value) => ({ kind: 'value' as const, value })),
|
|
45
|
-
},
|
|
46
|
-
page: cursor === undefined ? {} : { next: cursor },
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function sourceName(ast: QueryAST): string | undefined {
|
|
51
|
-
const term = ast.source.terms[0]
|
|
52
|
-
return term?.kind === 'definition' ? term.definition.name : undefined
|
|
53
|
-
}
|
|
54
|
-
|
|
55
6
|
function fixture(input: {
|
|
56
|
-
instances?: readonly Node[]
|
|
57
|
-
hosts?: readonly Node[]
|
|
58
|
-
reserved?: Node | null
|
|
59
7
|
invoke?: (method: { owner: string; name: string }, receiver: unknown, input: unknown) => unknown
|
|
60
8
|
}) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
$: {
|
|
70
|
-
publication: { origin: 'admin.astrale.ai' },
|
|
71
|
-
origin: 'admin.astrale.ai',
|
|
72
|
-
class(name: string) {
|
|
73
|
-
if (name === 'Instance') return Instance
|
|
74
|
-
if (name === 'Host') return Host
|
|
75
|
-
if (name === 'Fleet') return Fleet
|
|
76
|
-
throw new Error(`Unexpected class ${name}`)
|
|
77
|
-
},
|
|
78
|
-
core: { nodes: { fleet: { path: Path.id(NodeId('fleet')) } } },
|
|
79
|
-
invoke,
|
|
80
|
-
},
|
|
81
|
-
} as unknown as DomainBinding
|
|
82
|
-
const query = mock(async (ast: QueryAST) => {
|
|
83
|
-
const name = sourceName(ast)
|
|
84
|
-
if (name === 'Instance') return graphResult(input.instances ?? [])
|
|
85
|
-
if (name === 'Host') return graphResult(input.hosts ?? [])
|
|
86
|
-
throw new Error(`Unexpected graph query ${String(name)}`)
|
|
9
|
+
const calls: Array<{
|
|
10
|
+
method: { owner: string; name: string }
|
|
11
|
+
receiver: string
|
|
12
|
+
value: unknown
|
|
13
|
+
}> = []
|
|
14
|
+
const remote = adminSession((method, receiver, value) => {
|
|
15
|
+
calls.push({ method, receiver: String(receiver), value })
|
|
16
|
+
return input.invoke?.(method, receiver, value)
|
|
87
17
|
})
|
|
88
|
-
const
|
|
89
|
-
if (String(source) === '@fleet') return page(input.reserved ?? null)
|
|
90
|
-
if (edge.name === 'instance_runs_on_host') return page(input.hosts?.[0] ?? null)
|
|
91
|
-
throw new Error(`Unexpected neighbor query ${String(source)} ${String(edge)}`)
|
|
92
|
-
})
|
|
93
|
-
const graph = { query, neighbors } as unknown as AdminGraphApi
|
|
18
|
+
const binding = adminBinding()
|
|
94
19
|
return {
|
|
95
20
|
binding,
|
|
96
|
-
|
|
97
|
-
|
|
21
|
+
invoke: remote.invoke,
|
|
22
|
+
calls,
|
|
98
23
|
connect: () =>
|
|
99
24
|
connectAdminInstances(
|
|
100
|
-
{ session:
|
|
25
|
+
{ session: remote.session },
|
|
101
26
|
{
|
|
102
27
|
bind: async () => binding,
|
|
103
28
|
operationId: (kind) => `cli.instance.${kind}:test`,
|
|
@@ -106,15 +31,6 @@ function fixture(input: {
|
|
|
106
31
|
}
|
|
107
32
|
}
|
|
108
33
|
|
|
109
|
-
function page(item: Node | null) {
|
|
110
|
-
return {
|
|
111
|
-
nodes: item === null ? [] : [item],
|
|
112
|
-
first: item,
|
|
113
|
-
graph: { nodes: item === null ? [] : [item], edges: [] },
|
|
114
|
-
cursor: null,
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
34
|
describe('V2 Admin Instance adapter', () => {
|
|
119
35
|
test('lists caller-visible Instances through the Admin-owned Fleet operation', async () => {
|
|
120
36
|
const contract = fixture({
|
|
@@ -128,8 +44,6 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
128
44
|
state: 'ready',
|
|
129
45
|
createdAt: '2026-08-12T00:00:00.000Z',
|
|
130
46
|
updatedAt: '2026-08-12T00:00:00.000Z',
|
|
131
|
-
hostId: '@host-node',
|
|
132
|
-
region: 'fr-par',
|
|
133
47
|
},
|
|
134
48
|
]
|
|
135
49
|
: undefined,
|
|
@@ -142,15 +56,15 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
142
56
|
url: 'https://demo.eu.astrale.ai',
|
|
143
57
|
state: 'ready',
|
|
144
58
|
createdAt: '2026-08-12T00:00:00.000Z',
|
|
145
|
-
hostId: '@host-node',
|
|
146
|
-
region: 'fr-par',
|
|
147
59
|
},
|
|
148
60
|
])
|
|
149
|
-
expect(contract.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
61
|
+
expect(contract.calls).toEqual([
|
|
62
|
+
{
|
|
63
|
+
method: { owner: 'Fleet', name: 'listInstances' },
|
|
64
|
+
receiver: '/:admin.astrale.ai:core.fleet::listInstances',
|
|
65
|
+
value: {},
|
|
66
|
+
},
|
|
67
|
+
])
|
|
154
68
|
})
|
|
155
69
|
|
|
156
70
|
test('delegates default placement to Fleet without reading Host inventory', async () => {
|
|
@@ -162,10 +76,7 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
162
76
|
createdAt: '2026-08-12T00:00:00.000Z',
|
|
163
77
|
updatedAt: '2026-08-12T00:00:00.000Z',
|
|
164
78
|
}
|
|
165
|
-
const contract = fixture({
|
|
166
|
-
hosts: [node('host-node', { id: 'host-paris', state: 'ready' })],
|
|
167
|
-
invoke: () => created,
|
|
168
|
-
})
|
|
79
|
+
const contract = fixture({ invoke: () => created })
|
|
169
80
|
|
|
170
81
|
await expect((await contract.connect()).create('demo')).resolves.toMatchObject({
|
|
171
82
|
id: created.id,
|
|
@@ -174,47 +85,17 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
174
85
|
state: created.state,
|
|
175
86
|
createdAt: created.createdAt,
|
|
176
87
|
})
|
|
177
|
-
expect(contract.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
test('resolves --host-id to an exact Host receiver and rejects the reserved Admin Host', async () => {
|
|
187
|
-
const reserved = node('admin-host', { id: 'admin', state: 'ready' })
|
|
188
|
-
const consumer = node('consumer-host', { id: 'consumer-paris', state: 'ready' })
|
|
189
|
-
const contract = fixture({
|
|
190
|
-
hosts: [reserved, consumer],
|
|
191
|
-
reserved,
|
|
192
|
-
invoke: () => ({
|
|
193
|
-
id: '@instance-node',
|
|
194
|
-
slug: 'demo',
|
|
195
|
-
url: 'https://demo.eu.astrale.ai',
|
|
196
|
-
state: 'ready',
|
|
197
|
-
}),
|
|
198
|
-
})
|
|
199
|
-
const api = await contract.connect()
|
|
200
|
-
|
|
201
|
-
await expect(api.create('demo', 'admin')).rejects.toMatchObject({ name: 'NotFoundError' })
|
|
202
|
-
await expect(api.create('demo', 'consumer-paris')).resolves.toMatchObject({ slug: 'demo' })
|
|
203
|
-
expect(contract.invoke).toHaveBeenCalledWith(
|
|
204
|
-
expect.objectContaining({ owner: 'Host', name: 'createInstance' }),
|
|
205
|
-
Path.id(NodeId('consumer-host')),
|
|
206
|
-
{ operationId: 'cli.instance.create:test', slug: 'demo' },
|
|
207
|
-
)
|
|
88
|
+
expect(contract.calls).toEqual([
|
|
89
|
+
{
|
|
90
|
+
method: { owner: 'Fleet', name: 'createInstance' },
|
|
91
|
+
receiver: '/:admin.astrale.ai:core.fleet::createInstance',
|
|
92
|
+
value: { operationId: 'cli.instance.create:test', slug: 'demo' },
|
|
93
|
+
},
|
|
94
|
+
])
|
|
208
95
|
})
|
|
209
96
|
|
|
210
97
|
test('refreshes and deletes through the resolved Instance receiver', async () => {
|
|
211
|
-
const instance = node('instance-node', {
|
|
212
|
-
slug: 'demo',
|
|
213
|
-
url: 'https://demo.eu.astrale.ai',
|
|
214
|
-
state: 'ready',
|
|
215
|
-
})
|
|
216
98
|
const contract = fixture({
|
|
217
|
-
instances: [instance],
|
|
218
99
|
invoke: (method) =>
|
|
219
100
|
method.name === 'listInstances'
|
|
220
101
|
? [
|
|
@@ -238,22 +119,16 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
238
119
|
|
|
239
120
|
await expect(api.status('demo')).resolves.toMatchObject({ state: 'ready' })
|
|
240
121
|
await expect(api.delete('@instance-node')).resolves.toMatchObject({ state: 'deleted' })
|
|
241
|
-
expect(contract.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
122
|
+
expect(contract.calls.map(({ method }) => method)).toEqual([
|
|
123
|
+
{ owner: 'Fleet', name: 'listInstances' },
|
|
124
|
+
{ owner: 'Instance', name: 'status' },
|
|
125
|
+
{ owner: 'Fleet', name: 'listInstances' },
|
|
126
|
+
{ owner: 'Instance', name: 'delete' },
|
|
246
127
|
])
|
|
247
128
|
})
|
|
248
129
|
|
|
249
130
|
test('installs a resolved catalog Domain through Instance.installDomain', async () => {
|
|
250
|
-
const instance = node('instance-node', {
|
|
251
|
-
slug: 'demo',
|
|
252
|
-
url: 'https://demo.eu.astrale.ai',
|
|
253
|
-
state: 'ready',
|
|
254
|
-
})
|
|
255
131
|
const contract = fixture({
|
|
256
|
-
instances: [instance],
|
|
257
132
|
invoke: (method) =>
|
|
258
133
|
method.name === 'listInstances'
|
|
259
134
|
? [
|
|
@@ -282,10 +157,10 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
282
157
|
origin: 'crm.acme.dev',
|
|
283
158
|
ok: true,
|
|
284
159
|
})
|
|
285
|
-
expect(contract.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
{ operationId: 'cli.instance.install-domain:test', domain: '@crm-domain' },
|
|
289
|
-
)
|
|
160
|
+
expect(contract.calls.at(-1)).toEqual({
|
|
161
|
+
method: { owner: 'Instance', name: 'installDomain' },
|
|
162
|
+
receiver: '@instance-node::installDomain',
|
|
163
|
+
value: { operationId: 'cli.instance.install-domain:test', domain: '@crm-domain' },
|
|
164
|
+
})
|
|
290
165
|
})
|
|
291
166
|
})
|