@astrale-os/cli 1.0.0-beta.5 → 1.0.0-beta.7

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.
Files changed (162) hide show
  1. package/dist/astrale.js +66254 -64461
  2. package/dist/public/connect-core.js +14895 -33867
  3. package/dist/public/keys/index.js +1246 -34250
  4. package/dist/public/paths/index.js +866 -33833
  5. package/dist/types/admin/instance/model.d.ts +3 -4
  6. package/dist/types/errors.d.ts +1 -1
  7. package/dist/types/lib/instance-target.d.ts +1 -1
  8. package/dist/types/lib/log.d.ts +2 -2
  9. package/package.json +4 -9
  10. package/src/__tests__/fixtures/publication.ts +20 -0
  11. package/src/admin/__tests__/binding.test.ts +12 -19
  12. package/src/admin/__tests__/fixture.ts +101 -0
  13. package/src/admin/binding.ts +83 -3
  14. package/src/admin/catalog/.spec/api.d.ts +1 -1
  15. package/src/admin/catalog/__tests__/client.test.ts +20 -49
  16. package/src/admin/catalog/client.ts +35 -26
  17. package/src/admin/catalog/model.ts +3 -4
  18. package/src/admin/graph/.spec/api.d.ts +4 -10
  19. package/src/admin/graph/nodes.ts +1 -1
  20. package/src/admin/instance/.spec/api.d.ts +1 -1
  21. package/src/admin/instance/__tests__/client.test.ts +58 -83
  22. package/src/admin/instance/client.ts +49 -39
  23. package/src/admin/instance/model.ts +9 -8
  24. package/src/commands/__tests__/call-describe.test.ts +46 -33
  25. package/src/commands/__tests__/domain-install-operation.test.ts +3 -14
  26. package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
  27. package/src/commands/__tests__/domain-list.test.ts +5 -25
  28. package/src/commands/__tests__/install-identity-override.test.ts +3 -14
  29. package/src/commands/__tests__/read-commands.test.ts +35 -10
  30. package/src/commands/call-describe.ts +59 -67
  31. package/src/commands/call.ts +41 -54
  32. package/src/commands/domain/install.ts +2 -2
  33. package/src/commands/domain/uninstall.ts +2 -2
  34. package/src/commands/get.ts +13 -14
  35. package/src/commands/identity/__tests__/register.test.ts +3 -3
  36. package/src/commands/identity/register.ts +5 -4
  37. package/src/commands/instance/delete.ts +5 -3
  38. package/src/commands/instance/status.ts +1 -9
  39. package/src/commands/introspect.ts +4 -11
  40. package/src/commands/logs.ts +24 -25
  41. package/src/commands/mutate.ts +6 -5
  42. package/src/commands/query.ts +27 -30
  43. package/src/commands/token.ts +8 -7
  44. package/src/commands/view.ts +4 -3
  45. package/src/connection/.spec/api.d.ts +7 -8
  46. package/src/connection/.spec/architecture.md +5 -4
  47. package/src/connection/.spec/flows/session.ts +2 -2
  48. package/src/connection/.spec/laws/connection.ts +6 -2
  49. package/src/connection/.spec/layout.ts +1 -0
  50. package/src/connection/__tests__/credential.test.ts +1 -1
  51. package/src/connection/__tests__/errors.test.ts +27 -20
  52. package/src/connection/__tests__/exchange.test.ts +30 -1
  53. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  54. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  55. package/src/connection/__tests__/self.test.ts +31 -11
  56. package/src/connection/__tests__/session.test.ts +3 -3
  57. package/src/connection/call.ts +1 -1
  58. package/src/connection/credential.ts +2 -2
  59. package/src/connection/errors.ts +1 -355
  60. package/src/connection/exchange.ts +47 -23
  61. package/src/connection/failure/classify.ts +110 -0
  62. package/src/connection/failure/debug.ts +26 -0
  63. package/src/connection/failure/index.ts +18 -0
  64. package/src/connection/failure/model.ts +28 -0
  65. package/src/connection/failure/render.ts +116 -0
  66. package/src/connection/reasons.ts +16 -0
  67. package/src/connection/self.ts +39 -21
  68. package/src/connection/session.ts +8 -8
  69. package/src/errors.ts +3 -2
  70. package/src/graph/.spec/api.d.ts +12 -5
  71. package/src/graph/.spec/layout.ts +9 -1
  72. package/src/graph/__tests__/mutation.test.ts +2 -2
  73. package/src/graph/__tests__/query.test.ts +25 -6
  74. package/src/graph/class.ts +30 -0
  75. package/src/graph/index.ts +1 -0
  76. package/src/graph/query.ts +21 -32
  77. package/src/identity/.spec/api.d.ts +2 -2
  78. package/src/identity/__tests__/registration.test.ts +1 -1
  79. package/src/identity/registration.ts +3 -3
  80. package/src/lib/__tests__/domain-publication.test.ts +4 -15
  81. package/src/lib/__tests__/instance-target.test.ts +6 -39
  82. package/src/lib/__tests__/log-errors.test.ts +53 -0
  83. package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
  84. package/src/lib/command-dx.ts +1 -4
  85. package/src/lib/domain-publication.ts +1 -1
  86. package/src/lib/instance-target.ts +3 -14
  87. package/src/lib/log.ts +11 -6
  88. package/src/lib/validation.ts +2 -2
  89. package/src/lib/view/resolve.ts +1 -1
  90. package/src/program/__tests__/program.test.ts +1 -1
  91. package/studio/client/dist/assets/{elk-api-YEDvaNU-.js → elk-api-Di4OXGNH.js} +1 -1
  92. package/studio/client/dist/assets/index-BLm6J11H.js +81 -0
  93. package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
  94. package/studio/client/dist/assets/index-DTjvkOUX.js +8 -0
  95. package/studio/client/dist/index.html +2 -2
  96. package/studio/package.json +2 -7
  97. package/studio/server/agent/ask.test.ts +1 -1
  98. package/studio/server/agent/bridge/grant.test.ts +1 -1
  99. package/studio/server/agent/bridge/routes.test.ts +1 -1
  100. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  101. package/studio/server/agent/prompts/anchors.test.ts +32 -36
  102. package/studio/server/agent/prompts/anchors.ts +20 -49
  103. package/studio/server/agent/prompts/system.test.ts +3 -2
  104. package/studio/server/agent/prompts/system.ts +3 -3
  105. package/studio/server/agent/routes.test.ts +1 -1
  106. package/studio/server/agent/run/coordinator.test.ts +1 -1
  107. package/studio/server/api/canvas.ts +0 -1
  108. package/studio/server/api-agent-loadout.test.ts +1 -1
  109. package/studio/server/api.test.ts +1 -1
  110. package/studio/server/cache.test.ts +23 -12
  111. package/studio/server/cache.ts +12 -15
  112. package/studio/server/domain.test.ts +50 -68
  113. package/studio/server/domain.ts +82 -63
  114. package/studio/server/handoff/copy.ts +1 -1
  115. package/studio/server/index.ts +1 -1
  116. package/studio/server/instances/probe.test.ts +1 -1
  117. package/studio/server/introspect/anatomy/views/routes.ts +46 -37
  118. package/studio/server/introspect/anatomy/views.ts +9 -14
  119. package/studio/server/introspect/anatomy-extras.test.ts +26 -42
  120. package/studio/server/introspect/anatomy.test.ts +22 -14
  121. package/studio/server/introspect/anatomy.ts +6 -9
  122. package/studio/server/introspect/bundle.ts +0 -3
  123. package/studio/server/introspect/canonical-schema.test.ts +94 -389
  124. package/studio/server/introspect/canonical-schema.ts +227 -457
  125. package/studio/server/introspect/core-extractor.ts +18 -127
  126. package/studio/server/introspect/core.ts +1 -2
  127. package/studio/server/introspect/diff.test.ts +11 -7
  128. package/studio/server/introspect/diff.ts +18 -55
  129. package/studio/server/introspect/extractor.ts +22 -117
  130. package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
  131. package/studio/server/introspect/overlay.test.ts +26 -54
  132. package/studio/server/introspect/overlay.ts +10 -37
  133. package/studio/server/introspect/revision.test.ts +1 -1
  134. package/studio/server/introspect/revision.ts +1 -1
  135. package/studio/server/introspect/runtime.test.ts +65 -183
  136. package/studio/server/introspect/runtime.ts +8 -25
  137. package/studio/server/introspect/schema-ir-json.test.ts +70 -0
  138. package/studio/server/introspect/schema-ir-json.ts +38 -68
  139. package/studio/server/introspect/schema-refs.test.ts +43 -88
  140. package/studio/server/introspect/schema-refs.ts +14 -49
  141. package/studio/server/introspect/source-overlay/handlers.ts +116 -636
  142. package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
  143. package/studio/server/introspect/source-overlay/spans.ts +15 -45
  144. package/studio/server/state/baseline.test.ts +14 -9
  145. package/studio/server/state/baseline.ts +3 -5
  146. package/studio/server/state/visibility.ts +1 -5
  147. package/studio/server/views/model.ts +3 -3
  148. package/studio/server/views/target.test.ts +17 -74
  149. package/studio/server/views/target.ts +24 -50
  150. package/studio/server/watch.test.ts +11 -11
  151. package/studio/server/watch.ts +8 -4
  152. package/studio/server/workspace-watch.ts +2 -2
  153. package/studio/shared/contracts/schema.ts +38 -107
  154. package/studio/shared/contracts/surface.test.ts +12 -15
  155. package/studio/shared/contracts/workspace.ts +2 -11
  156. package/studio/shared/schema/identity.test.ts +20 -44
  157. package/studio/shared/schema/identity.ts +9 -23
  158. package/viewer/dist/main.js +41 -38
  159. package/studio/client/dist/assets/index-C-PvAXV4.js +0 -81
  160. package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
  161. package/studio/client/dist/assets/index-CzpmJD0j.js +0 -8
  162. package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
@@ -1,12 +1,15 @@
1
1
  import type {
2
+ NodeQueryBuilder,
2
3
  QueryAST as QueryASTValue,
3
- QueryDefinitionRef,
4
4
  QueryDirection,
5
+ QueryNodeInput,
5
6
  } from '@astrale-os/sdk/query'
6
7
 
7
8
  import { Path } from '@astrale-os/sdk/graph/path'
8
9
  import { Query, QueryAST } from '@astrale-os/sdk/query'
9
10
 
11
+ import { classReference } from './class'
12
+
10
13
  export interface QueryCommandInput {
11
14
  readonly sources: readonly string[]
12
15
  readonly definition?: string
@@ -51,43 +54,29 @@ export function prepareQuery(input: QueryCommandInput): PreparedQuery {
51
54
  }
52
55
 
53
56
  const paths = input.sources.map((source) => Path.parse(source))
54
- const definition = input.definition === undefined ? undefined : definitionRef(input.definition)
55
- const query =
56
- paths.length > 0
57
- ? Query.from({
58
- kind: 'node',
59
- paths: paths as [Path, ...Path[]],
60
- ...(definition === undefined ? {} : { definitions: [definition] }),
61
- })
62
- : Query.from({ kind: 'node', definitions: [definition!] })
57
+ const definition =
58
+ input.definition === undefined ? undefined : classReference(input.definition, '--definition')
59
+ const nodes = definition === undefined ? paths : [...paths, definition]
60
+ const query: NodeQueryBuilder<unknown> = Query.from({
61
+ nodes: nodes as [QueryNodeInput, ...QueryNodeInput[]],
62
+ })
63
63
  const ast =
64
64
  input.edge === undefined
65
- ? query.select({ kind: 'graph' })
66
- : query
67
- .expand({
68
- via: [definitionRef(input.edge)],
69
- direction: input.direction ?? 'outgoing',
70
- })
71
- .select({ kind: 'graph' })
65
+ ? query.select({ kind: 'graph', binding: query.node })
66
+ : expanded(query, input.edge, input.direction)
72
67
  return withPage(ast, limit, input.cursor)
73
68
  }
74
69
 
75
- function definitionRef(input: string): QueryDefinitionRef {
76
- const path = Path.parse(input)
77
- const step = path.ast.steps[0]
78
- if (
79
- path.ast.anchor.kind !== 'domain' ||
80
- path.ast.steps.length !== 1 ||
81
- step?.kind !== 'projection' ||
82
- (step.projection.kind !== 'class' && step.projection.kind !== 'interface')
83
- ) {
84
- throw new TypeError('--definition must be one canonical Class or Interface Path')
85
- }
86
- return Object.freeze({
87
- origin: path.ast.anchor.origin,
88
- kind: step.projection.kind,
89
- name: step.projection.name,
70
+ function expanded(
71
+ query: NodeQueryBuilder<unknown>,
72
+ edge: string,
73
+ direction: QueryDirection | undefined,
74
+ ): QueryASTValue {
75
+ const result = query.expand({
76
+ via: [classReference(edge, '--edge')],
77
+ direction: direction ?? 'outgoing',
90
78
  })
79
+ return result.select({ kind: 'graph', binding: result.node })
91
80
  }
92
81
 
93
82
  function positiveInteger(raw: string | undefined, name: string, fallback: number): number {
@@ -1,6 +1,6 @@
1
- import type { Call } from '@astrale-os/kernel-client'
2
1
  import type { ProvisionRequest } from '@astrale-os/sdk/auth'
3
- import type { LocalBinding } from '@astrale-os/sdk/graph/model'
2
+ import type { Call } from '@astrale-os/sdk/client'
3
+ import type { LocalBinding } from '@astrale-os/sdk/graph'
4
4
  import type { JWK } from 'jose'
5
5
 
6
6
  import type {
@@ -1,6 +1,6 @@
1
1
  import type { ProvisionRequest } from '@astrale-os/sdk/auth'
2
2
 
3
- import { LocalBinding } from '@astrale-os/sdk/graph/model'
3
+ import { LocalBinding } from '@astrale-os/sdk/graph'
4
4
  import { expect, test } from 'bun:test'
5
5
 
6
6
  import { submitIdentityProvision } from '../registration'
@@ -1,9 +1,9 @@
1
- import type { Call } from '@astrale-os/kernel-client'
2
1
  import type { ProvisionRequest } from '@astrale-os/sdk/auth'
3
- import type { LocalBinding } from '@astrale-os/sdk/graph/model'
2
+ import type { Call } from '@astrale-os/sdk/client'
3
+ import type { LocalBinding } from '@astrale-os/sdk/graph'
4
4
 
5
- import { call } from '@astrale-os/kernel-client'
6
5
  import { issuer } from '@astrale-os/sdk/auth'
6
+ import { call } from '@astrale-os/sdk/client'
7
7
  import { NodeId } from '@astrale-os/sdk/graph/node'
8
8
  import { Path } from '@astrale-os/sdk/graph/path'
9
9
 
@@ -1,26 +1,15 @@
1
- import { publication } from '@astrale-os/kernel-protocol'
2
- import { defineDomain } from '@astrale-os/sdk'
3
- import { issuer } from '@astrale-os/sdk/auth'
4
- import { createDeployment } from '@astrale-os/sdk/deployment'
5
- import { defineSchema } from '@astrale-os/sdk/schema/v1'
1
+ import { publication } from '@astrale-os/sdk/publication'
2
+ import { defineSchema } from '@astrale-os/sdk/schema'
6
3
  import { describe, expect, test } from 'bun:test'
7
4
 
5
+ import { releaseFor } from '../../__tests__/fixtures/publication'
8
6
  import { fetchDomainPublication } from '../domain-publication'
9
7
 
10
8
  const ROOT = 'https://publication-reader.example.dev'
11
9
  const PUBLICATION_URL = `${ROOT}/.well-known/astrale/domain.json`
12
10
  const MAXIMUM_PUBLICATION_BYTES = 1024 * 1024
13
11
  const schema = defineSchema('publication-reader.example.dev', {})
14
- const definition = defineDomain({
15
- schema,
16
- handlers: { functions: {}, classes: {}, interfaces: {} },
17
- })
18
- const deployed = createDeployment({
19
- definition,
20
- issuer: issuer.accept(ROOT),
21
- bundleHref: `${ROOT}/domain.bundle.json`,
22
- bindings: { callables: [] },
23
- }).publication
12
+ const deployed = releaseFor(schema, ROOT).publication
24
13
 
25
14
  describe('Domain Publication reader', () => {
26
15
  test('fetches only the canonical path with redirects disabled', async () => {
@@ -3,6 +3,7 @@ import { describe, expect, test } from 'bun:test'
3
3
  import type { AstraleConfig } from '../config'
4
4
  import type { InstanceStore } from '../instance'
5
5
 
6
+ import { AdminInstanceNotFoundError } from '../../admin/instance/model'
6
7
  import { AstraleError } from '../../errors'
7
8
  import { DEFAULT_CONFIG } from '../config'
8
9
  import {
@@ -124,9 +125,6 @@ describe('resolveInstanceTarget', () => {
124
125
  })
125
126
 
126
127
  test('unknown slugs surface the original instance-not-found error', async () => {
127
- const notFound = new Error('Path not found: "/admin/instances/missing"')
128
- notFound.name = 'NotFoundError'
129
-
130
128
  await expect(
131
129
  resolveInstanceTarget(
132
130
  { source: 'name', name: 'missing' },
@@ -134,7 +132,7 @@ describe('resolveInstanceTarget', () => {
134
132
  config: DEFAULT_CONFIG,
135
133
  instances: emptyStore,
136
134
  managed: async () => {
137
- throw notFound
135
+ throw new AdminInstanceNotFoundError('missing')
138
136
  },
139
137
  },
140
138
  ),
@@ -168,14 +166,8 @@ describe('instance target helpers', () => {
168
166
  expect(couldBeConfiguredAdminInstance('bryan', directAdminConfig)).toBe(false)
169
167
  })
170
168
 
171
- test('treats wrapped remote Instance.info misses as managed lookup not-found', () => {
172
- const wrapped = new Error('Path not found: "/admin/instances/admin"') as Error & {
173
- data?: unknown
174
- }
175
- wrapped.name = 'KernelError'
176
- wrapped.data = { type: 'NotFoundError' }
177
-
178
- expect(isManagedInstanceNotFound(wrapped)).toBe(true)
169
+ test('treats the owner-scoped Admin error as managed lookup not-found', () => {
170
+ expect(isManagedInstanceNotFound(new AdminInstanceNotFoundError('admin'))).toBe(true)
179
171
  })
180
172
 
181
173
  test('does not hide non-not-found managed lookup failures', () => {
@@ -194,37 +186,12 @@ describe('instance target helpers', () => {
194
186
  })
195
187
  })
196
188
 
197
- describe('isManagedInstanceNotFound: kernel InternalKernelError wrap', () => {
198
- test('NOT_FOUND-prefixed InternalKernelError is an instance miss', () => {
199
- const e = new Error('NOT_FOUND: no instance node for "knowledge"')
200
- e.name = 'InternalKernelError'
201
- expect(isManagedInstanceNotFound(e)).toBe(true)
202
- })
203
- test('other InternalKernelError messages are not swallowed', () => {
189
+ describe('isManagedInstanceNotFound: unknown errors', () => {
190
+ test('does not infer a miss from an InternalKernelError message', () => {
204
191
  const e = new Error('DISPATCH_FAILED: handler crashed')
205
192
  e.name = 'InternalKernelError'
206
193
  expect(isManagedInstanceNotFound(e)).toBe(false)
207
194
  })
208
- test('resolveNamedInstanceTarget maps the wrap to typed INSTANCE_NOT_FOUND', async () => {
209
- const managed = async () => {
210
- const e = new Error('NOT_FOUND: no instance node for "ghost"')
211
- e.name = 'InternalKernelError'
212
- throw e
213
- }
214
- const opts = {
215
- config: DEFAULT_CONFIG,
216
- instances: { instances: {} },
217
- managed,
218
- } as unknown as Parameters<typeof resolveInstanceTarget>[1]
219
- let caught: unknown
220
- try {
221
- await resolveInstanceTarget({ source: 'name', name: 'ghost' }, opts)
222
- } catch (e) {
223
- caught = e
224
- }
225
- expect(caught).toBeInstanceOf(AstraleError)
226
- expect((caught as AstraleError).code).toBe('INSTANCE_NOT_FOUND')
227
- })
228
195
 
229
196
  test('maps Admin token-exchange failure to INSTANCE_NOT_FOUND', async () => {
230
197
  const managed = async () => {
@@ -0,0 +1,53 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
2
+
3
+ import { AstraleError } from '../../errors'
4
+ import { failInput, fatal } from '../log'
5
+
6
+ class ExitError extends Error {}
7
+
8
+ let stderr = ''
9
+ let exit: typeof process.exit
10
+ let write: typeof process.stderr.write
11
+
12
+ beforeEach(() => {
13
+ stderr = ''
14
+ exit = process.exit
15
+ write = process.stderr.write
16
+ process.exit = (() => {
17
+ throw new ExitError()
18
+ }) as typeof process.exit
19
+ process.stderr.write = ((chunk: string | Uint8Array) => {
20
+ stderr += String(chunk)
21
+ return true
22
+ }) as typeof process.stderr.write
23
+ })
24
+
25
+ afterEach(() => {
26
+ process.exit = exit
27
+ process.stderr.write = write
28
+ })
29
+
30
+ describe('terminal error safety', () => {
31
+ test('renders an empty aggregate as an honest non-blank unexpected failure', () => {
32
+ expect(() => fatal(new AggregateError([], ''), { json: true })).toThrow(ExitError)
33
+ expect(JSON.parse(stderr)).toEqual({
34
+ error: 'UNEXPECTED_ERROR',
35
+ message: 'The CLI encountered an unexpected internal failure.',
36
+ })
37
+ })
38
+
39
+ test('rejects blank admitted CLI diagnostics', () => {
40
+ expect(() => new AstraleError('INVALID_INPUT', ' ')).toThrow(TypeError)
41
+ })
42
+
43
+ test('labels only expected admission failures as invalid input', () => {
44
+ expect(() => failInput(new TypeError('Authored value is invalid.'), { json: true })).toThrow(
45
+ ExitError,
46
+ )
47
+ expect(JSON.parse(stderr)).toMatchObject({ error: 'INVALID_INPUT' })
48
+
49
+ stderr = ''
50
+ expect(() => failInput(new AggregateError([], ''), { json: true })).toThrow(ExitError)
51
+ expect(JSON.parse(stderr)).toMatchObject({ error: 'UNEXPECTED_ERROR' })
52
+ })
53
+ })
@@ -103,7 +103,7 @@ describe('studio server runtime deps', () => {
103
103
  describe('studio test gate', () => {
104
104
  test('the root and Studio suites include all client, server, and shared tests', () => {
105
105
  expect(cliPackage.scripts?.test).toBe(
106
- 'bun test src studio/client/src studio/server studio/shared && node --test scripts/*.test.mjs',
106
+ 'node scripts/qualification/source-boundary.mjs --target && bun test src studio/client/src studio/server studio/shared && node --test scripts/*.test.mjs',
107
107
  )
108
108
  expect(cliPackage.scripts?.['test:studio']).toBe('pnpm --dir studio test')
109
109
  expect(studioPackage.scripts?.test).toBe('bun test client/src server shared')
@@ -41,12 +41,9 @@ export function renderCommanderError(
41
41
 
42
42
  if (error.code === 'commander.missingArgument') {
43
43
  const usage = usageFor(matched.path, matched.command)
44
- const argName = error.message.match(/'([^']+)'/)?.[1]
45
44
  return maybeMachine(
46
45
  [
47
- `Missing required argument${argName ? ` ${chalk.bold(`<${argName}>`)}` : ''} for ${chalk.bold(
48
- `astrale ${matched.path.join(' ')}`,
49
- )}`,
46
+ `Missing required argument for ${chalk.bold(`astrale ${matched.path.join(' ')}`)}`,
50
47
  '',
51
48
  'Usage:',
52
49
  ` astrale ${usage}`,
@@ -1,4 +1,4 @@
1
- import { publication } from '@astrale-os/kernel-protocol'
1
+ import { publication } from '@astrale-os/sdk/publication'
2
2
 
3
3
  const MAXIMUM_PUBLICATION_BYTES = 1024 * 1024
4
4
  type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>
@@ -1,6 +1,6 @@
1
- import type { InstanceInfo } from '../admin/instance/model'
2
1
  import type { AstraleConfig } from './config'
3
2
 
3
+ import { AdminInstanceNotFoundError, type InstanceInfo } from '../admin/instance/model'
4
4
  import { AstraleError } from '../errors'
5
5
  import {
6
6
  DEFAULT_ADMIN_TARGET_NAME,
@@ -190,19 +190,8 @@ export function isAdminDiscoveryFailure(error: unknown): boolean {
190
190
  }
191
191
 
192
192
  export function isManagedInstanceNotFound(error: unknown): boolean {
193
- if (error instanceof AstraleError && error.code === 'INSTANCE_NOT_FOUND') return true
194
- if (!(error instanceof Error)) return false
195
- if (error.name === 'NotFoundError') return true
196
- // The admin kernel reports a missing instance node as InternalKernelError
197
- // with a NOT_FOUND-prefixed message. In this lookup that's an instance
198
- // miss (config problem), not a kernel fault — map it so callers get the
199
- // typed INSTANCE_NOT_FOUND with remediation instead of a raw kernel error.
200
- if (error.name === 'InternalKernelError' && /^NOT_FOUND\b/.test(error.message)) return true
201
- const data = (error as Error & { data?: unknown }).data
202
193
  return (
203
- error.name === 'KernelError' &&
204
- !!data &&
205
- typeof data === 'object' &&
206
- (data as { type?: unknown }).type === 'NotFoundError'
194
+ error instanceof AdminInstanceNotFoundError ||
195
+ (error instanceof AstraleError && error.code === 'INSTANCE_NOT_FOUND')
207
196
  )
208
197
  }
package/src/lib/log.ts CHANGED
@@ -22,24 +22,29 @@ export function fatal(e: unknown, opts?: MachineOpts): never {
22
22
  // Ctrl-C at an interactive (@inquirer/prompts) prompt — exit quietly with the
23
23
  // SIGINT convention, not a red error line.
24
24
  if (e instanceof Error && e.name === 'ExitPromptError') process.exit(130)
25
- const msg = e instanceof Error ? e.message : String(e)
26
- const code = e instanceof AstraleError ? e.code : e instanceof Error ? e.name : 'Error'
25
+ const msg =
26
+ e instanceof AstraleError ? e.message : 'The CLI encountered an unexpected internal failure.'
27
+ const code = e instanceof AstraleError ? e.code : 'UNEXPECTED_ERROR'
27
28
  if (isMachine(opts)) {
28
29
  const payload: Record<string, unknown> = { error: code, message: msg }
29
30
  if (e instanceof AstraleError && e.hint) payload.hint = e.hint
30
31
  process.stderr.write(JSON.stringify(payload) + '\n')
31
32
  process.exit(1)
32
33
  }
33
- log.error(e instanceof AstraleError ? `${code}: ${msg}` : msg)
34
+ log.error(`${code}: ${msg}`)
34
35
  if (e instanceof AstraleError && e.hint) log.dim(` hint: ${e.hint}`)
35
36
  process.exit(1)
36
37
  }
37
38
 
38
- /** Admit expected invalid input and exit through {@link fatal}. */
39
- export function failClosed(error: unknown, opts?: MachineOpts): never {
39
+ /** Project only a caller-authored admission failure into the CLI input family. */
40
+ export function failInput(error: unknown, opts?: MachineOpts): never {
40
41
  if (error instanceof AstraleError) fatal(error, opts)
42
+ if (!(error instanceof TypeError)) fatal(error, opts)
41
43
  fatal(
42
- new AstraleError('INVALID_INPUT', error instanceof Error ? error.message : String(error)),
44
+ new AstraleError(
45
+ 'INVALID_INPUT',
46
+ error.message.trim() ? error.message : 'CLI input is invalid.',
47
+ ),
43
48
  opts,
44
49
  )
45
50
  }
@@ -1,4 +1,4 @@
1
- import { isDnsLabel } from '@astrale-os/sdk/domain'
1
+ import { isDnsLabel } from '@astrale-os/sdk/value'
2
2
  import { z } from 'zod'
3
3
 
4
4
  import { ReservedSlugError } from '../errors'
@@ -21,7 +21,7 @@ export function validateName(name: string, entity: string): void {
21
21
  }
22
22
 
23
23
  export function validateSlug(slug: string): void {
24
- // Canonical DNS-label rule (`@astrale-os/sdk/domain`): a slug becomes a
24
+ // Canonical Core DNS-label rule: a slug becomes a
25
25
  // hostname label, so reject anything not DNS-safe (§4.7).
26
26
  if (!slug || !isDnsLabel(slug)) {
27
27
  throw new Error(
@@ -1,4 +1,4 @@
1
- import type { ResolvedView as SessionResolvedView } from '@astrale-os/kernel-client/session'
1
+ import type { ResolvedView as SessionResolvedView } from '@astrale-os/sdk/client/session'
2
2
  import type { ResolvedView } from '@astrale-os/shell'
3
3
 
4
4
  import { Path } from '@astrale-os/sdk/graph/path'
@@ -187,7 +187,7 @@ describe('program composition', () => {
187
187
  'whoami',
188
188
  ])
189
189
  expect(createHash('sha256').update(JSON.stringify(surface)).digest('hex')).toBe(
190
- '44f78959867171661197043f5b47eb6d6890274090370e071d10f11b4204850d',
190
+ '42b4812abbbca3d54289a16d0b066dfb3b1caaf1df6597a425c675744466a728',
191
191
  )
192
192
  })
193
193
 
@@ -1 +1 @@
1
- import{m as L}from"./index-C-PvAXV4.js";function S(y,b){for(var u=0;u<b.length;u++){const a=b[u];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in y)){const n=Object.getOwnPropertyDescriptor(a,i);n&&Object.defineProperty(y,i,n.get?n:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(y,Symbol.toStringTag,{value:"Module"}))}function w(y){throw new Error('Could not dynamically require "'+y+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var O={exports:{}},j;function C(){return j||(j=1,(function(y,b){(function(u){y.exports=u()})(function(){return(function(){function u(a,i,n){function d(f,_){if(!i[f]){if(!a[f]){var h=typeof w=="function"&&w;if(!_&&h)return h(f,!0);if(g)return g(f,!0);var o=new Error("Cannot find module '"+f+"'");throw o.code="MODULE_NOT_FOUND",o}var e=i[f]={exports:{}};a[f][0].call(e.exports,function(r){var t=a[f][1][r];return d(t||r)},e,e.exports,u,a,i,n)}return i[f].exports}for(var g=typeof w=="function"&&w,m=0;m<n.length;m++)d(n[m]);return d}return u})()({1:[function(u,a,i){Object.defineProperty(i,"__esModule",{value:!0}),i.default=void 0;function n(o){"@babel/helpers - typeof";return n=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(o)}function d(o,e){if(!(o instanceof e))throw new TypeError("Cannot call a class as a function")}function g(o,e){for(var r=0;r<e.length;r++){var t=e[r];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(o,f(t.key),t)}}function m(o,e,r){return e&&g(o.prototype,e),Object.defineProperty(o,"prototype",{writable:!1}),o}function f(o){var e=_(o,"string");return n(e)=="symbol"?e:e+""}function _(o,e){if(n(o)!="object"||!o)return o;var r=o[Symbol.toPrimitive];if(r!==void 0){var t=r.call(o,e);if(n(t)!="object")return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(o)}i.default=(function(){function o(){var e=this,r=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=r.defaultLayoutOptions,s=t===void 0?{}:t,l=r.algorithms,v=l===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:l,c=r.workerFactory,p=r.workerUrl;if(d(this,o),this.defaultLayoutOptions=s,this.initialized=!1,typeof p>"u"&&typeof c>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var k=c;typeof p<"u"&&typeof c>"u"&&(k=function(M){return new Worker(M)});var E=k(p);if(typeof E.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new h(E),this.worker.postMessage({cmd:"register",algorithms:v}).then(function(P){return e.initialized=!0}).catch(console.err)}return m(o,[{key:"layout",value:function(r){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},s=t.layoutOptions,l=s===void 0?this.defaultLayoutOptions:s,v=t.logging,c=v===void 0?!1:v,p=t.measureExecutionTime,k=p===void 0?!1:p;return r?this.worker.postMessage({cmd:"layout",graph:r,layoutOptions:l,options:{logging:c,measureExecutionTime:k}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker&&this.worker.terminate()}}])})();var h=(function(){function o(e){var r=this;if(d(this,o),e===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=e,this.worker.onmessage=function(t){setTimeout(function(){r.receive(r,t)},0)}}return m(o,[{key:"postMessage",value:function(r){var t=this.id||0;this.id=t+1,r.id=t;var s=this;return new Promise(function(l,v){s.resolvers[t]=function(c,p){c?(s.convertGwtStyleError(c),v(c)):l(p)},s.worker.postMessage(r)})}},{key:"receive",value:function(r,t){var s=t.data,l=r.resolvers[s.id];l&&(delete r.resolvers[s.id],s.error?l(s.error):l(null,s.data))}},{key:"terminate",value:function(){this.worker&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(r){if(r){var t=r.__java$exception;t&&(t.cause&&t.cause.backingJsObject&&(r.cause=t.cause.backingJsObject,this.convertGwtStyleError(r.cause)),delete r.__java$exception)}}}])})()},{}],2:[function(u,a,i){var n=u("./elk-api.js").default;Object.defineProperty(a.exports,"__esModule",{value:!0}),a.exports=n,n.default=n},{"./elk-api.js":1}]},{},[2])(2)})})(O)),O.exports}var x=C();const A=L(x),q=S({__proto__:null,default:A},[x]);export{q as e};
1
+ import{m as L}from"./index-BLm6J11H.js";function S(y,b){for(var u=0;u<b.length;u++){const a=b[u];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in y)){const n=Object.getOwnPropertyDescriptor(a,i);n&&Object.defineProperty(y,i,n.get?n:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(y,Symbol.toStringTag,{value:"Module"}))}function w(y){throw new Error('Could not dynamically require "'+y+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var O={exports:{}},j;function C(){return j||(j=1,(function(y,b){(function(u){y.exports=u()})(function(){return(function(){function u(a,i,n){function d(f,_){if(!i[f]){if(!a[f]){var h=typeof w=="function"&&w;if(!_&&h)return h(f,!0);if(g)return g(f,!0);var o=new Error("Cannot find module '"+f+"'");throw o.code="MODULE_NOT_FOUND",o}var e=i[f]={exports:{}};a[f][0].call(e.exports,function(r){var t=a[f][1][r];return d(t||r)},e,e.exports,u,a,i,n)}return i[f].exports}for(var g=typeof w=="function"&&w,m=0;m<n.length;m++)d(n[m]);return d}return u})()({1:[function(u,a,i){Object.defineProperty(i,"__esModule",{value:!0}),i.default=void 0;function n(o){"@babel/helpers - typeof";return n=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(o)}function d(o,e){if(!(o instanceof e))throw new TypeError("Cannot call a class as a function")}function g(o,e){for(var r=0;r<e.length;r++){var t=e[r];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(o,f(t.key),t)}}function m(o,e,r){return e&&g(o.prototype,e),Object.defineProperty(o,"prototype",{writable:!1}),o}function f(o){var e=_(o,"string");return n(e)=="symbol"?e:e+""}function _(o,e){if(n(o)!="object"||!o)return o;var r=o[Symbol.toPrimitive];if(r!==void 0){var t=r.call(o,e);if(n(t)!="object")return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(o)}i.default=(function(){function o(){var e=this,r=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=r.defaultLayoutOptions,s=t===void 0?{}:t,l=r.algorithms,v=l===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:l,c=r.workerFactory,p=r.workerUrl;if(d(this,o),this.defaultLayoutOptions=s,this.initialized=!1,typeof p>"u"&&typeof c>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var k=c;typeof p<"u"&&typeof c>"u"&&(k=function(M){return new Worker(M)});var E=k(p);if(typeof E.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new h(E),this.worker.postMessage({cmd:"register",algorithms:v}).then(function(P){return e.initialized=!0}).catch(console.err)}return m(o,[{key:"layout",value:function(r){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},s=t.layoutOptions,l=s===void 0?this.defaultLayoutOptions:s,v=t.logging,c=v===void 0?!1:v,p=t.measureExecutionTime,k=p===void 0?!1:p;return r?this.worker.postMessage({cmd:"layout",graph:r,layoutOptions:l,options:{logging:c,measureExecutionTime:k}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker&&this.worker.terminate()}}])})();var h=(function(){function o(e){var r=this;if(d(this,o),e===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=e,this.worker.onmessage=function(t){setTimeout(function(){r.receive(r,t)},0)}}return m(o,[{key:"postMessage",value:function(r){var t=this.id||0;this.id=t+1,r.id=t;var s=this;return new Promise(function(l,v){s.resolvers[t]=function(c,p){c?(s.convertGwtStyleError(c),v(c)):l(p)},s.worker.postMessage(r)})}},{key:"receive",value:function(r,t){var s=t.data,l=r.resolvers[s.id];l&&(delete r.resolvers[s.id],s.error?l(s.error):l(null,s.data))}},{key:"terminate",value:function(){this.worker&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(r){if(r){var t=r.__java$exception;t&&(t.cause&&t.cause.backingJsObject&&(r.cause=t.cause.backingJsObject,this.convertGwtStyleError(r.cause)),delete r.__java$exception)}}}])})()},{}],2:[function(u,a,i){var n=u("./elk-api.js").default;Object.defineProperty(a.exports,"__esModule",{value:!0}),a.exports=n,n.default=n},{"./elk-api.js":1}]},{},[2])(2)})})(O)),O.exports}var x=C();const A=L(x),q=S({__proto__:null,default:A},[x]);export{q as e};