@astrale-os/cli 1.0.0-beta.0 → 1.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/README.md +23 -12
  2. package/dist/astrale.js +51494 -56307
  3. package/dist/public/connect-core.js +2028 -26846
  4. package/dist/public/keys/index.js +1755 -40694
  5. package/dist/public/paths/index.js +859 -39518
  6. package/dist/types/admin/binding.d.ts +19 -0
  7. package/dist/types/admin/instance/client.d.ts +22 -0
  8. package/dist/types/admin/instance/index.d.ts +2 -0
  9. package/dist/types/admin/instance/model.d.ts +5 -12
  10. package/dist/types/connection/auth.d.ts +3 -0
  11. package/dist/types/connection/call.d.ts +3 -0
  12. package/dist/types/connection/command.d.ts +27 -0
  13. package/dist/types/connection/credential.d.ts +14 -0
  14. package/dist/types/connection/errors.d.ts +1 -0
  15. package/dist/types/connection/exchange.d.ts +9 -0
  16. package/dist/types/connection/failure/classify.d.ts +2 -0
  17. package/dist/types/connection/failure/index.d.ts +5 -0
  18. package/dist/types/connection/failure/model.d.ts +25 -0
  19. package/dist/types/connection/failure/render.d.ts +3 -0
  20. package/dist/types/connection/index.d.ts +8 -0
  21. package/dist/types/connection/reasons.d.ts +37 -0
  22. package/dist/types/connection/self.d.ts +37 -0
  23. package/dist/types/connection/session.d.ts +31 -0
  24. package/dist/types/connection/target.d.ts +38 -0
  25. package/dist/types/errors.d.ts +1 -1
  26. package/dist/types/lib/admin-instance.d.ts +17 -0
  27. package/dist/types/lib/admin-target.d.ts +6 -2
  28. package/dist/types/lib/failure-debug.d.ts +1 -0
  29. package/dist/types/lib/idp.d.ts +7 -0
  30. package/dist/types/lib/instance-target.d.ts +1 -1
  31. package/dist/types/lib/instance.d.ts +10 -2
  32. package/dist/types/lib/log.d.ts +5 -3
  33. package/dist/types/lib/meta.d.ts +2 -2
  34. package/dist/types/lib/proc.d.ts +43 -0
  35. package/dist/types/lib/self.d.ts +9 -0
  36. package/dist/types/lib/update.d.ts +131 -0
  37. package/package.json +8 -10
  38. package/src/__tests__/fixtures/publication.ts +20 -0
  39. package/src/admin/__tests__/binding.test.ts +31 -0
  40. package/src/admin/__tests__/fixture.ts +101 -0
  41. package/src/admin/binding.ts +98 -0
  42. package/src/admin/catalog/.spec/api.d.ts +2 -2
  43. package/src/admin/catalog/__tests__/client.test.ts +20 -49
  44. package/src/admin/catalog/client.ts +36 -32
  45. package/src/admin/catalog/model.ts +3 -4
  46. package/src/admin/graph/.spec/api.d.ts +4 -10
  47. package/src/admin/graph/nodes.ts +1 -1
  48. package/src/admin/instance/.spec/api.d.ts +2 -2
  49. package/src/admin/instance/__tests__/client.test.ts +40 -163
  50. package/src/admin/instance/client.ts +35 -137
  51. package/src/admin/instance/index.ts +1 -2
  52. package/src/admin/instance/model.ts +11 -20
  53. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  54. package/src/commands/__tests__/auth-login.test.ts +54 -1
  55. package/src/commands/__tests__/call-describe.test.ts +46 -33
  56. package/src/commands/__tests__/call.test.ts +5 -1
  57. package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
  58. package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
  59. package/src/commands/__tests__/domain-list.test.ts +63 -4
  60. package/src/commands/__tests__/install-identity-override.test.ts +19 -19
  61. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  62. package/src/commands/__tests__/instance-status.test.ts +139 -0
  63. package/src/commands/__tests__/read-commands.test.ts +35 -10
  64. package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
  65. package/src/commands/__tests__/update.test.ts +95 -0
  66. package/src/commands/call-describe.ts +60 -68
  67. package/src/commands/call.ts +43 -56
  68. package/src/commands/domain/install.ts +13 -17
  69. package/src/commands/domain/list.ts +18 -13
  70. package/src/commands/domain/publish.ts +14 -11
  71. package/src/commands/domain/uninstall.ts +2 -2
  72. package/src/commands/get.ts +14 -15
  73. package/src/commands/identity/__tests__/register.test.ts +3 -3
  74. package/src/commands/identity/register.ts +5 -4
  75. package/src/commands/instance/create.ts +8 -16
  76. package/src/commands/instance/delete.ts +12 -9
  77. package/src/commands/instance/list.ts +2 -2
  78. package/src/commands/instance/status.ts +66 -20
  79. package/src/commands/instance/use.ts +16 -12
  80. package/src/commands/introspect.ts +9 -16
  81. package/src/commands/logs.ts +24 -25
  82. package/src/commands/mutate.ts +6 -5
  83. package/src/commands/query.ts +27 -30
  84. package/src/commands/studio.ts +20 -0
  85. package/src/commands/token.ts +8 -7
  86. package/src/commands/update.ts +68 -22
  87. package/src/commands/view.ts +7 -6
  88. package/src/connection/.spec/api.d.ts +7 -8
  89. package/src/connection/.spec/architecture.md +5 -4
  90. package/src/connection/.spec/flows/session.ts +2 -2
  91. package/src/connection/.spec/laws/connection.ts +6 -2
  92. package/src/connection/.spec/layout.ts +1 -0
  93. package/src/connection/__tests__/credential.test.ts +20 -1
  94. package/src/connection/__tests__/errors.test.ts +43 -32
  95. package/src/connection/__tests__/exchange.test.ts +36 -6
  96. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  97. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  98. package/src/connection/__tests__/self.test.ts +31 -11
  99. package/src/connection/__tests__/session.test.ts +3 -3
  100. package/src/connection/__tests__/target.test.ts +1 -0
  101. package/src/connection/auth.ts +13 -0
  102. package/src/connection/call.ts +1 -1
  103. package/src/connection/credential.ts +2 -2
  104. package/src/connection/errors.ts +1 -355
  105. package/src/connection/exchange.ts +52 -27
  106. package/src/connection/failure/classify.ts +110 -0
  107. package/src/connection/failure/index.ts +18 -0
  108. package/src/connection/failure/model.ts +28 -0
  109. package/src/connection/failure/render.ts +116 -0
  110. package/src/connection/reasons.ts +16 -0
  111. package/src/connection/self.ts +39 -21
  112. package/src/connection/session.ts +19 -8
  113. package/src/errors.ts +3 -2
  114. package/src/graph/.spec/api.d.ts +12 -5
  115. package/src/graph/.spec/layout.ts +9 -1
  116. package/src/graph/__tests__/mutation.test.ts +2 -2
  117. package/src/graph/__tests__/query.test.ts +25 -6
  118. package/src/graph/class.ts +30 -0
  119. package/src/graph/index.ts +1 -0
  120. package/src/graph/query.ts +21 -32
  121. package/src/identity/.spec/api.d.ts +2 -2
  122. package/src/identity/__tests__/registration.test.ts +1 -1
  123. package/src/identity/registration.ts +3 -3
  124. package/src/keys/__tests__/keys.test.ts +4 -0
  125. package/src/keys/credential.ts +1 -0
  126. package/src/lib/__tests__/admin-target.test.ts +12 -0
  127. package/src/lib/__tests__/command-dx.test.ts +1 -1
  128. package/src/lib/__tests__/domain-publication.test.ts +138 -0
  129. package/src/lib/__tests__/idp-session.test.ts +22 -0
  130. package/src/lib/__tests__/idp.test.ts +36 -4
  131. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  132. package/src/lib/__tests__/instance-target.test.ts +7 -39
  133. package/src/lib/__tests__/instance.test.ts +6 -0
  134. package/src/lib/__tests__/log-errors.test.ts +64 -0
  135. package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
  136. package/src/lib/__tests__/update.test.ts +113 -8
  137. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  138. package/src/lib/__tests__/view-server.test.ts +1 -1
  139. package/src/lib/__tests__/view-session.test.ts +1 -1
  140. package/src/lib/admin-instance.ts +14 -8
  141. package/src/lib/admin-target.ts +21 -2
  142. package/src/lib/command-dx.ts +9 -9
  143. package/src/lib/domain-publication.ts +104 -0
  144. package/src/lib/failure-debug.ts +26 -0
  145. package/src/lib/idp.ts +39 -4
  146. package/src/lib/instance-candidates.ts +2 -2
  147. package/src/lib/instance-target.ts +3 -14
  148. package/src/lib/instance.ts +22 -12
  149. package/src/lib/log.ts +16 -9
  150. package/src/lib/login-flow.ts +13 -3
  151. package/src/lib/meta.ts +2 -2
  152. package/src/lib/provision-instance.ts +34 -57
  153. package/src/lib/update.ts +124 -30
  154. package/src/lib/validation.ts +2 -2
  155. package/src/lib/view/resolve.ts +1 -1
  156. package/src/program/__tests__/program.test.ts +20 -4
  157. package/src/program/build.ts +2 -2
  158. package/src/setup/__tests__/instance-step.test.ts +27 -10
  159. package/src/setup/steps/instance.ts +22 -15
  160. package/studio/client/dist/assets/{elk-api-D2xgMJvi.js → elk-api-ByzoDZWH.js} +1 -1
  161. package/studio/client/dist/assets/index-B0RCgUOT.js +8 -0
  162. package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
  163. package/studio/client/dist/assets/index-N8J8EKlB.js +81 -0
  164. package/studio/client/dist/index.html +2 -2
  165. package/studio/package.json +5 -10
  166. package/studio/server/agent/ask.test.ts +1 -1
  167. package/studio/server/agent/bridge/grant.test.ts +1 -1
  168. package/studio/server/agent/bridge/routes.test.ts +1 -1
  169. package/studio/server/agent/bridge/stdio.ts +8 -1
  170. package/studio/server/agent/conversation.test.ts +10 -5
  171. package/studio/server/agent/conversation.ts +56 -8
  172. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  173. package/studio/server/agent/harness/codex/loadout.ts +18 -21
  174. package/studio/server/agent/harness/gateway/config.ts +20 -18
  175. package/studio/server/agent/harness/selection.ts +9 -1
  176. package/studio/server/agent/prompts/anchors.test.ts +32 -36
  177. package/studio/server/agent/prompts/anchors.ts +20 -49
  178. package/studio/server/agent/prompts/system.test.ts +3 -2
  179. package/studio/server/agent/prompts/system.ts +6 -5
  180. package/studio/server/agent/prompts/turn.ts +13 -4
  181. package/studio/server/agent/routes.test.ts +1 -1
  182. package/studio/server/agent/run/completion.ts +2 -2
  183. package/studio/server/agent/run/coordinator.test.ts +1 -1
  184. package/studio/server/agent/run/preparation.ts +6 -5
  185. package/studio/server/agent/run/transcript.test.ts +35 -1
  186. package/studio/server/agent/run/transcript.ts +169 -3
  187. package/studio/server/agent/run/usage.test.ts +24 -0
  188. package/studio/server/agent/run/usage.ts +26 -1
  189. package/studio/server/api/canvas.ts +43 -0
  190. package/studio/server/api/comments.ts +85 -0
  191. package/studio/server/api/context.ts +61 -0
  192. package/studio/server/api/deployment.ts +39 -0
  193. package/studio/server/api/documents.ts +55 -0
  194. package/studio/server/api/domain.ts +59 -0
  195. package/studio/server/api/http.ts +45 -0
  196. package/studio/server/api/project.ts +57 -0
  197. package/studio/server/api/schema.ts +12 -0
  198. package/studio/server/api/views.ts +57 -0
  199. package/studio/server/api/workspace.ts +60 -0
  200. package/studio/server/api-agent-loadout.test.ts +1 -1
  201. package/studio/server/api.test.ts +147 -0
  202. package/studio/server/api.ts +20 -422
  203. package/studio/server/cache.test.ts +122 -0
  204. package/studio/server/cache.ts +162 -11
  205. package/studio/server/cli-consumers.test.ts +494 -0
  206. package/studio/server/cli.test.ts +88 -0
  207. package/studio/server/cli.ts +240 -0
  208. package/studio/server/client-package.ts +25 -1
  209. package/studio/server/domain.test.ts +50 -40
  210. package/studio/server/domain.ts +83 -52
  211. package/studio/server/environment/dotenv-preview.test.ts +39 -0
  212. package/studio/server/environment/dotenv-preview.ts +27 -0
  213. package/studio/server/environment/files.test.ts +53 -0
  214. package/studio/server/{state/env.ts → environment/files.ts} +7 -48
  215. package/studio/server/{state → handoff}/copy.ts +21 -6
  216. package/studio/server/handoff/service.test.ts +22 -0
  217. package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
  218. package/studio/server/index.ts +1 -1
  219. package/studio/server/instances/active.ts +72 -0
  220. package/studio/server/instances/deploy-record.test.ts +31 -0
  221. package/studio/server/instances/deploy-record.ts +37 -0
  222. package/studio/server/instances/deploy.ts +56 -0
  223. package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
  224. package/studio/server/instances/probe.ts +67 -0
  225. package/studio/server/instances/status.test.ts +12 -0
  226. package/studio/server/instances/status.ts +49 -0
  227. package/studio/server/introspect/anatomy/client-tree.ts +57 -0
  228. package/studio/server/introspect/anatomy/env-fields.ts +66 -0
  229. package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
  230. package/studio/server/introspect/anatomy/source.ts +181 -0
  231. package/studio/server/introspect/anatomy/views/routes.ts +114 -0
  232. package/studio/server/introspect/anatomy/views.ts +53 -0
  233. package/studio/server/introspect/anatomy-extras.test.ts +106 -35
  234. package/studio/server/introspect/anatomy-extras.ts +7 -726
  235. package/studio/server/introspect/anatomy.test.ts +22 -14
  236. package/studio/server/introspect/anatomy.ts +52 -28
  237. package/studio/server/introspect/bundle.ts +15 -9
  238. package/studio/server/introspect/canonical-schema.test.ts +93 -309
  239. package/studio/server/introspect/canonical-schema.ts +257 -425
  240. package/studio/server/introspect/config-preview.test.ts +32 -0
  241. package/studio/server/introspect/config-preview.ts +119 -0
  242. package/studio/server/introspect/core-extractor.ts +18 -127
  243. package/studio/server/introspect/core.ts +1 -2
  244. package/studio/server/introspect/diff.test.ts +18 -18
  245. package/studio/server/introspect/diff.ts +44 -90
  246. package/studio/server/introspect/extractor.ts +23 -116
  247. package/studio/server/introspect/hash.ts +5 -2
  248. package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
  249. package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
  250. package/studio/server/introspect/overlay.test.ts +26 -54
  251. package/studio/server/introspect/overlay.ts +10 -37
  252. package/studio/server/introspect/revision.test.ts +54 -0
  253. package/studio/server/introspect/revision.ts +49 -0
  254. package/studio/server/introspect/runtime.test.ts +83 -143
  255. package/studio/server/introspect/runtime.ts +40 -11
  256. package/studio/server/introspect/schema-ir-json.test.ts +70 -0
  257. package/studio/server/introspect/schema-ir-json.ts +151 -0
  258. package/studio/server/introspect/schema-refs.test.ts +43 -88
  259. package/studio/server/introspect/schema-refs.ts +14 -49
  260. package/studio/server/introspect/source-overlay/annotations.ts +14 -0
  261. package/studio/server/introspect/source-overlay/handlers.ts +161 -0
  262. package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
  263. package/studio/server/introspect/source-overlay/project.ts +248 -0
  264. package/studio/server/introspect/source-overlay/spans.ts +330 -0
  265. package/studio/server/json.ts +46 -0
  266. package/studio/server/lifecycle.ts +5 -1
  267. package/studio/server/sse.test.ts +26 -0
  268. package/studio/server/sse.ts +4 -1
  269. package/studio/server/state/baseline.test.ts +223 -7
  270. package/studio/server/state/baseline.ts +148 -34
  271. package/studio/server/state/comments.test.ts +66 -1
  272. package/studio/server/state/comments.ts +173 -10
  273. package/studio/server/state/context.ts +34 -2
  274. package/studio/server/state/documents.ts +42 -1
  275. package/studio/server/state/integrations.ts +27 -1
  276. package/studio/server/state/layout.test.ts +34 -0
  277. package/studio/server/state/layout.ts +44 -17
  278. package/studio/server/state/settings.ts +29 -22
  279. package/studio/server/state/store.test.ts +122 -0
  280. package/studio/server/state/store.ts +66 -17
  281. package/studio/server/state/visibility.ts +22 -11
  282. package/studio/server/views/model.test.ts +57 -0
  283. package/studio/server/views/model.ts +66 -0
  284. package/studio/server/views/runtime.ts +40 -0
  285. package/studio/server/views/selection-repository.test.ts +31 -0
  286. package/studio/server/views/selection-repository.ts +60 -0
  287. package/studio/server/views/session.test.ts +73 -0
  288. package/studio/server/views/session.ts +166 -0
  289. package/studio/server/views/target.test.ts +78 -0
  290. package/studio/server/views/target.ts +222 -0
  291. package/studio/server/watch.test.ts +11 -11
  292. package/studio/server/watch.ts +9 -5
  293. package/studio/server/workspace/catalog.test.ts +17 -0
  294. package/studio/server/workspace/catalog.ts +43 -0
  295. package/studio/server/{state → workspace}/create.test.ts +1 -1
  296. package/studio/server/{state → workspace}/create.ts +1 -1
  297. package/studio/server/{state → workspace}/git.ts +1 -1
  298. package/studio/server/workspace/updates.ts +83 -0
  299. package/studio/server/workspace-state.ts +1 -1
  300. package/studio/server/workspace-watch.ts +2 -2
  301. package/studio/shared/contracts/README.md +16 -0
  302. package/studio/shared/contracts/agent.ts +270 -0
  303. package/studio/shared/contracts/runtime.ts +50 -0
  304. package/studio/shared/contracts/schema.ts +393 -0
  305. package/studio/shared/contracts/surface.test.ts +317 -0
  306. package/studio/shared/contracts/workspace.ts +265 -0
  307. package/studio/shared/layout.test.ts +116 -0
  308. package/studio/shared/schema/identity.test.ts +34 -0
  309. package/studio/shared/schema/identity.ts +68 -0
  310. package/studio/shared/types.ts +11 -1099
  311. package/studio/tsconfig.json +1 -1
  312. package/viewer/dist/main.js +40 -61
  313. package/.check-workspace.cjs +0 -40
  314. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  315. package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
  316. package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
  317. package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
  318. package/studio/server/state/catalog.ts +0 -117
  319. package/studio/server/state/instance.ts +0 -280
  320. package/studio/server/state/updates.ts +0 -63
  321. package/studio/server/state/views.test.ts +0 -286
  322. package/studio/server/state/views.ts +0 -535
@@ -0,0 +1,32 @@
1
+ import { expect, test } from 'bun:test'
2
+
3
+ import { parseConfigPreview } from './config-preview'
4
+
5
+ test('config preview ignores examples in comments and preserves URL literals', () => {
6
+ const preview = parseConfigPreview(`
7
+ // cloudflare({ prod: { route: 'commented.invalid', secrets: '.env.fake' } })
8
+ /* astrale({ prod: { instance: 'commented-instance' } }) */
9
+ export default deploy(domain, cloudflare({
10
+ dev: { client: { dir: 'client' }, secrets: '.env.dev' },
11
+ prod: {
12
+ client: { dir: 'client' },
13
+ route: 'https://services.example.dev/path',
14
+ secrets: '.env.prod',
15
+ },
16
+ }))
17
+ `)
18
+
19
+ expect(preview).toEqual({
20
+ adapter: 'cloudflare',
21
+ prodTarget: 'route: https://services.example.dev/path',
22
+ devSecrets: '.env.dev',
23
+ configuredSecretFiles: ['.env.dev', '.env.prod'],
24
+ })
25
+ })
26
+
27
+ test('config preview reports dynamic configuration as unknown instead of inventing authority', () => {
28
+ expect(parseConfigPreview(`export default makeDeployment(domain)`)).toEqual({
29
+ adapter: 'unknown',
30
+ configuredSecretFiles: [],
31
+ })
32
+ })
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Static, non-authoritative preview of astrale.config.ts.
3
+ *
4
+ * Deployment configuration is owned by the SDK adapter and is executable
5
+ * TypeScript. Studio deliberately does not execute it during anatomy/env reads;
6
+ * these few fields are only display/editor hints and may be unknown when the
7
+ * configuration is computed dynamically.
8
+ */
9
+ import { readFileSync } from 'node:fs'
10
+ import { join } from 'node:path'
11
+
12
+ export interface ConfigPreview {
13
+ adapter: 'astrale' | 'cloudflare' | 'unknown'
14
+ prodTarget?: string
15
+ devSecrets?: string
16
+ configuredSecretFiles: string[]
17
+ }
18
+
19
+ function withoutComments(source: string): string {
20
+ let output = ''
21
+ let quote: "'" | '"' | '`' | null = null
22
+ let escaped = false
23
+ for (let index = 0; index < source.length; index++) {
24
+ const char = source[index]!
25
+ const next = source[index + 1]
26
+ if (quote) {
27
+ output += char
28
+ if (escaped) escaped = false
29
+ else if (char === '\\') escaped = true
30
+ else if (char === quote) quote = null
31
+ continue
32
+ }
33
+ if (char === "'" || char === '"' || char === '`') {
34
+ quote = char
35
+ output += char
36
+ continue
37
+ }
38
+ if (char === '/' && next === '/') {
39
+ while (index + 1 < source.length && source[index + 1] !== '\n') index++
40
+ continue
41
+ }
42
+ if (char === '/' && next === '*') {
43
+ index += 2
44
+ while (index < source.length && !(source[index] === '*' && source[index + 1] === '/')) {
45
+ if (source[index] === '\n') output += '\n'
46
+ index++
47
+ }
48
+ index++
49
+ continue
50
+ }
51
+ output += char
52
+ }
53
+ return output
54
+ }
55
+
56
+ function stringField(source: string, name: string): string | undefined {
57
+ const match = new RegExp(`\\b${name}\\s*:\\s*(['"])(.*?)\\1`).exec(source)
58
+ return match?.[2]
59
+ }
60
+
61
+ function objectBody(source: string, name: string): string | undefined {
62
+ const start = new RegExp(`\\b${name}\\s*:\\s*\\{`).exec(source)
63
+ if (!start) return undefined
64
+ const opening = source.indexOf('{', start.index)
65
+ let depth = 1
66
+ let quote: "'" | '"' | '`' | null = null
67
+ let escaped = false
68
+ for (let index = opening + 1; index < source.length; index++) {
69
+ const char = source[index]!
70
+ if (quote) {
71
+ if (escaped) escaped = false
72
+ else if (char === '\\') escaped = true
73
+ else if (char === quote) quote = null
74
+ continue
75
+ }
76
+ if (char === "'" || char === '"' || char === '`') {
77
+ quote = char
78
+ continue
79
+ }
80
+ if (char === '{') depth++
81
+ else if (char === '}' && --depth === 0) return source.slice(opening + 1, index)
82
+ }
83
+ return undefined
84
+ }
85
+
86
+ export function parseConfigPreview(source: string): ConfigPreview {
87
+ const active = withoutComments(source)
88
+ const adapter: ConfigPreview['adapter'] = /\bastrale\s*\(/.test(active)
89
+ ? 'astrale'
90
+ : /\bcloudflare\s*\(/.test(active)
91
+ ? 'cloudflare'
92
+ : 'unknown'
93
+ const prod = objectBody(active, 'prod') ?? active
94
+ const dev = objectBody(active, 'dev') ?? ''
95
+ const instance = stringField(prod, 'instance')
96
+ const route = stringField(prod, 'route')
97
+ const configuredSecretFiles = [...active.matchAll(/\bsecrets\s*:\s*(['"])(.*?)\1/g)].map(
98
+ (match) => match[2]!,
99
+ )
100
+ const devSecrets = stringField(dev, 'secrets')
101
+ return {
102
+ adapter,
103
+ ...(instance
104
+ ? { prodTarget: `instance: ${instance}` }
105
+ : route
106
+ ? { prodTarget: `route: ${route}` }
107
+ : {}),
108
+ ...(devSecrets ? { devSecrets } : {}),
109
+ configuredSecretFiles: [...new Set(configuredSecretFiles)],
110
+ }
111
+ }
112
+
113
+ export function readConfigPreview(root: string): ConfigPreview {
114
+ try {
115
+ return parseConfigPreview(readFileSync(join(root, 'astrale.config.ts'), 'utf8'))
116
+ } catch {
117
+ return { adapter: 'unknown', configuredSecretFiles: [] }
118
+ }
119
+ }
@@ -1,139 +1,30 @@
1
- /**
2
- * core-extractor.ts — the Bun-executed island for a domain's CORE (genesis) data.
3
- * Spawned as a short-lived subprocess by runtime.ts (cwd = domain dir, so the
4
- * domain's own node_modules resolve @astrale-os/*). It imports the pure schema
5
- * entry and reads canonical V1 `schema.core` directly. Importing the composition
6
- * entry and discovering legacy `defineCore(...)` output is retained only as a
7
- * fallback.
8
- *
9
- * bun core-extractor.ts <schemaIndexPath> <domainFile> <domainDir>
10
- *
11
- * Contract mirrors extractor.ts exactly: NEVER crash. A thrown error prints
12
- * { ok:false } and exits 0 — the driver treats it as a render state. A domain
13
- * with no core prints { ok:true, core:null }.
14
- *
15
- * NOTE: the `export {}` below marks this as a module so its top-level `domainDir`/
16
- * `main` are module-scoped (extractor.ts is a sibling script with the same names).
17
- *
18
- * className resolution: a core node's `def` is the runtime class-definition
19
- * object (shape `{ __kind, config }` — it carries NO name field). We resolve the
20
- * name by identity-matching `def` against the core's own `schema.classes` /
21
- * `schema.interfaces`, AND every `schema.imports[*]` group — imported kernel
22
- * classes like `Folder` ONLY resolve via the imports walk. `data` is passed
23
- * through as the author wrote it in `node(Class, {...})` (most readable form).
24
- */
25
- export {} // module marker — see header note
1
+ /** Bun subprocess that projects canonical Core directly from the pure Schema entry. */
26
2
  import { isAbsolute, resolve } from 'node:path'
27
3
 
28
4
  import { findCanonicalDomainSchemaExport, projectCanonicalCore } from './canonical-schema'
29
5
 
30
- const domainDir = process.argv[4] ?? process.cwd()
31
- const resolveInput = (file: string | undefined): string | undefined =>
32
- file && !isAbsolute(file) ? resolve(domainDir, file) : file
33
- const schemaFile = resolveInput(process.argv[2])
34
- const domainFile = resolveInput(process.argv[3])
6
+ const projectRoot = process.argv[3] ?? process.cwd()
7
+ const input = process.argv[2]
8
+ const schemaFile = input && !isAbsolute(input) ? resolve(projectRoot, input) : input
35
9
 
36
- type AnyRec = Record<string, any>
37
-
38
- /** A defineCore() result: flat __nodes/__edges arrays + its schema + domain. */
39
- function looksLikeCore(v: any): boolean {
40
- return (
41
- !!v &&
42
- typeof v === 'object' &&
43
- Array.isArray(v.__nodes) &&
44
- Array.isArray(v.__edges) &&
45
- !!v.schema &&
46
- typeof v.domain === 'string'
10
+ async function main(): Promise<void> {
11
+ if (!schemaFile) throw new Error('core-extractor: missing <schemaPath>')
12
+ const exports = (await import(schemaFile)) as Record<string, unknown>
13
+ const schema = findCanonicalDomainSchemaExport(exports)
14
+ if (schema === null) throw new Error('Schema entry exports no canonical V1 DomainSchema.')
15
+ const core = projectCanonicalCore(schema)
16
+ process.stdout.write(
17
+ JSON.stringify({
18
+ ok: true,
19
+ core: core.nodes.length === 0 && core.edges.length === 0 ? null : core,
20
+ }),
47
21
  )
48
22
  }
49
23
 
50
- /** Find the Core object — wired as `domain.core`, exported directly, or by shape. */
51
- function findCore(mod: AnyRec): any {
52
- const wired = mod?.domain?.core ?? mod?.default?.core ?? mod?.core
53
- if (looksLikeCore(wired)) return wired
54
- // export name varies per domain (GatewayCore / IntegrationCore / …) — scan by shape
55
- for (const v of Object.values(mod ?? {})) {
56
- if (looksLikeCore(v)) return v
57
- if (v && typeof v === 'object' && looksLikeCore((v as AnyRec).core)) return (v as AnyRec).core
58
- }
59
- return null
60
- }
61
-
62
- /** Build def→className from the schema's own classes/interfaces + imported schemas. */
63
- function classNameMap(schema: AnyRec): Map<any, string> {
64
- const m = new Map<any, string>()
65
- const add = (group?: AnyRec) => {
66
- for (const [name, def] of Object.entries(group ?? {})) if (def && !m.has(def)) m.set(def, name)
67
- }
68
- add(schema?.interfaces)
69
- add(schema?.classes)
70
- for (const imp of schema?.imports ?? []) {
71
- add(imp?.interfaces)
72
- add(imp?.classes)
73
- }
74
- return m
75
- }
76
-
77
- async function main() {
78
- if (!schemaFile) throw new Error('core-extractor: missing <schemaIndexPath>')
79
-
80
- // Current SDK roots embed genesis data in the canonical, portable schema.
81
- // Do not import implementation.ts/domain.ts when that source of truth exists.
82
- try {
83
- const schemaModule: AnyRec = await import(schemaFile)
84
- const canonical = findCanonicalDomainSchemaExport(schemaModule)
85
- if (canonical) {
86
- const core = projectCanonicalCore(canonical)
87
- const empty = core.nodes.length === 0 && core.edges.length === 0
88
- process.stdout.write(JSON.stringify({ ok: true, core: empty ? null : core }))
89
- return
90
- }
91
- } catch {
92
- // A legacy composition entry may still expose a valid defineCore result.
93
- }
94
-
95
- if (!domainFile) throw new Error('core-extractor: missing <domainFile> legacy fallback')
96
- const mod: AnyRec = await import(domainFile)
97
- const core = findCore(mod)
98
- if (!core) {
99
- process.stdout.write(JSON.stringify({ ok: true, core: null }))
100
- return
101
- }
102
-
103
- const names = classNameMap(core.schema)
104
- const nameOf = (def: any): string => names.get(def) ?? def?.config?.name ?? def?.name ?? '?'
105
- // CorePath is a branded string; nested parents are objects with toString/valueOf,
106
- // so String() is the correct universal coercion (never JSON.stringify a path).
107
- const pathStr = (p: any): string => (p == null ? '' : String(p))
108
- // An edge endpoint is a CorePath OR a SelfMarker ({ type:'core-self', __def }).
109
- const endpoint = (e: any): string =>
110
- e && typeof e === 'object' && (e.type === 'core-self' || e.__def)
111
- ? `self(${nameOf(e.__def)})`
112
- : pathStr(e)
113
-
114
- const nodes = (core.__nodes ?? []).map((n: AnyRec) => ({
115
- path: pathStr(n.path),
116
- className: nameOf(n.def),
117
- data: n.data ?? {},
118
- ...(n.parent != null ? { parent: pathStr(n.parent) } : {}),
119
- }))
120
-
121
- const edges = (core.__edges ?? []).map((e: AnyRec) => ({
122
- from: endpoint(e.from),
123
- to: endpoint(e.to),
124
- edgeName: nameOf(e.edge),
125
- ...(e.data != null ? { data: e.data } : {}),
126
- }))
127
-
128
- process.stdout.write(JSON.stringify({ ok: true, core: { domain: core.domain, nodes, edges } }))
129
- }
130
-
131
- main().catch((err: any) => {
24
+ main().catch((cause: unknown) => {
25
+ const error = cause instanceof Error ? cause : new Error(String(cause))
132
26
  process.stdout.write(
133
- JSON.stringify({
134
- ok: false,
135
- error: { message: String(err?.message ?? err), stack: String(err?.stack ?? '') },
136
- }),
27
+ JSON.stringify({ ok: false, error: { message: error.message, stack: error.stack ?? '' } }),
137
28
  )
138
29
  process.exit(0)
139
30
  })
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * core.ts — assembles a domain's StudioCore: the genesis node/edge graph
3
- * extracted from canonical `schema.core` (or legacy `defineCore` fallback), gated
3
+ * extracted from canonical `schema.core`, gated
4
4
  * on installed deps. Never throws; a failed import or a domain with no core both
5
5
  * become a well-formed (empty) render state.
6
6
  */
@@ -28,7 +28,6 @@ export async function buildCore(handle: DomainHandle): Promise<StudioCore> {
28
28
 
29
29
  const r = await coreExtract(
30
30
  handle.schemaIndex,
31
- handle.domainFile,
32
31
  handle.root,
33
32
  readSettings(handle.root).introspectTimeoutMs,
34
33
  )
@@ -2,27 +2,27 @@ import { describe, expect, test } from 'bun:test'
2
2
 
3
3
  import type { IrClass, IrFunction, SchemaIR } from '../../shared/types'
4
4
 
5
- import { classify, diffSchemas } from './diff'
5
+ import { diffSchemas, structuralStatusOf } from './diff'
6
6
 
7
7
  const callable = (returnsType = 'string'): IrFunction => ({
8
8
  name: 'inspect',
9
9
  input: { type: 'object', properties: {}, additionalProperties: false },
10
- params: {},
11
10
  output: { mode: 'value', schema: { type: returnsType } },
12
- returns: { type: returnsType },
13
- static: true,
14
- inheritance: 'default',
15
11
  auth: 'authenticated',
16
12
  })
17
13
 
18
14
  const schema = (functions: SchemaIR['functions']): SchemaIR => ({
19
15
  version: 'v1',
16
+ format: 'astrale.dsl',
20
17
  domain: 'example.test',
21
- types: {},
22
- interfaces: {},
23
18
  classes: {},
24
- imports: {},
19
+ importsByKey: {},
20
+ importedClassesByKey: {},
25
21
  functions,
22
+ views: {},
23
+ policies: {},
24
+ dependencies: [],
25
+ core: {},
26
26
  })
27
27
 
28
28
  const withClass = (member: IrClass): SchemaIR => ({
@@ -31,21 +31,19 @@ const withClass = (member: IrClass): SchemaIR => ({
31
31
  })
32
32
 
33
33
  describe('canonical standalone Function diffs', () => {
34
- test('classifies addition as additive and removal as breaking', () => {
34
+ test('reports additions and removals without claiming Runtime compatibility', () => {
35
35
  const empty = schema({})
36
36
  const populated = schema({ inspect: callable() })
37
- expect(diffSchemas(empty, populated)).toEqual([
38
- { kind: 'function-added', target: 'inspect', breaking: false },
39
- ])
37
+ expect(diffSchemas(empty, populated)).toEqual([{ kind: 'function-added', target: 'inspect' }])
40
38
  const removed = diffSchemas(populated, empty)
41
- expect(removed).toEqual([{ kind: 'function-removed', target: 'inspect', breaking: true }])
42
- expect(classify(removed)).toBe('breaking')
39
+ expect(removed).toEqual([{ kind: 'function-removed', target: 'inspect' }])
40
+ expect(structuralStatusOf(removed)).toBe('changed')
43
41
  })
44
42
 
45
43
  test('detects a standalone Function signature change', () => {
46
44
  expect(
47
45
  diffSchemas(schema({ inspect: callable() }), schema({ inspect: callable('number') })),
48
- ).toEqual([{ kind: 'function-signature-changed', target: 'inspect', breaking: true }])
46
+ ).toEqual([{ kind: 'function-signature-changed', target: 'inspect' }])
49
47
  })
50
48
 
51
49
  test('detects auth and output-mode changes in callable contracts', () => {
@@ -57,7 +55,7 @@ describe('canonical standalone Function diffs', () => {
57
55
  }
58
56
 
59
57
  expect(diffSchemas(schema({ inspect: before }), schema({ inspect: after }))).toEqual([
60
- { kind: 'function-signature-changed', target: 'inspect', breaking: true },
58
+ { kind: 'function-signature-changed', target: 'inspect' },
61
59
  ])
62
60
  })
63
61
 
@@ -65,6 +63,8 @@ describe('canonical standalone Function diffs', () => {
65
63
  const member = (required: string[], minLength: number): IrClass => ({
66
64
  type: 'node',
67
65
  name: 'Person',
66
+ origin: 'example.test',
67
+ ref: { origin: 'example.test', kind: 'class', name: 'Person' },
68
68
  properties: { name: { type: 'string', minLength } },
69
69
  required,
70
70
  methods: {},
@@ -75,13 +75,11 @@ describe('canonical standalone Function diffs', () => {
75
75
  kind: 'prop-schema-changed',
76
76
  target: 'Person.name',
77
77
  detail: 'value constraints changed',
78
- breaking: true,
79
78
  },
80
79
  {
81
80
  kind: 'prop-required-changed',
82
81
  target: 'Person.name',
83
82
  detail: 'optional → required',
84
- breaking: true,
85
83
  },
86
84
  ])
87
85
  })
@@ -91,6 +89,8 @@ describe('canonical standalone Function diffs', () => {
91
89
  ...withClass({
92
90
  type: 'edge',
93
91
  name: 'owns',
92
+ origin: 'example.test',
93
+ ref: { origin: 'example.test', kind: 'class', name: 'owns' },
94
94
  properties: {},
95
95
  required: [],
96
96
  methods: {},