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

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 (180) hide show
  1. package/README.md +7 -11
  2. package/dist/astrale.js +3769 -3549
  3. package/dist/public/connect-core.js +396 -392
  4. package/dist/public/keys/index.js +371 -378
  5. package/dist/public/paths/index.js +371 -378
  6. package/dist/types/lib/idp.d.ts +6 -0
  7. package/dist/types/lib/meta.d.ts +2 -2
  8. package/package.json +6 -4
  9. package/src/admin/binding.ts +168 -0
  10. package/src/admin/catalog/__tests__/client.test.ts +2 -2
  11. package/src/admin/catalog/client.ts +4 -9
  12. package/src/admin/instance/__tests__/client.test.ts +5 -3
  13. package/src/admin/instance/client.ts +9 -27
  14. package/src/commands/__tests__/auth-login.test.ts +54 -1
  15. package/src/commands/__tests__/call.test.ts +5 -1
  16. package/src/commands/__tests__/domain-install-operation.test.ts +23 -7
  17. package/src/commands/__tests__/domain-install-owned.test.ts +5 -1
  18. package/src/commands/__tests__/domain-list.test.ts +83 -4
  19. package/src/commands/__tests__/install-identity-override.test.ts +30 -19
  20. package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
  21. package/src/commands/__tests__/update.test.ts +73 -0
  22. package/src/commands/domain/install.ts +11 -15
  23. package/src/commands/domain/list.ts +17 -12
  24. package/src/commands/studio.ts +20 -0
  25. package/src/commands/update.ts +39 -13
  26. package/src/connection/__tests__/errors.test.ts +16 -12
  27. package/src/connection/__tests__/exchange.test.ts +6 -5
  28. package/src/connection/exchange.ts +5 -4
  29. package/src/lib/__tests__/domain-publication.test.ts +144 -0
  30. package/src/lib/__tests__/idp-session.test.ts +22 -0
  31. package/src/lib/__tests__/idp.test.ts +2 -0
  32. package/src/lib/__tests__/instance.test.ts +6 -0
  33. package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
  34. package/src/lib/__tests__/update.test.ts +12 -0
  35. package/src/lib/domain-publication.ts +102 -0
  36. package/src/lib/idp.ts +5 -1
  37. package/src/lib/instance.ts +6 -1
  38. package/src/lib/login-flow.ts +13 -3
  39. package/src/lib/meta.ts +2 -2
  40. package/src/lib/update.ts +4 -4
  41. package/src/program/__tests__/program.test.ts +1 -1
  42. package/studio/client/dist/assets/{elk-api-D2xgMJvi.js → elk-api-lwhFo7vB.js} +1 -1
  43. package/studio/client/dist/assets/index-B-c-smo9.js +8 -0
  44. package/studio/client/dist/assets/index-BckHuAWk.js +81 -0
  45. package/studio/client/dist/assets/index-C4aNQ6dz.css +1 -0
  46. package/studio/client/dist/index.html +2 -2
  47. package/studio/package.json +3 -1
  48. package/studio/server/agent/bridge/stdio.ts +8 -1
  49. package/studio/server/agent/conversation.test.ts +10 -5
  50. package/studio/server/agent/conversation.ts +56 -8
  51. package/studio/server/agent/harness/codex/loadout.ts +18 -21
  52. package/studio/server/agent/harness/gateway/config.ts +20 -18
  53. package/studio/server/agent/harness/selection.ts +9 -1
  54. package/studio/server/agent/prompts/system.ts +3 -2
  55. package/studio/server/agent/prompts/turn.ts +13 -4
  56. package/studio/server/agent/run/completion.ts +2 -2
  57. package/studio/server/agent/run/preparation.ts +6 -5
  58. package/studio/server/agent/run/transcript.test.ts +35 -1
  59. package/studio/server/agent/run/transcript.ts +169 -3
  60. package/studio/server/agent/run/usage.test.ts +24 -0
  61. package/studio/server/agent/run/usage.ts +26 -1
  62. package/studio/server/api/canvas.ts +44 -0
  63. package/studio/server/api/comments.ts +85 -0
  64. package/studio/server/api/context.ts +61 -0
  65. package/studio/server/api/deployment.ts +39 -0
  66. package/studio/server/api/documents.ts +55 -0
  67. package/studio/server/api/domain.ts +59 -0
  68. package/studio/server/api/http.ts +45 -0
  69. package/studio/server/api/project.ts +57 -0
  70. package/studio/server/api/schema.ts +12 -0
  71. package/studio/server/api/views.ts +57 -0
  72. package/studio/server/api/workspace.ts +60 -0
  73. package/studio/server/api.test.ts +147 -0
  74. package/studio/server/api.ts +20 -422
  75. package/studio/server/cache.test.ts +111 -0
  76. package/studio/server/cache.ts +163 -9
  77. package/studio/server/cli-consumers.test.ts +494 -0
  78. package/studio/server/cli.test.ts +88 -0
  79. package/studio/server/cli.ts +240 -0
  80. package/studio/server/client-package.ts +25 -1
  81. package/studio/server/domain.test.ts +30 -2
  82. package/studio/server/domain.ts +14 -2
  83. package/studio/server/environment/dotenv-preview.test.ts +39 -0
  84. package/studio/server/environment/dotenv-preview.ts +27 -0
  85. package/studio/server/environment/files.test.ts +53 -0
  86. package/studio/server/{state/env.ts → environment/files.ts} +7 -48
  87. package/studio/server/{state → handoff}/copy.ts +21 -6
  88. package/studio/server/handoff/service.test.ts +22 -0
  89. package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
  90. package/studio/server/instances/active.ts +72 -0
  91. package/studio/server/instances/deploy-record.test.ts +31 -0
  92. package/studio/server/instances/deploy-record.ts +37 -0
  93. package/studio/server/instances/deploy.ts +56 -0
  94. package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
  95. package/studio/server/instances/probe.ts +67 -0
  96. package/studio/server/instances/status.test.ts +12 -0
  97. package/studio/server/instances/status.ts +49 -0
  98. package/studio/server/introspect/anatomy/client-tree.ts +57 -0
  99. package/studio/server/introspect/anatomy/env-fields.ts +66 -0
  100. package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
  101. package/studio/server/introspect/anatomy/source.ts +181 -0
  102. package/studio/server/introspect/anatomy/views/legacy.ts +232 -0
  103. package/studio/server/introspect/anatomy/views/routes.ts +105 -0
  104. package/studio/server/introspect/anatomy/views.ts +58 -0
  105. package/studio/server/introspect/anatomy-extras.test.ts +91 -4
  106. package/studio/server/introspect/anatomy-extras.ts +7 -726
  107. package/studio/server/introspect/anatomy.ts +46 -19
  108. package/studio/server/introspect/bundle.ts +15 -6
  109. package/studio/server/introspect/canonical-schema.test.ts +79 -0
  110. package/studio/server/introspect/canonical-schema.ts +80 -18
  111. package/studio/server/introspect/config-preview.test.ts +32 -0
  112. package/studio/server/introspect/config-preview.ts +119 -0
  113. package/studio/server/introspect/diff.test.ts +7 -11
  114. package/studio/server/introspect/diff.ts +28 -37
  115. package/studio/server/introspect/extractor.ts +8 -6
  116. package/studio/server/introspect/hash.ts +5 -2
  117. package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
  118. package/studio/server/introspect/revision.test.ts +54 -0
  119. package/studio/server/introspect/revision.ts +49 -0
  120. package/studio/server/introspect/runtime.test.ts +63 -5
  121. package/studio/server/introspect/runtime.ts +49 -3
  122. package/studio/server/introspect/schema-ir-json.ts +181 -0
  123. package/studio/server/introspect/source-overlay/annotations.ts +14 -0
  124. package/studio/server/introspect/source-overlay/handlers.ts +681 -0
  125. package/studio/server/introspect/source-overlay/kernel-calls.ts +49 -0
  126. package/studio/server/introspect/source-overlay/project.ts +248 -0
  127. package/studio/server/introspect/source-overlay/spans.ts +360 -0
  128. package/studio/server/json.ts +46 -0
  129. package/studio/server/lifecycle.ts +5 -1
  130. package/studio/server/sse.test.ts +26 -0
  131. package/studio/server/sse.ts +4 -1
  132. package/studio/server/state/baseline.test.ts +212 -1
  133. package/studio/server/state/baseline.ts +145 -29
  134. package/studio/server/state/comments.test.ts +66 -1
  135. package/studio/server/state/comments.ts +173 -10
  136. package/studio/server/state/context.ts +34 -2
  137. package/studio/server/state/documents.ts +42 -1
  138. package/studio/server/state/integrations.ts +27 -1
  139. package/studio/server/state/layout.test.ts +34 -0
  140. package/studio/server/state/layout.ts +44 -17
  141. package/studio/server/state/settings.ts +29 -22
  142. package/studio/server/state/store.test.ts +122 -0
  143. package/studio/server/state/store.ts +66 -17
  144. package/studio/server/state/visibility.ts +22 -7
  145. package/studio/server/views/model.test.ts +57 -0
  146. package/studio/server/views/model.ts +66 -0
  147. package/studio/server/views/runtime.ts +40 -0
  148. package/studio/server/views/selection-repository.test.ts +31 -0
  149. package/studio/server/views/selection-repository.ts +60 -0
  150. package/studio/server/views/session.test.ts +73 -0
  151. package/studio/server/views/session.ts +166 -0
  152. package/studio/server/{state/views.test.ts → views/target.test.ts} +8 -159
  153. package/studio/server/views/target.ts +248 -0
  154. package/studio/server/watch.ts +1 -1
  155. package/studio/server/workspace/catalog.test.ts +17 -0
  156. package/studio/server/workspace/catalog.ts +43 -0
  157. package/studio/server/{state → workspace}/create.test.ts +1 -1
  158. package/studio/server/{state → workspace}/create.ts +1 -1
  159. package/studio/server/{state → workspace}/git.ts +1 -1
  160. package/studio/server/workspace/updates.ts +83 -0
  161. package/studio/server/workspace-state.ts +1 -1
  162. package/studio/shared/contracts/README.md +16 -0
  163. package/studio/shared/contracts/agent.ts +270 -0
  164. package/studio/shared/contracts/runtime.ts +50 -0
  165. package/studio/shared/contracts/schema.ts +462 -0
  166. package/studio/shared/contracts/surface.test.ts +319 -0
  167. package/studio/shared/contracts/workspace.ts +274 -0
  168. package/studio/shared/layout.test.ts +116 -0
  169. package/studio/shared/schema/identity.test.ts +58 -0
  170. package/studio/shared/schema/identity.ts +82 -0
  171. package/studio/shared/types.ts +11 -1099
  172. package/studio/tsconfig.json +1 -1
  173. package/viewer/dist/main.js +35 -35
  174. package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
  175. package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
  176. package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
  177. package/studio/server/state/catalog.ts +0 -117
  178. package/studio/server/state/instance.ts +0 -280
  179. package/studio/server/state/updates.ts +0 -63
  180. package/studio/server/state/views.ts +0 -535
@@ -1,1102 +1,14 @@
1
1
  /**
2
- * shared/types.ts the ONE contract shared by the Bun server and the React
3
- * client. Shapes under "DSL Schema IR" retain the legacy `D.$.ir` projection
4
- * while carrying the richer canonical DomainSchema V1 coordinates when they
5
- * are available:
6
- * ir = { version, domain, types, interfaces, classes, imports, functions, views? }
7
- * class = { type:'node'|'edge', name, implements?, endpoints?(edge), properties, methods }
8
- * interface = { type:'interface', name, extends?, properties, methods }
9
- * method = { name, params:{name->JsonSchema}, returns:JsonSchema, static, inheritance }
10
- * importsByKey = { 'origin:kind.Name' -> exact imported definition }
11
- * imports = unambiguous legacy aliases by short name
12
- * Everything under "Studio overlay/state" is the studio's own augmentation.
2
+ * Compatibility facade for the contracts shared by Studio's Bun server and
3
+ * React client.
4
+ *
5
+ * Semantic ownership lives in `contracts/` and `schema/identity.ts`. Existing
6
+ * `@shared/types` consumers intentionally keep the same public surface while
7
+ * new code may import its owning contract directly.
13
8
  */
14
9
 
15
- // ───────────────────────────── DSL Schema IR ─────────────────────────────
16
-
17
- export interface JsonSchema {
18
- type?: string | string[]
19
- enum?: (string | number | boolean | null)[]
20
- properties?: Record<string, JsonSchema>
21
- required?: string[]
22
- items?: JsonSchema
23
- additionalProperties?: boolean
24
- minimum?: number
25
- maximum?: number
26
- format?: string
27
- description?: string
28
- $nodeRef?: unknown
29
- $dataRef?: unknown
30
- [k: string]: unknown
31
- }
32
-
33
- export type MethodInheritance = 'default' | 'abstract' | 'sealed'
34
-
35
- /** Exact structural coordinate embedded in a canonical DomainSchema V1 root. */
36
- export interface IrSchemaRef {
37
- origin: string
38
- kind: 'type' | 'interface' | 'class' | 'function' | 'policy' | 'view' | 'core'
39
- name: string
40
- }
41
-
42
- /** Canonical DSL Key for a schema member: `origin:kind.name`. */
43
- export type IrSchemaKey = `${string}:${IrSchemaRef['kind']}.${string}`
44
-
45
- export type IrDefinitionRef = Omit<IrSchemaRef, 'kind'> & {
46
- kind: 'class' | 'interface'
47
- }
48
-
49
- export type IrDefinitionKey = `${string}:${IrDefinitionRef['kind']}.${string}`
50
-
51
- export type IrCallableAuth = 'anonymous' | 'authenticated' | 'authorized'
52
-
53
- export type IrCallableOutput =
54
- | { mode: 'value'; schema: JsonSchema }
55
- | { mode: 'stream'; item: JsonSchema }
56
- | { mode: 'binary' }
57
-
58
- export interface IrMethod {
59
- name: string
60
- /** Canonical callable input. Legacy projections expose only `params`. */
61
- input?: JsonSchema
62
- params: Record<string, JsonSchema>
63
- /** Names required by canonical `input.required`; absent on legacy Methods. */
64
- requiredParams?: string[]
65
- /** Canonical discriminated output. Legacy projections expose only `returns`. */
66
- output?: IrCallableOutput
67
- returns: JsonSchema
68
- static: boolean
69
- inheritance: MethodInheritance
70
- description?: string
71
- auth?: IrCallableAuth
72
- policy?: unknown
73
- }
74
-
75
- /** Standalone Domain Function projected into the Studio's callable vocabulary. */
76
- export interface IrFunction {
77
- name: string
78
- input: JsonSchema
79
- params: Record<string, JsonSchema>
80
- /** Names required by canonical `input.required`. */
81
- requiredParams?: string[]
82
- output: IrCallableOutput
83
- returns: JsonSchema
84
- /** Standalone Functions have no receiver; these legacy-compatible fields let
85
- * existing callable renderers consume them alongside static Methods. */
86
- static: true
87
- inheritance: 'default'
88
- description?: string
89
- auth?: IrCallableAuth
90
- policy?: unknown
91
- }
92
-
93
- export interface IrInterface {
94
- type: 'interface'
95
- name: string
96
- /** Canonical declaration owner/family; absent on legacy projections. */
97
- origin?: string
98
- family?: 'node' | 'edge' | 'both'
99
- ref?: IrSchemaRef
100
- extends?: string[]
101
- extendsRefs?: IrSchemaRef[]
102
- properties: Record<string, JsonSchema>
103
- /** Canonical `properties.required`; absence, unlike null, encodes optionality. */
104
- required?: string[]
105
- methods: Record<string, IrMethod>
106
- endpoints?: IrEndpoint[]
107
- orientation?: 'directed' | 'undirected'
108
- constraints?: { noSelf?: true; acyclic?: true }
109
- description?: string
110
- propertyMetadata?: Record<string, unknown>
111
- /** Canonical data declaration; `mediaType` is required and extensions stay lossless. */
112
- data?: { mediaType: string; [key: string]: unknown }
113
- }
114
-
115
- export interface IrEndpoint {
116
- name: string
117
- types: string[]
118
- /** Exact accepted Definition coordinates. `types` remains for existing UI consumers. */
119
- refs?: IrSchemaRef[]
120
- /** declared multiplicity for this end; max:null = unbounded ("many"). Absent ⇒ unconstrained. */
121
- cardinality?: { min: number; max: number | null }
122
- }
123
-
124
- export interface IrClass {
125
- type: 'node' | 'edge'
126
- name: string
127
- /** Canonical declaration owner/ref; absent on legacy projections. */
128
- origin?: string
129
- ref?: IrSchemaRef
130
- implements?: string[]
131
- implementsRefs?: IrSchemaRef[]
132
- /** edges only: the two (source,target) endpoints with role names + allowed types */
133
- endpoints?: IrEndpoint[]
134
- orientation?: 'directed' | 'undirected'
135
- constraints?: { noSelf?: true; acyclic?: true }
136
- properties: Record<string, JsonSchema>
137
- /** Canonical `properties.required`; absence, unlike null, encodes optionality. */
138
- required?: string[]
139
- methods: Record<string, IrMethod>
140
- /** class-level icon: raw (lucide-style) SVG markup, `stroke="currentColor"` */
141
- icon?: string
142
- description?: string
143
- propertyMetadata?: Record<string, unknown>
144
- /** Canonical data declaration; `mediaType` is required and extensions stay lossless. */
145
- data?: { mediaType: string; [key: string]: unknown }
146
- policies?: Record<string, IrSchemaRef>
147
- }
148
-
149
- export interface IrImportDescriptor {
150
- origin: string
151
- definition: 'interface' | 'class'
152
- ref?: IrDefinitionRef
153
- /** Canonical qualified identity; absent on legacy import descriptors. */
154
- key?: IrDefinitionKey
155
- }
156
-
157
- export type IrViewTarget = { kind: 'domain' } | { kind: 'definition'; definitions: IrSchemaRef[] }
158
-
159
- export interface IrView {
160
- name: string
161
- target: IrViewTarget
162
- auth: 'required' | 'optional' | 'public'
163
- description?: string
164
- }
165
-
166
- export interface SchemaIR {
167
- version: string
168
- domain: string
169
- /** Canonical document format; absent on legacy projections. */
170
- format?: 'astrale.dsl'
171
- types: Record<string, JsonSchema>
172
- interfaces: Record<string, IrInterface>
173
- classes: Record<string, IrClass>
174
- imports: Record<string, IrImportDescriptor>
175
- /**
176
- * Canonical authoritative import index, keyed by `origin:kind.name`.
177
- * `imports` remains the unambiguous short-name compatibility index.
178
- */
179
- importsByKey?: Record<IrDefinitionKey, IrImportDescriptor>
180
- /** Exact imported Interface bodies under the same collision-free identity. */
181
- importedInterfacesByKey?: Record<IrDefinitionKey, IrInterface>
182
- /** Canonical V1 members absent from the legacy serializer projection. */
183
- functions: Record<string, IrFunction>
184
- views?: Record<string, IrView>
185
- policies?: Record<string, unknown>
186
- dependencies?: Array<{ origin: string; revision: string }>
187
- /** Exact canonical genesis declaration; absent on legacy projections. */
188
- core?: unknown
189
- }
190
-
191
- // ─────────────────────────── Studio schema overlay ───────────────────────────
192
-
193
- export interface HandlerLink {
194
- owner: string
195
- ownerKind: 'class' | 'interface' | 'function'
196
- method: string
197
- static: boolean
198
- /** the legacy runtime registry or current implementation.ts wiring site */
199
- wiringFile?: string
200
- wiringLine?: number
201
- /** the resolved handler file (followed from the `execute` import) */
202
- handlerFile?: string
203
- handlerLine?: number
204
- /** kernel ops detected in the handler (::update, ::link, createNode, …) */
205
- kernelCalls?: string[]
206
- /** declared auth policy on the runtime config; absent ⇒ defaults to 'required'. */
207
- auth?: 'public' | 'optional' | 'required'
208
- /** Canonical V1 callable auth, when the handler comes from implementation.ts. */
209
- callableAuth?: IrCallableAuth
210
- /** authorize hook shape: 'absent' (none), 'noop' (allow-all), 'custom' (real check). */
211
- authorize?: 'absent' | 'noop' | 'custom'
212
- /** raw source of the authorize hook (for the hover preview). */
213
- authorizeSnippet?: string
214
- /** false ⇒ a todo()/NotImplemented stub → "contract-only" badge */
215
- implemented: boolean
216
- /** true ⇒ resolver could not link a file → "unlinked" badge */
217
- unlinked?: boolean
218
- }
219
-
220
- export interface SourceSpan {
221
- file: string
222
- startLine: number
223
- endLine: number
224
- doc?: string
225
- }
226
-
227
- export interface SchemaAnnotation {
228
- /** anchor ref key, e.g. 'class.Monitor.property.status' */
229
- target: string
230
- severity: 'warn' | 'info'
231
- code: 'COMPILE_ERROR' | 'EDGE_PROP_TYPE_MISSING'
232
- message: string
233
- }
234
-
235
- export interface CrossDomainImport {
236
- name: string
237
- origin: string
238
- definition: 'interface' | 'class'
239
- }
240
-
241
- export interface SchemaOverlay {
242
- origin: string
243
- /** defineDomain({ requires }) — runtime domain dependencies */
244
- requires: string[]
245
- /** non-kernel ir.imports → true cross-domain imports */
246
- crossDomainImports: CrossDomainImport[]
247
- /** kernel-origin ir.imports → mixin interfaces (collapsed chip) */
248
- mixins: CrossDomainImport[]
249
- postInstall?: string
250
- handlerLinks: HandlerLink[]
251
- /** keyed by anchor ref (class.X / class.X.property.y / class.X.method.m / edge.e / interface.I…) */
252
- sourceSpans: Record<string, SourceSpan>
253
- annotations: SchemaAnnotation[]
254
- }
255
-
256
- export interface BundleError {
257
- message: string
258
- file?: string
259
- }
260
-
261
- export interface StudioSchemaBundle {
262
- domainId: string
263
- schemaHash: string
264
- extractedBy: 'runtime-bun' | 'static-tsmorph-fallback'
265
- depsInstalled: boolean
266
- ir: SchemaIR | null
267
- /**
268
- * Exact canonical DomainSchema V1 root emitted by the domain. This is kept
269
- * separate from the render-oriented IR so drift hashes the same root the
270
- * Kernel installs. Absent for legacy `D.$.ir` domains.
271
- */
272
- schemaRoot?: unknown
273
- overlay: SchemaOverlay
274
- /**
275
- * Unambiguous short-name aliases for imported Interface bodies, retained for
276
- * legacy renderers. Canonical consumers use `ir.importedInterfacesByKey`, whose
277
- * `origin:interface.Name` keys cannot collide. Empty when deps aren't installed.
278
- */
279
- importedInterfaces?: Record<string, IrInterface>
280
- /** present when the runtime import failed to compile (render state, not a crash) */
281
- error?: BundleError | null
282
- extractedAt: string
283
- }
284
-
285
- // ─────────────────────────── Domain anatomy (non-schema) ───────────────────────────
286
-
287
- export interface DomainOverview {
288
- origin: string
289
- /** Active SDK composition entry; `domain.ts` is retained for legacy projects. */
290
- compositionFile?: 'implementation.ts' | 'domain.ts'
291
- adapter: 'astrale' | 'cloudflare' | 'unknown'
292
- prodTarget?: string
293
- devSecrets?: string
294
- postInstall?: string
295
- requires: string[]
296
- packageName?: string
297
- packageVersion?: string
298
- astraleDeps: Record<string, string>
299
- schemaDir: string
300
- client?: string
301
- }
302
-
303
- export interface ViewInfo {
304
- slug: string
305
- kind: 'inline-html' | 'spa' | 'unknown'
306
- auth?: string
307
- mount?: string
308
- url?: string
309
- /** the class(es) this view binds to via `viewFor: selfOf(Class)` (DSL allows an array);
310
- * absent ⇒ unbound/global */
311
- viewFor?: string | string[]
312
- file?: string
313
- description?: string
314
- }
315
-
316
- /** One node that can be supplied as a targeted view's `targetNodeId`. */
317
- export interface ViewTargetCandidate {
318
- id: string
319
- ref: string
320
- className: string
321
- classOrigin: string
322
- label: string
323
- description?: string
324
- status?: string
325
- }
326
-
327
- /** Small durable snapshot retained when a previously selected node disappears. */
328
- export interface RememberedViewTarget {
329
- id: string
330
- className: string
331
- classOrigin: string
332
- label: string
333
- }
334
-
335
- export interface ViewTargetResult {
336
- status: 'available' | 'unavailable'
337
- items: ViewTargetCandidate[]
338
- selected: ViewTargetCandidate | null
339
- stale: RememberedViewTarget | null
340
- truncated: boolean
341
- reason?: string
342
- }
343
-
344
- /** Full launch context shown before Studio asks `astrale view` to resolve and open the View. */
345
- export interface ViewRuntime {
346
- slug: string
347
- instance: string | null
348
- targetRequired: boolean
349
- targets: ViewTargetResult
350
- }
351
-
352
- export type ViewSessionResult =
353
- | {
354
- status: 'ready'
355
- sessionId: string
356
- pageUrl: string
357
- viewUrl: string
358
- target: ViewTargetCandidate | null
359
- }
360
- | { status: 'unavailable'; reason: string }
361
-
362
- export interface ClientFeature {
363
- name: string
364
- files: string[]
365
- }
366
-
367
- export interface ClientTree {
368
- shell: string[]
369
- features: ClientFeature[]
370
- routes: Record<string, string>
371
- present: boolean
372
- }
373
-
374
- export interface EnvField {
375
- name: string
376
- optional: boolean
377
- doc?: string
378
- secret?: boolean
379
- }
380
-
381
- export type EnvName = 'dev' | 'prod'
382
-
383
- /** One env var in the editor: the env.ts contract side (declared/optional/doc)
384
- * merged with the `.env.<env>` file side (value). A row may be declared-only
385
- * (in env.ts, not yet in the file), set, or an orphan (in the file, not env.ts). */
386
- export interface EnvVarRow {
387
- name: string
388
- /** current value from `.env.<env>` ('' when unset or empty) */
389
- value: string
390
- /** declared as a fillable (non-binding) field in env.ts's Env interface */
391
- declared: boolean
392
- /** env.ts marks it optional (`?`). Only required (!optional) + empty raises the signal. */
393
- optional: boolean
394
- /** JSDoc on the env.ts field — the inline hint */
395
- doc?: string
396
- }
397
-
398
- /** The editable env for one env name (dev|prod): the `.env.<env>` file reconciled
399
- * against env.ts. The GUI is the read-only studio's one sanctioned writer of a
400
- * domain file (the explicit exception). */
401
- export interface EnvFileModel {
402
- env: EnvName
403
- /** the secrets file, relative to the domain root (e.g. '.env.dev') */
404
- file: string
405
- /** wired via `astrale.config.ts` (`secrets: '.env.<env>'`)? false ⇒ the file is used
406
- * by convention but the adapter isn't pointed at it (e.g. managed prod). */
407
- configured: boolean
408
- exists: boolean
409
- adapter: DomainOverview['adapter']
410
- rows: EnvVarRow[]
411
- /** declared && required && empty — the count the "needs values" signal shows */
412
- requiredMissing: number
413
- }
414
-
415
- export interface DomainAnatomy {
416
- overview: DomainOverview
417
- views: ViewInfo[]
418
- client: ClientTree
419
- env: EnvField[]
420
- depsContainer?: string
421
- /** shallow readdir of integrations/ top-level dir names — a hint, NOT a parse */
422
- detectedIntegrations: string[]
423
- }
424
-
425
- // ─────────────────────────── Instance / deploy ───────────────────────────
426
-
427
- /** A kernel instance the CLI knows about (a local bookmark or an admin-managed one). */
428
- export interface InstanceInfo {
429
- name: string
430
- url: string
431
- active: boolean
432
- kind: 'bookmark' | 'managed'
433
- }
434
-
435
- /** Global (NOT per-domain) — the CLI's instances + which is active. Source of truth: `astrale instance list`. */
436
- export interface InstancesState {
437
- active: string | null
438
- instances: InstanceInfo[]
439
- }
440
-
441
- /** What the studio recorded the last time IT ran a deploy for this domain. */
442
- export interface DeployRecord {
443
- at: string
444
- schemaHash: string
445
- ok: boolean
446
- url?: string
447
- }
448
-
449
- /** Per-domain deploy/install state (the active instance is global — see InstancesState). */
450
- export interface InstanceStatus {
451
- /** the domain's configured deploy target (astrale.config.ts prod.instance) */
452
- deployTarget: string | null
453
- /** has a `prod` script → deployable via `pnpm prod` */
454
- deployable: boolean
455
- /** GROUND TRUTH — queried from `astrale introspect <origin> --bundle`, not local state.
456
- * 'unknown' = the instance couldn't be reached/queried (no target, not authed, offline). */
457
- install: 'installed' | 'not-installed' | 'unknown'
458
- /** local schema vs the schema actually INSTALLED on the instance (ground truth) */
459
- drift: 'in-sync' | 'drifted' | 'unknown'
460
- localHash: string | null
461
- /** hash of the schema installed on the instance (when reachable + installed) */
462
- installedHash: string | null
463
- /** the studio's own last deploy — supplementary (service URL / when), not the source of truth */
464
- lastDeploy: DeployRecord | null
465
- }
466
-
467
- export interface DeployResult {
468
- ok: boolean
469
- url: string | null
470
- output: string
471
- }
472
-
473
- // ─────────────────────────── Comments / open-questions ───────────────────────────
474
-
475
- export type ThreadRole = 'user' | 'author'
476
- export type ThreadEntryType = 'text' | 'choice'
477
-
478
- export interface ThreadEntry {
479
- id: string
480
- role: ThreadRole
481
- type: ThreadEntryType
482
- text: string
483
- options?: string[]
484
- answer?: string | null
485
- }
486
-
487
- export type AnchorKind = 'schema' | 'section' | 'file' | 'free'
488
-
489
- export interface AnchorRef {
490
- ref: string
491
- kind: AnchorKind
492
- file?: string
493
- startLine?: number
494
- endLine?: number
495
- label?: string
496
- /** Flow-canvas coordinates for section-level canvas comments. */
497
- x?: number
498
- y?: number
499
- }
500
-
501
- export interface Comment {
502
- id: string
503
- /** annotate-compatible: array of string excerpts */
504
- anchors: string[]
505
- /** studio-only, index-aligned to `anchors` */
506
- anchorRefs: AnchorRef[]
507
- status: 'open' | 'closed'
508
- closeNote?: string
509
- thread: ThreadEntry[]
510
- createdAt: string
511
- /** derived: a thread whose first entry is role:'author' is a question */
512
- kind: 'comment' | 'question'
513
- /** set when the anchor ref no longer resolves against the current schema */
514
- orphaned?: boolean
515
- }
516
-
517
- export interface CommentStore {
518
- schemaVersion: string
519
- comments: Comment[]
520
- }
521
-
522
- export interface MergeResult {
523
- merged: number
524
- closed: number
525
- unknownIds: string[]
526
- schemaMismatch: boolean
527
- pastedSchemaVersion?: string
528
- }
529
-
530
- // ─────────────────────────── Change tracking ───────────────────────────
531
-
532
- export type SchemaChangeKind =
533
- | 'schema-metadata-changed'
534
- | 'type-added'
535
- | 'type-removed'
536
- | 'type-changed'
537
- | 'import-added'
538
- | 'import-removed'
539
- | 'import-changed'
540
- | 'class-added'
541
- | 'class-removed'
542
- | 'class-contract-changed'
543
- | 'interface-added'
544
- | 'interface-removed'
545
- | 'interface-contract-changed'
546
- | 'edge-added'
547
- | 'edge-removed'
548
- | 'edge-contract-changed'
549
- | 'definition-metadata-changed'
550
- | 'prop-added'
551
- | 'prop-removed'
552
- | 'prop-type-changed'
553
- | 'prop-schema-changed'
554
- | 'prop-required-changed'
555
- | 'method-added'
556
- | 'method-removed'
557
- | 'method-signature-changed'
558
- | 'method-metadata-changed'
559
- | 'function-added'
560
- | 'function-removed'
561
- | 'function-signature-changed'
562
- | 'function-metadata-changed'
563
- | 'view-added'
564
- | 'view-removed'
565
- | 'view-changed'
566
- | 'view-metadata-changed'
567
- | 'policy-added'
568
- | 'policy-removed'
569
- | 'policy-changed'
570
- | 'dependency-added'
571
- | 'dependency-removed'
572
- | 'dependency-changed'
573
- | 'core-changed'
574
-
575
- export interface SchemaChange {
576
- kind: SchemaChangeKind
577
- target: string
578
- detail?: string
579
- breaking: boolean
580
- }
581
-
582
- export interface FileChange {
583
- file: string
584
- status: 'added' | 'modified' | 'removed'
585
- }
586
-
587
- export interface ChangeSet {
588
- source: 'baseline' | 'git'
589
- hasGit: boolean
590
- hasBaseline: boolean
591
- schemaChanges: SchemaChange[]
592
- fileChanges: FileChange[]
593
- schemaDiffText?: string
594
- classification: 'none' | 'additive' | 'breaking'
595
- baselineCapturedAt?: string
596
- }
597
-
598
- // ─────────────────────────── Core (genesis) data ───────────────────────────
599
- // A domain's `core` is its baked-in genesis graph. Canonical V1 stores it in the
600
- // DomainSchema; legacy projects may still expose `defineCore(...)` separately.
601
- // Read-only here — the studio renders it and lets you comment to request changes.
602
-
603
- /** One materialized node instance in a domain's core graph. */
604
- export interface StudioCoreNode {
605
- /** canonical CoreRef identity, e.g. `/:big-shop.example.dev:core.acme` */
606
- path: string
607
- /** the IR class this node instantiates (keys into StudioSchemaBundle.ir.classes) */
608
- className: string
609
- /** the node's property values, keyed by (possibly owner-qualified) property name */
610
- data: Record<string, unknown>
611
- /** parent node's `path`, when nested under another node (absent for roots) */
612
- parent?: string
613
- }
614
-
615
- /** One materialized edge instance wiring two core nodes. */
616
- export interface StudioCoreEdge {
617
- /** source Core path, owning Domain path, or a legacy meta-node endpoint */
618
- from: string
619
- /** target Core path, owning Domain path, or a legacy meta-node endpoint */
620
- to: string
621
- /** the IR edge class name (keys into StudioSchemaBundle.ir.classes, type:'edge') */
622
- edgeName: string
623
- /** edge property values, when the edge class carries data */
624
- data?: Record<string, unknown>
625
- }
626
-
627
- /** A domain's core data: the concrete genesis node/edge instance graph. */
628
- export interface StudioCore {
629
- /** the domain origin this core graph belongs to (mirrors SchemaIR.domain) */
630
- domain: string
631
- nodes: StudioCoreNode[]
632
- edges: StudioCoreEdge[]
633
- /** set when extraction failed; null when extraction succeeded (including "no core defined") */
634
- error?: { message: string } | null
635
- extractedAt: string
636
- }
637
-
638
- // ─────────────────────────── Context ───────────────────────────
639
-
640
- export interface ContextItem {
641
- id: string
642
- bucket: 'user' | 'auto'
643
- title: string
644
- body: string
645
- source?: string
646
- updatedAt: string
647
- /** auto items: included in the copy payload only when true */
648
- includeInHandoff?: boolean
649
- freshness?: string
650
- }
651
-
652
- export interface ContextStore {
653
- user: ContextItem[]
654
- auto: ContextItem[]
655
- }
656
-
657
- /** A document the user drops in as context for the AI agent. */
658
- export interface DocMeta {
659
- id: string
660
- name: string
661
- type: string
662
- size: number
663
- addedAt: string
664
- updatedAt?: string
665
- /** relative path under the dotted folder (server-side) */
666
- stored: string
667
- }
668
-
669
- // ─────────────────────────── Integrations ───────────────────────────
670
-
671
- export interface Integration {
672
- id: string
673
- name: string
674
- kind: string
675
- status: 'planned' | 'active' | 'deprecated' | string
676
- notes?: string
677
- }
678
-
679
- export interface IntegrationsState {
680
- integrations: Integration[]
681
- detectedSubfolders: string[]
682
- }
683
-
684
- /** A domain in the catalog — local to this workspace, a faked external service, or the kernel. */
685
- export interface DomainCatalogEntry {
686
- origin: string
687
- name: string
688
- kind: 'kernel' | 'local' | 'external'
689
- description: string
690
- /** raw lucide-style SVG icon (stroke="currentColor") */
691
- icon: string
692
- /** kernel is always present + required */
693
- required?: boolean
694
- }
695
-
696
- // ─────────────────────────── Domain summary / workspace ───────────────────────────
697
-
698
- export interface DomainSummary {
699
- id: string
700
- origin: string
701
- path: string
702
- schemaDir: string
703
- depsInstalled: boolean
704
- hasGit: boolean
705
- configFile: string
706
- }
707
-
708
- // ─────────────────────────── Copy payload ───────────────────────────
709
-
710
- export interface CopyPayload {
711
- markdown: string
712
- openComments: number
713
- }
714
-
715
- // ─────────────────────────── Agent loop (live, harness-agnostic) ───────────────────────────
716
-
717
- /** Kinds of activity the studio surfaces while a local agent runs a turn. */
718
- export type AgentEventKind =
719
- | 'status' // lifecycle / human note ("session started", "merged 2 replies")
720
- | 'thinking' // assistant reasoning (summarized)
721
- | 'message' // assistant prose addressed to the user
722
- | 'tool' // a tool invocation (edit, bash, read, …)
723
- | 'reply' // the agent posted a reply to a specific thread (via the bridge)
724
- | 'error'
725
-
726
- export interface AgentEvent {
727
- id: string
728
- ts: string
729
- kind: AgentEventKind
730
- text: string
731
- /** for kind:'tool' — the tool name (Edit/Write/Bash/Read…) */
732
- tool?: string
733
- /** for kind:'tool' — a compact target (file path, command, pattern) */
734
- target?: string
735
- /** for kind:'reply' — the comment id the reply landed on */
736
- commentId?: string
737
- }
738
-
739
- export const AGENT_EFFORT_LEVELS = [
740
- 'minimal',
741
- 'low',
742
- 'medium',
743
- 'high',
744
- 'xhigh',
745
- 'max',
746
- 'ultracode',
747
- ] as const
748
- export type AgentEffort = (typeof AGENT_EFFORT_LEVELS)[number]
749
- export const AGENT_ACCESS_LEVELS = ['workspace', 'full'] as const
750
- export type AgentAccess = (typeof AGENT_ACCESS_LEVELS)[number]
751
-
752
- export interface AgentPromptSnapshot {
753
- createdAt: string
754
- /** appended to the harness default system prompt */
755
- systemPrompt: string
756
- /** piped to the harness on stdin */
757
- turnPrompt: string
758
- /** true when this turn started a new harness conversation */
759
- firstTurn: boolean
760
- /** true when this turn used a prior harness session id */
761
- resumed: boolean
762
- sessionId?: string
763
- /** Explicit Studio model override used for this turn; absent means harness-native default. */
764
- model?: string
765
- /** Harness-native reasoning effort used for this turn. */
766
- effort?: AgentEffort
767
- /** Filesystem/network authority granted to the harness for this turn. */
768
- access?: AgentAccess
769
- /** generated MCP bridge tools exposed to the harness for live write-back */
770
- mcpTools: string[]
771
- }
772
-
773
- export interface AgentSystemPromptInfo {
774
- bridge: boolean
775
- systemPrompt: string
776
- }
777
-
778
- export type AgentRunStatus =
779
- | 'queued'
780
- | 'running'
781
- | 'succeeded'
782
- | 'failed'
783
- | 'canceled'
784
- /** the studio process died mid-turn (restart/crash) — the spawned agent went with
785
- * it, but the CONVERSATION is preserved, so the next submit resumes it. */
786
- | 'interrupted'
787
-
788
- /** One agent turn for a domain: the live transcript + outcome. */
789
- export interface AgentRun {
790
- id: string
791
- domainId: string
792
- harness: string
793
- status: AgentRunStatus
794
- createdAt: string
795
- finishedAt?: string
796
- /** the harness session id (so the next turn resumes the same conversation) */
797
- sessionId?: string
798
- /** true ⇒ this turn resumed an existing conversation (vs. started a new one) */
799
- resumed?: boolean
800
- /** short human label of what this turn was asked to do */
801
- summary: string
802
- /** comment ids this turn was started to answer */
803
- targetCommentIds: string[]
804
- events: AgentEvent[]
805
- costUsd?: number
806
- numTurns?: number
807
- /** total token usage reported by the harness for this turn */
808
- tokens?: number
809
- error?: string
810
- /** how many threads the agent answered live via the bridge tools this turn */
811
- liveReplies?: number
812
- /** result of merging the agent's final machine-state reply block, if any */
813
- merge?: MergeResult
814
- /** exact prompt inputs sent to the harness for this turn */
815
- prompt?: AgentPromptSnapshot
816
- }
817
-
818
- /** The ongoing, resumable conversation for a domain and selected harness.
819
- * Survives studio restarts (persisted on disk). */
820
- export interface ConversationInfo {
821
- /** a resumable session exists → the next submit continues it (vs. starting fresh) */
822
- active: boolean
823
- /** successful turns recorded in the current conversation */
824
- turns: number
825
- /** which harness the conversation belongs to (resume only applies within it) */
826
- harness?: string
827
- }
828
-
829
- /** The agent's raw resumable session id, surfaced for manual view/edit in Settings. */
830
- export interface AgentSessionInfo {
831
- sessionId: string | null
832
- turns: number
833
- harness?: string
834
- }
835
-
836
- export interface HarnessCapabilities {
837
- effortLevels: readonly AgentEffort[]
838
- accessLevels: readonly AgentAccess[]
839
- /** Stable aliases advertised even when the harness has no catalog API. */
840
- modelOptions?: readonly HarnessModelOption[]
841
- ask: boolean
842
- loadout: boolean
843
- /** Custom model-gateway wire contract this harness can consume in Studio. */
844
- gateway: 'anthropic' | 'responses' | 'none'
845
- }
846
-
847
- /** Whether the selected agent harness is installed, invokable, and configurable. */
848
- export interface HarnessStatus {
849
- id: string
850
- label: string
851
- /** the binary/command probed (e.g. 'claude') */
852
- bin: string
853
- ok: boolean
854
- version?: string
855
- /** human message — install / PATH guidance when not ok */
856
- message: string
857
- /** known harnesses for the selector (locked to one for now) */
858
- options: { id: string; label: string }[]
859
- /** an environment/CLI override owns the selection, so the GUI cannot change it */
860
- locked: boolean
861
- source: 'environment' | 'domain' | 'default'
862
- capabilities: HarnessCapabilities
863
- }
864
-
865
- /** One MCP server the harness loaded, with its live connection status. */
866
- export interface McpServerInfo {
867
- name: string
868
- /** harness-reported status: 'connected' | 'needs-auth' | 'failed' | 'pending' | … */
869
- status: string
870
- }
871
-
872
- /** One skill, reconciled between what is installed on disk and what the harness
873
- * actually LOADED for this domain's cwd. `loaded:false` ⇒ installed but inactive
874
- * here (e.g. a disabled plugin or a cwd-scoped skill) — the key diagnostic. */
875
- export interface LoadoutSkill {
876
- /** the slash-command the harness invokes it by — e.g. 'astrale-domain' or 'vercel:nextjs' */
877
- command: string
878
- /** display name from SKILL.md frontmatter (falls back to `command`) */
879
- name: string
880
- description?: string
881
- /** where it lives on disk */
882
- source: 'project' | 'user' | 'plugin'
883
- /** the providing plugin, when source==='plugin' */
884
- plugin?: string
885
- /** present in the harness's loaded slash-commands for this cwd */
886
- loaded: boolean
887
- /** absolute path to the skill's SKILL.md (so the UI can show its content) */
888
- path?: string
889
- }
890
-
891
- /** What the harness ACTUALLY loaded for a domain's cwd — read from the `system/init`
892
- * event of a headless `claude` probe (the harness-authoritative source), then
893
- * reconciled against on-disk skills. The studio's read-only window into its agent. */
894
- export interface HarnessLoadout {
895
- /** the probe ran and returned an init event */
896
- ok: boolean
897
- /** reason when !ok (binary missing / probe timed out / no init event) */
898
- detail?: string
899
- /** Model the harness resolves before Studio applies its optional override. */
900
- nativeModel?: string
901
- model?: string
902
- /** Where the effective model came from. */
903
- modelSource?: 'studio' | 'config' | 'default' | 'runtime'
904
- /** Models the harness currently advertises for easy selection. */
905
- models?: HarnessModelOption[]
906
- permissionMode?: string
907
- /** how the harness is authed: 'none' | 'ANTHROPIC_API_KEY' | … */
908
- apiKeySource?: string
909
- /** the cwd the harness was probed in (the domain root) */
910
- cwd?: string
911
- /** built-in tool names loaded (Read, Edit, Bash, …) */
912
- tools: string[]
913
- mcpServers: McpServerInfo[]
914
- skills: LoadoutSkill[]
915
- /** subagent types available to the harness (incl. plugin-provided) */
916
- agents: string[]
917
- /** count of loaded slash-commands that are built-in/harness commands, not skills */
918
- builtinCommandCount: number
919
- /** epoch ms when probed */
920
- probedAt: number
921
- /** Claude exposes a live init event; Codex exposes configured/installed state. */
922
- source?: 'runtime' | 'configured'
923
- }
924
-
925
- export interface HarnessModelOption {
926
- /** Stable model slug passed to the harness, e.g. `gpt-5.6-sol`. */
927
- id: string
928
- /** Human-friendly catalog label. */
929
- label: string
930
- description?: string
931
- /** The harness catalog's built-in default when no config layer overrides it. */
932
- isDefault?: boolean
933
- }
934
-
935
- /** Domain-attributable agent spend — accumulated from this studio's own runs on
936
- * this domain (NOT machine-wide). Stored at `.domain-studio/usage.json`. */
937
- export interface DomainUsage {
938
- /** runs that reported usage (succeeded or not — a failed turn still costs) */
939
- runs: number
940
- /** cumulative tokens (input + output + cache) across those runs */
941
- tokens: number
942
- /** cumulative USD across those runs */
943
- costUsd: number
944
- lastRunAt?: string
945
- lastTokens?: number
946
- lastCostUsd?: number
947
- }
948
-
949
- /** Snapshot returned by GET /agent — drives the activity drawer. */
950
- export interface AgentRunSnapshot {
951
- harness: string
952
- available: boolean
953
- /** the active or most-recent run for this domain (null if none yet) */
954
- run: AgentRun | null
955
- /** the resumable conversation behind the runs (turns, whether one is live) */
956
- conversation: ConversationInfo
957
- }
958
-
959
- // ─────────────────────────── SSE events ───────────────────────────
960
-
961
- export type StudioEvent =
962
- | { type: 'schema-diff'; domainId: string; schemaHash: string }
963
- | { type: 'anatomy-diff'; domainId: string }
964
- | { type: 'comments'; domainId: string }
965
- | { type: 'compile-error'; domainId: string; message: string }
966
- | { type: 'resolving'; domainId: string }
967
- | { type: 'agent-run'; domainId: string; run: AgentRun }
968
- | { type: 'agent-event'; domainId: string; runId: string; event: AgentEvent }
969
- | { type: 'hello'; domains: string[] }
970
- | { type: 'workspace'; domains: string[] }
971
-
972
- // ─────────────────────────── Render helpers (client) ───────────────────────────
973
-
974
- // ─────────────────────────── Graph layout ───────────────────────────
975
-
976
- export interface NodePosition {
977
- x: number
978
- y: number
979
- /** persisted size — only expanded module containers carry one. */
980
- w?: number
981
- h?: number
982
- }
983
- export interface LayoutState {
984
- schemaHash?: string
985
- positions: Record<string, NodePosition>
986
- }
987
-
988
- /** Persisted per-domain canvas visibility — the manual hide-set, inherited-edge category toggle,
989
- * and materialized interfaces. Sibling of LayoutState: layout owns node POSITIONS, this owns
990
- * what's SHOWN. */
991
- export interface VisibilityState {
992
- /** refs hidden on the canvas: `class.X` | `edge.X` | `domain.<origin>` (interfaces use
993
- * `materializedInterfaces`, not this set — see below) */
994
- hidden: Record<string, true>
995
- showInheritedEdges: boolean
996
- /** Local interfaces MATERIALIZED as canvas NODES (default = badge). Keyed by BARE interface
997
- * name (e.g. `Fulfillable`) — a set distinct from `hidden`, so no ref namespace collision. */
998
- materializedInterfaces: Record<string, true>
999
- }
1000
-
1001
- export type TypeDescriptor =
1002
- | { kind: 'string' | 'number' | 'integer' | 'boolean' | 'null' | 'unknown'; optional: boolean }
1003
- | { kind: 'enum'; values: (string | number | boolean | null)[]; optional: boolean }
1004
- | { kind: 'array'; items: TypeDescriptor; optional: boolean }
1005
- | {
1006
- kind: 'object'
1007
- fields: Record<string, TypeDescriptor>
1008
- required: string[]
1009
- optional: boolean
1010
- }
1011
- | { kind: 'ref'; target: string; refKind: 'node' | 'data'; optional: boolean }
1012
-
1013
- // ─────────────────────────── Studio settings (power-user overrides) ───────────────────────────
1014
-
1015
- /** Per-domain overrides for values the studio otherwise hard-codes. Stored at
1016
- * `.domain-studio/settings.json`; missing keys fall back to defaults. */
1017
- export interface StudioSettings {
1018
- /** Harness-native reasoning effort (default 'high') */
1019
- agentEffort: AgentEffort
1020
- /** workspace = sandboxed edits; full = unrestricted local automation */
1021
- agentAccess: AgentAccess
1022
- /** Optional model override, independently remembered for each harness id. */
1023
- agentModels: Record<string, string>
1024
- /** folder under the domain root scanned for integrations (default 'integrations') */
1025
- integrationsDir: string
1026
- /** schema/core extraction subprocess timeout in ms (default 20000) */
1027
- introspectTimeoutMs: number
1028
- /** how often the per-domain instance status refreshes, ms (default 30000) */
1029
- instancePollMs: number
1030
- /** how often the studio re-checks for stale schema / updates, ms (default 600000) */
1031
- updatesPollMs: number
1032
- /** timeout when probing a live view URL from the instance, ms (default 8000) */
1033
- viewProbeTimeoutMs: number
1034
- }
1035
-
1036
- // ─────────────────── Harness model gateway (custom LLM endpoint) ───────────────────
1037
-
1038
- /**
1039
- * Point the agent harness (Claude Code) at a custom Anthropic-compatible model
1040
- * gateway — e.g. an Astrale `ai-gateway` model node — instead of its built-in
1041
- * auth. The values become env on the SPAWNED harness child only
1042
- * (ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN / ANTHROPIC_MODEL): the studio
1043
- * never writes them to your shell, your `~/.claude`, or a `claude` you run
1044
- * yourself outside the studio.
1045
- */
1046
- /**
1047
- * How the harness gets its bearer token for the gateway. Abstracted so the same
1048
- * gateway works whether the studio runs locally or embedded in the Astrale GUI:
1049
- * - `mint` — LOCAL: the studio mints a fresh, short-lived delegation token per
1050
- * run via `astrale token` (audience derived from the gateway URL).
1051
- * No secret is stored on disk; auth follows the active CLI identity.
1052
- * - `token` — MANUAL: a static bearer the user pastes (non-Astrale gateways, or
1053
- * an explicitly long-lived token).
1054
- * - `host` — EMBED: the embedding Astrale GUI supplies the token (via the shell)
1055
- * and owns mint / refresh / scope; the studio just relays it to the
1056
- * harness child. The forward-looking path for the iframe deployment.
1057
- */
1058
- export type HarnessGatewayAuth =
1059
- | { mode: 'mint'; instance?: string } // instance to mint on; omitted ⇒ the active one
1060
- | { mode: 'token'; token: string }
1061
- | { mode: 'host' }
1062
-
1063
- export interface HarnessGatewayConfig {
1064
- /** master switch — off ⇒ the harness uses its own default auth */
1065
- enabled: boolean
1066
- /** ANTHROPIC_BASE_URL — Claude Code POSTs to `${baseUrl}/v1/messages`. For an
1067
- * Astrale model node: `https://<gateway-host>/v1/models/<modelNodeId>`. */
1068
- baseUrl: string
1069
- /** ANTHROPIC_MODEL label (cosmetic — the gateway pins the real model by URL). */
1070
- model?: string
1071
- /** how the bearer token is obtained (see HarnessGatewayAuth) */
1072
- auth: HarnessGatewayAuth
1073
- }
1074
-
1075
- /** The layered harness-gateway config for a domain: its own per-domain override,
1076
- * the studio-wide global default, and which one actually takes effect. */
1077
- export interface HarnessGatewayState {
1078
- /** per-domain override (`.domain-studio/harness-gateway.json`); null ⇒ inherits global */
1079
- local: HarnessGatewayConfig | null
1080
- /** studio-wide default — applies to every domain that has no local override */
1081
- global: HarnessGatewayConfig | null
1082
- /** the config that actually takes effect (an enabled local ∨ an enabled global), else null */
1083
- effective: HarnessGatewayConfig | null
1084
- /** which layer `effective` came from */
1085
- source: 'domain' | 'global' | 'none'
1086
- }
1087
-
1088
- // ─────────────────────────── Update staleness (the header "Update" badge) ───────────────────────────
1089
-
1090
- /** The Astrale CLI's own staleness report — `astrale update --check --json`, run
1091
- * in the domain root. The CLI owns the detection; the studio only renders it.
1092
- * Skills are intentionally absent: they ride along with `astrale update`, so a
1093
- * stale CLI or SDK dep is the only thing worth surfacing. */
1094
- export interface StaleReport {
1095
- stale: boolean
1096
- cli: { stale: boolean; managed: boolean; current?: string; latest?: string; channel?: string }
1097
- sdk: {
1098
- stale: boolean
1099
- inProject: boolean
1100
- outdated: { pkg: string; current: string; latest: string }[]
1101
- }
1102
- }
10
+ export * from './schema/identity'
11
+ export * from './contracts/schema'
12
+ export * from './contracts/workspace'
13
+ export * from './contracts/agent'
14
+ export * from './contracts/runtime'