@astrale-os/cli 0.4.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.check-workspace.cjs +40 -0
- package/README.md +151 -0
- package/dist/astrale.js +59749 -0
- package/package.json +90 -0
- package/src/command.ts +40 -0
- package/src/commands/__tests__/admin-instance.test.ts +73 -0
- package/src/commands/__tests__/auth-login.test.ts +178 -0
- package/src/commands/__tests__/auth-token.test.ts +223 -0
- package/src/commands/__tests__/call.test.ts +72 -0
- package/src/commands/__tests__/domain-list.test.ts +74 -0
- package/src/commands/__tests__/help-contract.test.ts +136 -0
- package/src/commands/__tests__/install-identity-override.test.ts +65 -0
- package/src/commands/__tests__/instance-bookmark.test.ts +101 -0
- package/src/commands/__tests__/instance-create-hosts.test.ts +29 -0
- package/src/commands/__tests__/instance-list-rows.test.ts +63 -0
- package/src/commands/__tests__/logs.test.ts +117 -0
- package/src/commands/__tests__/ls.test.ts +25 -0
- package/src/commands/__tests__/setup-plan.test.ts +61 -0
- package/src/commands/admin/status.ts +61 -0
- package/src/commands/admin/use.ts +77 -0
- package/src/commands/auth/login.ts +82 -0
- package/src/commands/auth/logout.ts +50 -0
- package/src/commands/auth/status.ts +86 -0
- package/src/commands/auth/token.ts +162 -0
- package/src/commands/browser.ts +207 -0
- package/src/commands/call.ts +300 -0
- package/src/commands/describe.ts +182 -0
- package/src/commands/domain/install.ts +420 -0
- package/src/commands/domain/list.ts +154 -0
- package/src/commands/domain/publish.ts +155 -0
- package/src/commands/get.ts +60 -0
- package/src/commands/identity/create.ts +26 -0
- package/src/commands/identity/delete.ts +18 -0
- package/src/commands/identity/export.ts +66 -0
- package/src/commands/identity/import.ts +101 -0
- package/src/commands/identity/list.ts +56 -0
- package/src/commands/identity/register.ts +170 -0
- package/src/commands/identity/sync.ts +32 -0
- package/src/commands/identity/unsync.ts +24 -0
- package/src/commands/identity/use.ts +18 -0
- package/src/commands/identity/whoami.ts +34 -0
- package/src/commands/idp/add.ts +150 -0
- package/src/commands/idp/list.ts +57 -0
- package/src/commands/idp/refresh.ts +38 -0
- package/src/commands/idp/remove.ts +36 -0
- package/src/commands/idp/show.ts +29 -0
- package/src/commands/instance/active.ts +64 -0
- package/src/commands/instance/bookmark.ts +72 -0
- package/src/commands/instance/create.ts +69 -0
- package/src/commands/instance/delete.ts +72 -0
- package/src/commands/instance/forget.ts +26 -0
- package/src/commands/instance/list.ts +149 -0
- package/src/commands/instance/status.ts +42 -0
- package/src/commands/instance/use.ts +210 -0
- package/src/commands/logs.ts +347 -0
- package/src/commands/ls.ts +229 -0
- package/src/commands/query.ts +32 -0
- package/src/commands/setup.ts +54 -0
- package/src/commands/status.ts +60 -0
- package/src/commands/studio.ts +401 -0
- package/src/commands/token.ts +77 -0
- package/src/commands/update.ts +267 -0
- package/src/commands/use.ts +87 -0
- package/src/errors.ts +65 -0
- package/src/kernel/__tests__/auth.test.ts +77 -0
- package/src/kernel/__tests__/errors.test.ts +43 -0
- package/src/kernel/__tests__/remote-routing.test.ts +70 -0
- package/src/kernel/auth.ts +234 -0
- package/src/kernel/ca-fetch.ts +119 -0
- package/src/kernel/client.ts +191 -0
- package/src/kernel/errors.ts +280 -0
- package/src/kernel/expand.ts +217 -0
- package/src/kernel/index.ts +14 -0
- package/src/kernel/options.ts +22 -0
- package/src/kernel/remote-routing.ts +88 -0
- package/src/kernel/run.ts +63 -0
- package/src/kernel/types.ts +14 -0
- package/src/lib/__tests__/admin-target.test.ts +112 -0
- package/src/lib/__tests__/binary.test.ts +56 -0
- package/src/lib/__tests__/command-dx.test.ts +58 -0
- package/src/lib/__tests__/concurrency.test.ts +62 -0
- package/src/lib/__tests__/config.test.ts +53 -0
- package/src/lib/__tests__/design.test.ts +99 -0
- package/src/lib/__tests__/domain-identity.test.ts +60 -0
- package/src/lib/__tests__/format.test.ts +22 -0
- package/src/lib/__tests__/fs-atomic.test.ts +104 -0
- package/src/lib/__tests__/identity.test.ts +79 -0
- package/src/lib/__tests__/idp-session.driver.ts +53 -0
- package/src/lib/__tests__/idp-session.test.ts +357 -0
- package/src/lib/__tests__/idp.test.ts +385 -0
- package/src/lib/__tests__/instance-candidates.test.ts +73 -0
- package/src/lib/__tests__/instance-target.test.ts +183 -0
- package/src/lib/__tests__/instance.test.ts +136 -0
- package/src/lib/__tests__/keys.test.ts +129 -0
- package/src/lib/__tests__/local-status.test.ts +202 -0
- package/src/lib/__tests__/output.test.ts +150 -0
- package/src/lib/__tests__/panel.test.ts +40 -0
- package/src/lib/__tests__/port.test.ts +44 -0
- package/src/lib/__tests__/prompt.test.ts +25 -0
- package/src/lib/__tests__/sdk-deps.test.ts +68 -0
- package/src/lib/__tests__/self.test.ts +272 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +74 -0
- package/src/lib/__tests__/table.test.ts +53 -0
- package/src/lib/__tests__/update.test.ts +246 -0
- package/src/lib/__tests__/use-target.test.ts +56 -0
- package/src/lib/__tests__/validation.test.ts +34 -0
- package/src/lib/admin-domain.ts +25 -0
- package/src/lib/admin-instance.ts +26 -0
- package/src/lib/admin-target.ts +217 -0
- package/src/lib/binary.ts +131 -0
- package/src/lib/browser.ts +150 -0
- package/src/lib/command-dx.ts +161 -0
- package/src/lib/concurrency.ts +31 -0
- package/src/lib/config.ts +45 -0
- package/src/lib/domain-identity.ts +49 -0
- package/src/lib/env.ts +49 -0
- package/src/lib/format.ts +4 -0
- package/src/lib/fs-atomic.ts +126 -0
- package/src/lib/identity.ts +256 -0
- package/src/lib/idp-session.ts +134 -0
- package/src/lib/idp.ts +876 -0
- package/src/lib/instance-candidates.ts +49 -0
- package/src/lib/instance-target.ts +182 -0
- package/src/lib/instance.ts +395 -0
- package/src/lib/keys.ts +294 -0
- package/src/lib/local-status.ts +152 -0
- package/src/lib/log.ts +116 -0
- package/src/lib/login-flow.ts +164 -0
- package/src/lib/meta.ts +86 -0
- package/src/lib/output.ts +222 -0
- package/src/lib/panel.ts +61 -0
- package/src/lib/paths.ts +11 -0
- package/src/lib/port.ts +41 -0
- package/src/lib/proc.ts +82 -0
- package/src/lib/prompt.ts +136 -0
- package/src/lib/provision-instance.ts +170 -0
- package/src/lib/sdk-deps.ts +104 -0
- package/src/lib/self.ts +166 -0
- package/src/lib/skills.ts +171 -0
- package/src/lib/table.ts +62 -0
- package/src/lib/update.ts +315 -0
- package/src/lib/use-target.ts +24 -0
- package/src/lib/validation.ts +59 -0
- package/src/program.ts +200 -0
- package/src/registry.ts +59 -0
- package/src/setup/__tests__/util.test.ts +29 -0
- package/src/setup/engine.ts +83 -0
- package/src/setup/render.ts +109 -0
- package/src/setup/steps/admin.ts +78 -0
- package/src/setup/steps/agent-browser.ts +81 -0
- package/src/setup/steps/auth.ts +54 -0
- package/src/setup/steps/domain.ts +68 -0
- package/src/setup/steps/index.ts +18 -0
- package/src/setup/steps/instance.ts +119 -0
- package/src/setup/steps/skills-bridge.ts +70 -0
- package/src/setup/steps/skills.ts +59 -0
- package/src/setup/types.ts +61 -0
- package/src/setup/util.ts +34 -0
- package/src/test-utils.ts +18 -0
- package/studio/client/dist/assets/index-DOwzZAEK.css +1 -0
- package/studio/client/dist/assets/index-wtU0Zxhy.js +183 -0
- package/studio/client/dist/index.html +13 -0
- package/studio/package.json +62 -0
- package/studio/server/agent/ask.ts +68 -0
- package/studio/server/agent/bridge-mcp.ts +182 -0
- package/studio/server/agent/bridge.ts +188 -0
- package/studio/server/agent/claude.ts +666 -0
- package/studio/server/agent/mock.ts +186 -0
- package/studio/server/agent/prompt.ts +202 -0
- package/studio/server/agent/registry.ts +29 -0
- package/studio/server/agent/runner.ts +484 -0
- package/studio/server/agent/schema-map.ts +112 -0
- package/studio/server/agent/types.ts +120 -0
- package/studio/server/api.ts +574 -0
- package/studio/server/cache.ts +138 -0
- package/studio/server/detect.ts +81 -0
- package/studio/server/domain.ts +70 -0
- package/studio/server/index.ts +136 -0
- package/studio/server/introspect/anatomy-extras.ts +398 -0
- package/studio/server/introspect/anatomy.ts +108 -0
- package/studio/server/introspect/bundle.ts +57 -0
- package/studio/server/introspect/core-extractor.ts +119 -0
- package/studio/server/introspect/core.ts +44 -0
- package/studio/server/introspect/diff.ts +133 -0
- package/studio/server/introspect/extractor.ts +102 -0
- package/studio/server/introspect/hash.ts +21 -0
- package/studio/server/introspect/overlay-tsmorph.ts +874 -0
- package/studio/server/introspect/overlay.ts +57 -0
- package/studio/server/introspect/runtime.ts +99 -0
- package/studio/server/introspect/schema-refs.ts +46 -0
- package/studio/server/lifecycle.ts +38 -0
- package/studio/server/sse.ts +57 -0
- package/studio/server/state/baseline.ts +211 -0
- package/studio/server/state/catalog.ts +117 -0
- package/studio/server/state/comments.ts +321 -0
- package/studio/server/state/context.ts +167 -0
- package/studio/server/state/copy.ts +156 -0
- package/studio/server/state/create.ts +156 -0
- package/studio/server/state/documents.ts +70 -0
- package/studio/server/state/env.ts +161 -0
- package/studio/server/state/git.ts +75 -0
- package/studio/server/state/handoff.ts +55 -0
- package/studio/server/state/harness-gateway.ts +181 -0
- package/studio/server/state/harness-token.ts +0 -0
- package/studio/server/state/instance.ts +244 -0
- package/studio/server/state/integrations.ts +55 -0
- package/studio/server/state/layout.ts +55 -0
- package/studio/server/state/settings.ts +39 -0
- package/studio/server/state/store.ts +97 -0
- package/studio/server/state/updates.ts +63 -0
- package/studio/server/state/usage.ts +37 -0
- package/studio/server/state/views.ts +138 -0
- package/studio/server/state/visibility.ts +33 -0
- package/studio/server/watch.ts +81 -0
- package/studio/server/workspace-state.ts +26 -0
- package/studio/server/workspace-watch.ts +101 -0
- package/studio/shared/types.ts +873 -0
- package/studio/tsconfig.json +23 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,873 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shared/types.ts — the ONE contract shared by the Bun server and the React
|
|
3
|
+
* client. Shapes under "DSL Schema IR" mirror EXACTLY what `D.$.ir` /
|
|
4
|
+
* `serialize(schema)` emit (verified empirically against my-domain + evaluation):
|
|
5
|
+
* ir = { version, domain, types, interfaces, classes, imports }
|
|
6
|
+
* class = { type:'node'|'edge', name, implements?, endpoints?(edge), properties, methods }
|
|
7
|
+
* interface = { type:'interface', name, extends?, properties, methods }
|
|
8
|
+
* method = { name, params:{name->JsonSchema}, returns:JsonSchema, static, inheritance }
|
|
9
|
+
* imports = { name -> { origin, definition:'interface'|'class' } }
|
|
10
|
+
* Everything under "Studio overlay/state" is the studio's own augmentation.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ───────────────────────────── DSL Schema IR ─────────────────────────────
|
|
14
|
+
|
|
15
|
+
export interface JsonSchema {
|
|
16
|
+
type?: string | string[]
|
|
17
|
+
enum?: (string | number | boolean | null)[]
|
|
18
|
+
properties?: Record<string, JsonSchema>
|
|
19
|
+
required?: string[]
|
|
20
|
+
items?: JsonSchema
|
|
21
|
+
additionalProperties?: boolean
|
|
22
|
+
minimum?: number
|
|
23
|
+
maximum?: number
|
|
24
|
+
format?: string
|
|
25
|
+
description?: string
|
|
26
|
+
$nodeRef?: unknown
|
|
27
|
+
$dataRef?: unknown
|
|
28
|
+
[k: string]: unknown
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type MethodInheritance = 'default' | 'abstract' | 'sealed'
|
|
32
|
+
|
|
33
|
+
export interface IrMethod {
|
|
34
|
+
name: string
|
|
35
|
+
params: Record<string, JsonSchema>
|
|
36
|
+
returns: JsonSchema
|
|
37
|
+
static: boolean
|
|
38
|
+
inheritance: MethodInheritance
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface IrInterface {
|
|
42
|
+
type: 'interface'
|
|
43
|
+
name: string
|
|
44
|
+
extends?: string[]
|
|
45
|
+
properties: Record<string, JsonSchema>
|
|
46
|
+
methods: Record<string, IrMethod>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface IrEndpoint {
|
|
50
|
+
name: string
|
|
51
|
+
types: string[]
|
|
52
|
+
/** declared multiplicity for this end; max:null = unbounded ("many"). Absent ⇒ unconstrained. */
|
|
53
|
+
cardinality?: { min: number; max: number | null }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface IrClass {
|
|
57
|
+
type: 'node' | 'edge'
|
|
58
|
+
name: string
|
|
59
|
+
implements?: string[]
|
|
60
|
+
/** edges only: the two (source,target) endpoints with role names + allowed types */
|
|
61
|
+
endpoints?: IrEndpoint[]
|
|
62
|
+
properties: Record<string, JsonSchema>
|
|
63
|
+
methods: Record<string, IrMethod>
|
|
64
|
+
/** class-level icon: raw (lucide-style) SVG markup, `stroke="currentColor"` */
|
|
65
|
+
icon?: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface IrImportDescriptor {
|
|
69
|
+
origin: string
|
|
70
|
+
definition: 'interface' | 'class'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface SchemaIR {
|
|
74
|
+
version: string
|
|
75
|
+
domain: string
|
|
76
|
+
types: Record<string, JsonSchema>
|
|
77
|
+
interfaces: Record<string, IrInterface>
|
|
78
|
+
classes: Record<string, IrClass>
|
|
79
|
+
imports: Record<string, IrImportDescriptor>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ─────────────────────────── Studio schema overlay ───────────────────────────
|
|
83
|
+
|
|
84
|
+
export interface HandlerLink {
|
|
85
|
+
owner: string
|
|
86
|
+
ownerKind: 'class' | 'interface'
|
|
87
|
+
method: string
|
|
88
|
+
static: boolean
|
|
89
|
+
/** the runtime/index.ts wiring site */
|
|
90
|
+
wiringFile?: string
|
|
91
|
+
wiringLine?: number
|
|
92
|
+
/** the resolved handler file (followed from the `execute` import) */
|
|
93
|
+
handlerFile?: string
|
|
94
|
+
handlerLine?: number
|
|
95
|
+
/** kernel ops detected in the handler (::update, ::link, createNode, …) */
|
|
96
|
+
kernelCalls?: string[]
|
|
97
|
+
/** declared auth policy on the runtime config; absent ⇒ defaults to 'required'. */
|
|
98
|
+
auth?: 'public' | 'optional' | 'required'
|
|
99
|
+
/** authorize hook shape: 'absent' (none), 'noop' (allow-all), 'custom' (real check). */
|
|
100
|
+
authorize?: 'absent' | 'noop' | 'custom'
|
|
101
|
+
/** raw source of the authorize hook (for the hover preview). */
|
|
102
|
+
authorizeSnippet?: string
|
|
103
|
+
/** false ⇒ a todo()/NotImplemented stub → "contract-only" badge */
|
|
104
|
+
implemented: boolean
|
|
105
|
+
/** true ⇒ resolver could not link a file → "unlinked" badge */
|
|
106
|
+
unlinked?: boolean
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface SourceSpan {
|
|
110
|
+
file: string
|
|
111
|
+
startLine: number
|
|
112
|
+
endLine: number
|
|
113
|
+
doc?: string
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface SchemaAnnotation {
|
|
117
|
+
/** anchor ref key, e.g. 'class.Monitor.property.status' */
|
|
118
|
+
target: string
|
|
119
|
+
severity: 'warn' | 'info'
|
|
120
|
+
code: 'ENUM_DROPPED_BY_UPDATE' | 'COMPILE_ERROR' | 'EDGE_PROP_TYPE_MISSING'
|
|
121
|
+
message: string
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface CrossDomainImport {
|
|
125
|
+
name: string
|
|
126
|
+
origin: string
|
|
127
|
+
definition: 'interface' | 'class'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface SchemaOverlay {
|
|
131
|
+
origin: string
|
|
132
|
+
/** defineDomain({ requires }) — runtime domain dependencies */
|
|
133
|
+
requires: string[]
|
|
134
|
+
/** non-kernel ir.imports → true cross-domain imports */
|
|
135
|
+
crossDomainImports: CrossDomainImport[]
|
|
136
|
+
/** kernel-origin ir.imports → mixin interfaces (collapsed chip) */
|
|
137
|
+
mixins: CrossDomainImport[]
|
|
138
|
+
postInstall?: string
|
|
139
|
+
handlerLinks: HandlerLink[]
|
|
140
|
+
/** keyed by anchor ref (class.X / class.X.property.y / class.X.method.m / edge.e / interface.I…) */
|
|
141
|
+
sourceSpans: Record<string, SourceSpan>
|
|
142
|
+
annotations: SchemaAnnotation[]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface BundleError {
|
|
146
|
+
message: string
|
|
147
|
+
file?: string
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface StudioSchemaBundle {
|
|
151
|
+
domainId: string
|
|
152
|
+
schemaHash: string
|
|
153
|
+
extractedBy: 'runtime-bun' | 'static-tsmorph-fallback'
|
|
154
|
+
depsInstalled: boolean
|
|
155
|
+
ir: SchemaIR | null
|
|
156
|
+
overlay: SchemaOverlay
|
|
157
|
+
/**
|
|
158
|
+
* Member bodies of the interfaces this domain IMPORTS — kernel mixins (Named,
|
|
159
|
+
* Iconable, Timestamped…) and cross-domain interfaces (e.g. Notifiable). The
|
|
160
|
+
* serializer drops these from `ir` (they appear in `ir.imports` as
|
|
161
|
+
* {origin,definition} descriptors only), so the extractor re-serializes each
|
|
162
|
+
* imported schema to recover them. Keyed by interface name; the origin lives in
|
|
163
|
+
* `ir.imports[name]`. Lets the detail pane surface inherited members like
|
|
164
|
+
* Named→name without re-parsing the kernel. Empty when deps aren't installed.
|
|
165
|
+
*/
|
|
166
|
+
importedInterfaces?: Record<string, IrInterface>
|
|
167
|
+
/** present when the runtime import failed to compile (render state, not a crash) */
|
|
168
|
+
error?: BundleError | null
|
|
169
|
+
extractedAt: string
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ─────────────────────────── Domain anatomy (non-schema) ───────────────────────────
|
|
173
|
+
|
|
174
|
+
export interface DomainOverview {
|
|
175
|
+
origin: string
|
|
176
|
+
adapter: 'astrale' | 'cloudflare' | 'unknown'
|
|
177
|
+
prodTarget?: string
|
|
178
|
+
devSecrets?: string
|
|
179
|
+
postInstall?: string
|
|
180
|
+
requires: string[]
|
|
181
|
+
packageName?: string
|
|
182
|
+
packageVersion?: string
|
|
183
|
+
astraleDeps: Record<string, string>
|
|
184
|
+
schemaDir: string
|
|
185
|
+
client?: string
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface ViewInfo {
|
|
189
|
+
slug: string
|
|
190
|
+
kind: 'inline-html' | 'spa' | 'unknown'
|
|
191
|
+
auth?: string
|
|
192
|
+
mount?: string
|
|
193
|
+
url?: string
|
|
194
|
+
/** the class(es) this view binds to via `viewFor: selfOf(Class)` (DSL allows an array);
|
|
195
|
+
* absent ⇒ unbound/global */
|
|
196
|
+
viewFor?: string | string[]
|
|
197
|
+
file?: string
|
|
198
|
+
description?: string
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Resolved LIVE serving URL of a view on its target instance (ground truth via `astrale get`). */
|
|
202
|
+
export interface ViewUrlResult {
|
|
203
|
+
status: 'installed' | 'not-installed' | 'unknown'
|
|
204
|
+
url?: string | null
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** A short-lived delegation token + context so the studio can act as the authenticated
|
|
208
|
+
* SHELL HOST for a live view preview (the parent hands this to the view iframe). */
|
|
209
|
+
export type PreviewToken =
|
|
210
|
+
| { status: 'ok'; token: string; expiresAt: number; kernelUrl: string; functionId: string }
|
|
211
|
+
| { status: 'unavailable'; reason: string }
|
|
212
|
+
|
|
213
|
+
export interface ClientFeature {
|
|
214
|
+
name: string
|
|
215
|
+
files: string[]
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface ClientTree {
|
|
219
|
+
shell: string[]
|
|
220
|
+
features: ClientFeature[]
|
|
221
|
+
routes: Record<string, string>
|
|
222
|
+
present: boolean
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export interface EnvField {
|
|
226
|
+
name: string
|
|
227
|
+
optional: boolean
|
|
228
|
+
doc?: string
|
|
229
|
+
secret?: boolean
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export type EnvName = 'dev' | 'prod'
|
|
233
|
+
|
|
234
|
+
/** One env var in the editor: the env.ts contract side (declared/optional/doc)
|
|
235
|
+
* merged with the `.env.<env>` file side (value). A row may be declared-only
|
|
236
|
+
* (in env.ts, not yet in the file), set, or an orphan (in the file, not env.ts). */
|
|
237
|
+
export interface EnvVarRow {
|
|
238
|
+
name: string
|
|
239
|
+
/** current value from `.env.<env>` ('' when unset or empty) */
|
|
240
|
+
value: string
|
|
241
|
+
/** declared as a fillable (non-binding) field in env.ts's Env interface */
|
|
242
|
+
declared: boolean
|
|
243
|
+
/** env.ts marks it optional (`?`). Only required (!optional) + empty raises the signal. */
|
|
244
|
+
optional: boolean
|
|
245
|
+
/** JSDoc on the env.ts field — the inline hint */
|
|
246
|
+
doc?: string
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** The editable env for one env name (dev|prod): the `.env.<env>` file reconciled
|
|
250
|
+
* against env.ts. The GUI is the read-only studio's one sanctioned writer of a
|
|
251
|
+
* domain file (the explicit exception). */
|
|
252
|
+
export interface EnvFileModel {
|
|
253
|
+
env: EnvName
|
|
254
|
+
/** the secrets file, relative to the domain root (e.g. '.env.dev') */
|
|
255
|
+
file: string
|
|
256
|
+
/** wired via `astrale.config.ts` (`secrets: '.env.<env>'`)? false ⇒ the file is used
|
|
257
|
+
* by convention but the adapter isn't pointed at it (e.g. managed prod). */
|
|
258
|
+
configured: boolean
|
|
259
|
+
exists: boolean
|
|
260
|
+
adapter: DomainOverview['adapter']
|
|
261
|
+
rows: EnvVarRow[]
|
|
262
|
+
/** declared && required && empty — the count the "needs values" signal shows */
|
|
263
|
+
requiredMissing: number
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export interface DomainAnatomy {
|
|
267
|
+
overview: DomainOverview
|
|
268
|
+
views: ViewInfo[]
|
|
269
|
+
client: ClientTree
|
|
270
|
+
env: EnvField[]
|
|
271
|
+
depsContainer?: string
|
|
272
|
+
/** shallow readdir of integrations/ top-level dir names — a hint, NOT a parse */
|
|
273
|
+
detectedIntegrations: string[]
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ─────────────────────────── Instance / deploy ───────────────────────────
|
|
277
|
+
|
|
278
|
+
/** A kernel instance the CLI knows about (a local bookmark or an admin-managed one). */
|
|
279
|
+
export interface InstanceInfo {
|
|
280
|
+
name: string
|
|
281
|
+
url: string
|
|
282
|
+
active: boolean
|
|
283
|
+
kind: 'bookmark' | 'managed'
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** Global (NOT per-domain) — the CLI's instances + which is active. Source of truth: `astrale instance list`. */
|
|
287
|
+
export interface InstancesState {
|
|
288
|
+
active: string | null
|
|
289
|
+
instances: InstanceInfo[]
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** What the studio recorded the last time IT ran a deploy for this domain. */
|
|
293
|
+
export interface DeployRecord {
|
|
294
|
+
at: string
|
|
295
|
+
schemaHash: string
|
|
296
|
+
ok: boolean
|
|
297
|
+
url?: string
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** Per-domain deploy/install state (the active instance is global — see InstancesState). */
|
|
301
|
+
export interface InstanceStatus {
|
|
302
|
+
/** the domain's configured deploy target (astrale.config.ts prod.instance) */
|
|
303
|
+
deployTarget: string | null
|
|
304
|
+
/** has a `prod` script → deployable via `pnpm prod` */
|
|
305
|
+
deployable: boolean
|
|
306
|
+
/** GROUND TRUTH — queried from the target instance (`astrale get /<origin>`), not local state.
|
|
307
|
+
* 'unknown' = the instance couldn't be reached/queried (no target, not authed, offline). */
|
|
308
|
+
install: 'installed' | 'not-installed' | 'unknown'
|
|
309
|
+
/** local schema vs the schema actually INSTALLED on the instance (ground truth) */
|
|
310
|
+
drift: 'in-sync' | 'drifted' | 'unknown'
|
|
311
|
+
localHash: string | null
|
|
312
|
+
/** hash of the schema installed on the instance (when reachable + installed) */
|
|
313
|
+
installedHash: string | null
|
|
314
|
+
/** the studio's own last deploy — supplementary (service URL / when), not the source of truth */
|
|
315
|
+
lastDeploy: DeployRecord | null
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export interface DeployResult {
|
|
319
|
+
ok: boolean
|
|
320
|
+
url: string | null
|
|
321
|
+
output: string
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ─────────────────────────── Comments / open-questions ───────────────────────────
|
|
325
|
+
|
|
326
|
+
export type ThreadRole = 'user' | 'author'
|
|
327
|
+
export type ThreadEntryType = 'text' | 'choice'
|
|
328
|
+
|
|
329
|
+
export interface ThreadEntry {
|
|
330
|
+
id: string
|
|
331
|
+
role: ThreadRole
|
|
332
|
+
type: ThreadEntryType
|
|
333
|
+
text: string
|
|
334
|
+
options?: string[]
|
|
335
|
+
answer?: string | null
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export type AnchorKind = 'schema' | 'section' | 'file' | 'free'
|
|
339
|
+
|
|
340
|
+
export interface AnchorRef {
|
|
341
|
+
ref: string
|
|
342
|
+
kind: AnchorKind
|
|
343
|
+
file?: string
|
|
344
|
+
startLine?: number
|
|
345
|
+
endLine?: number
|
|
346
|
+
label?: string
|
|
347
|
+
/** Flow-canvas coordinates for section-level canvas comments. */
|
|
348
|
+
x?: number
|
|
349
|
+
y?: number
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export interface Comment {
|
|
353
|
+
id: string
|
|
354
|
+
/** annotate-compatible: array of string excerpts */
|
|
355
|
+
anchors: string[]
|
|
356
|
+
/** studio-only, index-aligned to `anchors` */
|
|
357
|
+
anchorRefs: AnchorRef[]
|
|
358
|
+
status: 'open' | 'closed'
|
|
359
|
+
closeNote?: string
|
|
360
|
+
thread: ThreadEntry[]
|
|
361
|
+
createdAt: string
|
|
362
|
+
/** derived: a thread whose first entry is role:'author' is a question */
|
|
363
|
+
kind: 'comment' | 'question'
|
|
364
|
+
/** set when the anchor ref no longer resolves against the current schema */
|
|
365
|
+
orphaned?: boolean
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export interface CommentStore {
|
|
369
|
+
schemaVersion: string
|
|
370
|
+
comments: Comment[]
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export interface MergeResult {
|
|
374
|
+
merged: number
|
|
375
|
+
closed: number
|
|
376
|
+
unknownIds: string[]
|
|
377
|
+
schemaMismatch: boolean
|
|
378
|
+
pastedSchemaVersion?: string
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ─────────────────────────── Change tracking ───────────────────────────
|
|
382
|
+
|
|
383
|
+
export type SchemaChangeKind =
|
|
384
|
+
| 'class-added'
|
|
385
|
+
| 'class-removed'
|
|
386
|
+
| 'interface-added'
|
|
387
|
+
| 'interface-removed'
|
|
388
|
+
| 'edge-added'
|
|
389
|
+
| 'edge-removed'
|
|
390
|
+
| 'prop-added'
|
|
391
|
+
| 'prop-removed'
|
|
392
|
+
| 'prop-type-changed'
|
|
393
|
+
| 'prop-required-changed'
|
|
394
|
+
| 'method-added'
|
|
395
|
+
| 'method-removed'
|
|
396
|
+
| 'method-signature-changed'
|
|
397
|
+
|
|
398
|
+
export interface SchemaChange {
|
|
399
|
+
kind: SchemaChangeKind
|
|
400
|
+
target: string
|
|
401
|
+
detail?: string
|
|
402
|
+
breaking: boolean
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export interface FileChange {
|
|
406
|
+
file: string
|
|
407
|
+
status: 'added' | 'modified' | 'removed'
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export interface ChangeSet {
|
|
411
|
+
source: 'baseline' | 'git'
|
|
412
|
+
hasGit: boolean
|
|
413
|
+
hasBaseline: boolean
|
|
414
|
+
schemaChanges: SchemaChange[]
|
|
415
|
+
fileChanges: FileChange[]
|
|
416
|
+
schemaDiffText?: string
|
|
417
|
+
classification: 'none' | 'additive' | 'breaking'
|
|
418
|
+
baselineCapturedAt?: string
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ─────────────────────────── Core (genesis) data ───────────────────────────
|
|
422
|
+
// A domain's `core` is its baked-in genesis graph: the concrete node/edge
|
|
423
|
+
// instances `defineCore(schema, { nodes, edges })` ships in the install bundle.
|
|
424
|
+
// Read-only here — the studio renders it and lets you comment to request changes.
|
|
425
|
+
|
|
426
|
+
/** One materialized node instance in a domain's core graph. */
|
|
427
|
+
export interface StudioCoreNode {
|
|
428
|
+
/** stable slash-path identity, e.g. `/big-shop.example.dev/core/brands/acme` (also the comment anchor key) */
|
|
429
|
+
path: string
|
|
430
|
+
/** the IR class this node instantiates (keys into StudioSchemaBundle.ir.classes) */
|
|
431
|
+
className: string
|
|
432
|
+
/** the node's property values, keyed by (possibly owner-qualified) property name */
|
|
433
|
+
data: Record<string, unknown>
|
|
434
|
+
/** parent node's `path`, when nested under another node (absent for roots) */
|
|
435
|
+
parent?: string
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/** One materialized edge instance wiring two core nodes. */
|
|
439
|
+
export interface StudioCoreEdge {
|
|
440
|
+
/** source node `path` (or `self(ClassName)` for a meta-node endpoint) */
|
|
441
|
+
from: string
|
|
442
|
+
/** target node `path` (or `self(ClassName)`) */
|
|
443
|
+
to: string
|
|
444
|
+
/** the IR edge class name (keys into StudioSchemaBundle.ir.classes, type:'edge') */
|
|
445
|
+
edgeName: string
|
|
446
|
+
/** edge property values, when the edge class carries data */
|
|
447
|
+
data?: Record<string, unknown>
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/** A domain's core data: the concrete genesis node/edge instance graph. */
|
|
451
|
+
export interface StudioCore {
|
|
452
|
+
/** the domain origin this core graph belongs to (mirrors SchemaIR.domain) */
|
|
453
|
+
domain: string
|
|
454
|
+
nodes: StudioCoreNode[]
|
|
455
|
+
edges: StudioCoreEdge[]
|
|
456
|
+
/** set when extraction failed; null when extraction succeeded (including "no core defined") */
|
|
457
|
+
error?: { message: string } | null
|
|
458
|
+
extractedAt: string
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// ─────────────────────────── Context ───────────────────────────
|
|
462
|
+
|
|
463
|
+
export interface ContextItem {
|
|
464
|
+
id: string
|
|
465
|
+
bucket: 'user' | 'auto'
|
|
466
|
+
title: string
|
|
467
|
+
body: string
|
|
468
|
+
source?: string
|
|
469
|
+
updatedAt: string
|
|
470
|
+
/** auto items: included in the copy payload only when true */
|
|
471
|
+
includeInHandoff?: boolean
|
|
472
|
+
freshness?: string
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
export interface ContextStore {
|
|
476
|
+
user: ContextItem[]
|
|
477
|
+
auto: ContextItem[]
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** A document the user drops in as context for the AI agent. */
|
|
481
|
+
export interface DocMeta {
|
|
482
|
+
id: string
|
|
483
|
+
name: string
|
|
484
|
+
type: string
|
|
485
|
+
size: number
|
|
486
|
+
addedAt: string
|
|
487
|
+
updatedAt?: string
|
|
488
|
+
/** relative path under the dotted folder (server-side) */
|
|
489
|
+
stored: string
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// ─────────────────────────── Integrations ───────────────────────────
|
|
493
|
+
|
|
494
|
+
export interface Integration {
|
|
495
|
+
id: string
|
|
496
|
+
name: string
|
|
497
|
+
kind: string
|
|
498
|
+
status: 'planned' | 'active' | 'deprecated' | string
|
|
499
|
+
notes?: string
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export interface IntegrationsState {
|
|
503
|
+
integrations: Integration[]
|
|
504
|
+
detectedSubfolders: string[]
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** A domain in the catalog — local to this workspace, a faked external service, or the kernel. */
|
|
508
|
+
export interface DomainCatalogEntry {
|
|
509
|
+
origin: string
|
|
510
|
+
name: string
|
|
511
|
+
kind: 'kernel' | 'local' | 'external'
|
|
512
|
+
description: string
|
|
513
|
+
/** raw lucide-style SVG icon (stroke="currentColor") */
|
|
514
|
+
icon: string
|
|
515
|
+
/** kernel is always present + required */
|
|
516
|
+
required?: boolean
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// ─────────────────────────── Domain summary / workspace ───────────────────────────
|
|
520
|
+
|
|
521
|
+
export interface DomainSummary {
|
|
522
|
+
id: string
|
|
523
|
+
origin: string
|
|
524
|
+
path: string
|
|
525
|
+
schemaDir: string
|
|
526
|
+
depsInstalled: boolean
|
|
527
|
+
hasGit: boolean
|
|
528
|
+
configFile: string
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// ─────────────────────────── Copy payload ───────────────────────────
|
|
532
|
+
|
|
533
|
+
export interface CopyPayload {
|
|
534
|
+
markdown: string
|
|
535
|
+
openComments: number
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// ─────────────────────────── Agent loop (live, harness-agnostic) ───────────────────────────
|
|
539
|
+
|
|
540
|
+
/** Kinds of activity the studio surfaces while a local agent runs a turn. */
|
|
541
|
+
export type AgentEventKind =
|
|
542
|
+
| 'status' // lifecycle / human note ("session started", "merged 2 replies")
|
|
543
|
+
| 'thinking' // assistant reasoning (summarized)
|
|
544
|
+
| 'message' // assistant prose addressed to the user
|
|
545
|
+
| 'tool' // a tool invocation (edit, bash, read, …)
|
|
546
|
+
| 'reply' // the agent posted a reply to a specific thread (via the bridge)
|
|
547
|
+
| 'error'
|
|
548
|
+
|
|
549
|
+
export interface AgentEvent {
|
|
550
|
+
id: string
|
|
551
|
+
ts: string
|
|
552
|
+
kind: AgentEventKind
|
|
553
|
+
text: string
|
|
554
|
+
/** for kind:'tool' — the tool name (Edit/Write/Bash/Read…) */
|
|
555
|
+
tool?: string
|
|
556
|
+
/** for kind:'tool' — a compact target (file path, command, pattern) */
|
|
557
|
+
target?: string
|
|
558
|
+
/** for kind:'reply' — the comment id the reply landed on */
|
|
559
|
+
commentId?: string
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export const AGENT_EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max', 'ultracode'] as const
|
|
563
|
+
export type AgentEffort = (typeof AGENT_EFFORT_LEVELS)[number]
|
|
564
|
+
|
|
565
|
+
export interface AgentPromptSnapshot {
|
|
566
|
+
createdAt: string
|
|
567
|
+
/** appended to the harness default system prompt */
|
|
568
|
+
systemPrompt: string
|
|
569
|
+
/** piped to the harness on stdin */
|
|
570
|
+
turnPrompt: string
|
|
571
|
+
/** true when this turn started a new harness conversation */
|
|
572
|
+
firstTurn: boolean
|
|
573
|
+
/** true when this turn used a prior harness session id */
|
|
574
|
+
resumed: boolean
|
|
575
|
+
sessionId?: string
|
|
576
|
+
/** Claude Code --effort value used for this turn. */
|
|
577
|
+
effort?: AgentEffort
|
|
578
|
+
/** generated MCP bridge tools exposed to the harness for live write-back */
|
|
579
|
+
mcpTools: string[]
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export interface AgentSystemPromptInfo {
|
|
583
|
+
bridge: boolean
|
|
584
|
+
systemPrompt: string
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export type AgentRunStatus =
|
|
588
|
+
| 'queued'
|
|
589
|
+
| 'running'
|
|
590
|
+
| 'succeeded'
|
|
591
|
+
| 'failed'
|
|
592
|
+
| 'canceled'
|
|
593
|
+
/** the studio process died mid-turn (restart/crash) — the spawned agent went with
|
|
594
|
+
* it, but the CONVERSATION is preserved, so the next submit resumes it. */
|
|
595
|
+
| 'interrupted'
|
|
596
|
+
|
|
597
|
+
/** One agent turn for a domain: the live transcript + outcome. */
|
|
598
|
+
export interface AgentRun {
|
|
599
|
+
id: string
|
|
600
|
+
domainId: string
|
|
601
|
+
harness: string
|
|
602
|
+
status: AgentRunStatus
|
|
603
|
+
createdAt: string
|
|
604
|
+
finishedAt?: string
|
|
605
|
+
/** the harness session id (so the next turn resumes the same conversation) */
|
|
606
|
+
sessionId?: string
|
|
607
|
+
/** true ⇒ this turn resumed an existing conversation (vs. started a new one) */
|
|
608
|
+
resumed?: boolean
|
|
609
|
+
/** short human label of what this turn was asked to do */
|
|
610
|
+
summary: string
|
|
611
|
+
/** comment ids this turn was started to answer */
|
|
612
|
+
targetCommentIds: string[]
|
|
613
|
+
events: AgentEvent[]
|
|
614
|
+
costUsd?: number
|
|
615
|
+
numTurns?: number
|
|
616
|
+
/** total tokens processed this turn (input + output + cache) */
|
|
617
|
+
tokens?: number
|
|
618
|
+
error?: string
|
|
619
|
+
/** how many threads the agent answered live via the bridge tools this turn */
|
|
620
|
+
liveReplies?: number
|
|
621
|
+
/** result of merging the agent's final machine-state reply block, if any */
|
|
622
|
+
merge?: MergeResult
|
|
623
|
+
/** exact prompt inputs sent to the harness for this turn */
|
|
624
|
+
prompt?: AgentPromptSnapshot
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/** The ongoing, resumable conversation for a domain — one continuous Claude Code
|
|
628
|
+
* session threaded across submits. Survives studio restarts (persisted on disk). */
|
|
629
|
+
export interface ConversationInfo {
|
|
630
|
+
/** a resumable session exists → the next submit continues it (vs. starting fresh) */
|
|
631
|
+
active: boolean
|
|
632
|
+
/** successful turns recorded in the current conversation */
|
|
633
|
+
turns: number
|
|
634
|
+
/** which harness the conversation belongs to (resume only applies within it) */
|
|
635
|
+
harness?: string
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/** The agent's raw resumable session id, surfaced for manual view/edit in Settings. */
|
|
639
|
+
export interface AgentSessionInfo {
|
|
640
|
+
sessionId: string | null
|
|
641
|
+
turns: number
|
|
642
|
+
harness?: string
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/** Whether the selected agent harness (e.g. Claude Code) is installed & invokable. */
|
|
646
|
+
export interface HarnessStatus {
|
|
647
|
+
id: string
|
|
648
|
+
label: string
|
|
649
|
+
/** the binary/command probed (e.g. 'claude') */
|
|
650
|
+
bin: string
|
|
651
|
+
ok: boolean
|
|
652
|
+
version?: string
|
|
653
|
+
/** human message — install / PATH guidance when not ok */
|
|
654
|
+
message: string
|
|
655
|
+
/** known harnesses for the selector (locked to one for now) */
|
|
656
|
+
options: { id: string; label: string }[]
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/** One MCP server the harness loaded, with its live connection status. */
|
|
660
|
+
export interface McpServerInfo {
|
|
661
|
+
name: string
|
|
662
|
+
/** harness-reported status: 'connected' | 'needs-auth' | 'failed' | 'pending' | … */
|
|
663
|
+
status: string
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/** One skill, reconciled between what is installed on disk and what the harness
|
|
667
|
+
* actually LOADED for this domain's cwd. `loaded:false` ⇒ installed but inactive
|
|
668
|
+
* here (e.g. a disabled plugin or a cwd-scoped skill) — the key diagnostic. */
|
|
669
|
+
export interface LoadoutSkill {
|
|
670
|
+
/** the slash-command the harness invokes it by — e.g. 'astrale-domain' or 'vercel:nextjs' */
|
|
671
|
+
command: string
|
|
672
|
+
/** display name from SKILL.md frontmatter (falls back to `command`) */
|
|
673
|
+
name: string
|
|
674
|
+
description?: string
|
|
675
|
+
/** where it lives on disk */
|
|
676
|
+
source: 'project' | 'user' | 'plugin'
|
|
677
|
+
/** the providing plugin, when source==='plugin' */
|
|
678
|
+
plugin?: string
|
|
679
|
+
/** present in the harness's loaded slash-commands for this cwd */
|
|
680
|
+
loaded: boolean
|
|
681
|
+
/** absolute path to the skill's SKILL.md (so the UI can show its content) */
|
|
682
|
+
path?: string
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/** What the harness ACTUALLY loaded for a domain's cwd — read from the `system/init`
|
|
686
|
+
* event of a headless `claude` probe (the harness-authoritative source), then
|
|
687
|
+
* reconciled against on-disk skills. The studio's read-only window into its agent. */
|
|
688
|
+
export interface HarnessLoadout {
|
|
689
|
+
/** the probe ran and returned an init event */
|
|
690
|
+
ok: boolean
|
|
691
|
+
/** reason when !ok (binary missing / probe timed out / no init event) */
|
|
692
|
+
detail?: string
|
|
693
|
+
model?: string
|
|
694
|
+
permissionMode?: string
|
|
695
|
+
/** how the harness is authed: 'none' | 'ANTHROPIC_API_KEY' | … */
|
|
696
|
+
apiKeySource?: string
|
|
697
|
+
/** the cwd the harness was probed in (the domain root) */
|
|
698
|
+
cwd?: string
|
|
699
|
+
/** built-in tool names loaded (Read, Edit, Bash, …) */
|
|
700
|
+
tools: string[]
|
|
701
|
+
mcpServers: McpServerInfo[]
|
|
702
|
+
skills: LoadoutSkill[]
|
|
703
|
+
/** subagent types available to the harness (incl. plugin-provided) */
|
|
704
|
+
agents: string[]
|
|
705
|
+
/** count of loaded slash-commands that are built-in/harness commands, not skills */
|
|
706
|
+
builtinCommandCount: number
|
|
707
|
+
/** epoch ms when probed */
|
|
708
|
+
probedAt: number
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/** Domain-attributable agent spend — accumulated from this studio's own runs on
|
|
712
|
+
* this domain (NOT machine-wide). Stored at `.domain-studio/usage.json`. */
|
|
713
|
+
export interface DomainUsage {
|
|
714
|
+
/** runs that reported usage (succeeded or not — a failed turn still costs) */
|
|
715
|
+
runs: number
|
|
716
|
+
/** cumulative tokens (input + output + cache) across those runs */
|
|
717
|
+
tokens: number
|
|
718
|
+
/** cumulative USD across those runs */
|
|
719
|
+
costUsd: number
|
|
720
|
+
lastRunAt?: string
|
|
721
|
+
lastTokens?: number
|
|
722
|
+
lastCostUsd?: number
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/** Snapshot returned by GET /agent — drives the activity drawer. */
|
|
726
|
+
export interface AgentRunSnapshot {
|
|
727
|
+
harness: string
|
|
728
|
+
available: boolean
|
|
729
|
+
/** the active or most-recent run for this domain (null if none yet) */
|
|
730
|
+
run: AgentRun | null
|
|
731
|
+
/** the resumable conversation behind the runs (turns, whether one is live) */
|
|
732
|
+
conversation: ConversationInfo
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// ─────────────────────────── SSE events ───────────────────────────
|
|
736
|
+
|
|
737
|
+
export type StudioEvent =
|
|
738
|
+
| { type: 'schema-diff'; domainId: string; schemaHash: string }
|
|
739
|
+
| { type: 'anatomy-diff'; domainId: string }
|
|
740
|
+
| { type: 'comments'; domainId: string }
|
|
741
|
+
| { type: 'compile-error'; domainId: string; message: string }
|
|
742
|
+
| { type: 'resolving'; domainId: string }
|
|
743
|
+
| { type: 'agent-run'; domainId: string; run: AgentRun }
|
|
744
|
+
| { type: 'agent-event'; domainId: string; runId: string; event: AgentEvent }
|
|
745
|
+
| { type: 'hello'; domains: string[] }
|
|
746
|
+
| { type: 'workspace'; domains: string[] }
|
|
747
|
+
|
|
748
|
+
// ─────────────────────────── Render helpers (client) ───────────────────────────
|
|
749
|
+
|
|
750
|
+
// ─────────────────────────── Graph layout ───────────────────────────
|
|
751
|
+
|
|
752
|
+
export interface NodePosition {
|
|
753
|
+
x: number
|
|
754
|
+
y: number
|
|
755
|
+
/** persisted size — only expanded module containers carry one. */
|
|
756
|
+
w?: number
|
|
757
|
+
h?: number
|
|
758
|
+
}
|
|
759
|
+
export interface LayoutState {
|
|
760
|
+
schemaHash?: string
|
|
761
|
+
positions: Record<string, NodePosition>
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/** Persisted per-domain canvas visibility — the manual hide-set + the inherited-edge
|
|
765
|
+
* category toggle. Sibling of LayoutState: layout owns node POSITIONS, this owns what's SHOWN. */
|
|
766
|
+
export interface VisibilityState {
|
|
767
|
+
/** refs hidden on the canvas: `class.X` | `edge.X` | `domain.<origin>` (interfaces use
|
|
768
|
+
* `materializedInterfaces`, not this set — see below) */
|
|
769
|
+
hidden: Record<string, true>
|
|
770
|
+
showInheritedEdges: boolean
|
|
771
|
+
/** Local interfaces MATERIALIZED as canvas NODES (default = badge). Keyed by BARE interface
|
|
772
|
+
* name (e.g. `Fulfillable`) — a set distinct from `hidden`, so no ref namespace collision. */
|
|
773
|
+
materializedInterfaces: Record<string, true>
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
export type TypeDescriptor =
|
|
777
|
+
| { kind: 'string' | 'number' | 'integer' | 'boolean' | 'null' | 'unknown'; optional: boolean }
|
|
778
|
+
| { kind: 'enum'; values: (string | number | boolean | null)[]; optional: boolean }
|
|
779
|
+
| { kind: 'array'; items: TypeDescriptor; optional: boolean }
|
|
780
|
+
| {
|
|
781
|
+
kind: 'object'
|
|
782
|
+
fields: Record<string, TypeDescriptor>
|
|
783
|
+
required: string[]
|
|
784
|
+
optional: boolean
|
|
785
|
+
}
|
|
786
|
+
| { kind: 'ref'; target: string; refKind: 'node' | 'data'; optional: boolean }
|
|
787
|
+
|
|
788
|
+
// ─────────────────────────── Studio settings (power-user overrides) ───────────────────────────
|
|
789
|
+
|
|
790
|
+
/** Per-domain overrides for values the studio otherwise hard-codes. Stored at
|
|
791
|
+
* `.domain-studio/settings.json`; missing keys fall back to defaults. */
|
|
792
|
+
export interface StudioSettings {
|
|
793
|
+
/** Claude Code reasoning effort passed as --effort (default 'high') */
|
|
794
|
+
agentEffort: AgentEffort
|
|
795
|
+
/** folder under the domain root scanned for integrations (default 'integrations') */
|
|
796
|
+
integrationsDir: string
|
|
797
|
+
/** schema/core extraction subprocess timeout in ms (default 20000) */
|
|
798
|
+
introspectTimeoutMs: number
|
|
799
|
+
/** how often the per-domain instance status refreshes, ms (default 30000) */
|
|
800
|
+
instancePollMs: number
|
|
801
|
+
/** how often the studio re-checks for stale schema / updates, ms (default 600000) */
|
|
802
|
+
updatesPollMs: number
|
|
803
|
+
/** timeout when probing a live view URL from the instance, ms (default 8000) */
|
|
804
|
+
viewProbeTimeoutMs: number
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// ─────────────────── Harness model gateway (custom LLM endpoint) ───────────────────
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* Point the agent harness (Claude Code) at a custom Anthropic-compatible model
|
|
811
|
+
* gateway — e.g. an Astrale `ai-gateway` model node — instead of its built-in
|
|
812
|
+
* auth. The values become env on the SPAWNED harness child only
|
|
813
|
+
* (ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN / ANTHROPIC_MODEL): the studio
|
|
814
|
+
* never writes them to your shell, your `~/.claude`, or a `claude` you run
|
|
815
|
+
* yourself outside the studio.
|
|
816
|
+
*/
|
|
817
|
+
/**
|
|
818
|
+
* How the harness gets its bearer token for the gateway. Abstracted so the same
|
|
819
|
+
* gateway works whether the studio runs locally or embedded in the Astrale GUI:
|
|
820
|
+
* - `mint` — LOCAL: the studio mints a fresh, short-lived delegation token per
|
|
821
|
+
* run via `astrale token` (audience derived from the gateway URL).
|
|
822
|
+
* No secret is stored on disk; auth follows the active CLI identity.
|
|
823
|
+
* - `token` — MANUAL: a static bearer the user pastes (non-Astrale gateways, or
|
|
824
|
+
* an explicitly long-lived token).
|
|
825
|
+
* - `host` — EMBED: the embedding Astrale GUI supplies the token (via the shell)
|
|
826
|
+
* and owns mint / refresh / scope; the studio just relays it to the
|
|
827
|
+
* harness child. The forward-looking path for the iframe deployment.
|
|
828
|
+
*/
|
|
829
|
+
export type HarnessGatewayAuth =
|
|
830
|
+
| { mode: 'mint'; instance?: string } // instance to mint on; omitted ⇒ the active one
|
|
831
|
+
| { mode: 'token'; token: string }
|
|
832
|
+
| { mode: 'host' }
|
|
833
|
+
|
|
834
|
+
export interface HarnessGatewayConfig {
|
|
835
|
+
/** master switch — off ⇒ the harness uses its own default auth */
|
|
836
|
+
enabled: boolean
|
|
837
|
+
/** ANTHROPIC_BASE_URL — Claude Code POSTs to `${baseUrl}/v1/messages`. For an
|
|
838
|
+
* Astrale model node: `https://<gateway-host>/v1/models/<modelNodeId>`. */
|
|
839
|
+
baseUrl: string
|
|
840
|
+
/** ANTHROPIC_MODEL label (cosmetic — the gateway pins the real model by URL). */
|
|
841
|
+
model?: string
|
|
842
|
+
/** how the bearer token is obtained (see HarnessGatewayAuth) */
|
|
843
|
+
auth: HarnessGatewayAuth
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/** The layered harness-gateway config for a domain: its own per-domain override,
|
|
847
|
+
* the studio-wide global default, and which one actually takes effect. */
|
|
848
|
+
export interface HarnessGatewayState {
|
|
849
|
+
/** per-domain override (`.domain-studio/harness-gateway.json`); null ⇒ inherits global */
|
|
850
|
+
local: HarnessGatewayConfig | null
|
|
851
|
+
/** studio-wide default — applies to every domain that has no local override */
|
|
852
|
+
global: HarnessGatewayConfig | null
|
|
853
|
+
/** the config that actually takes effect (an enabled local ∨ an enabled global), else null */
|
|
854
|
+
effective: HarnessGatewayConfig | null
|
|
855
|
+
/** which layer `effective` came from */
|
|
856
|
+
source: 'domain' | 'global' | 'none'
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// ─────────────────────────── Update staleness (the header "Update" badge) ───────────────────────────
|
|
860
|
+
|
|
861
|
+
/** The Astrale CLI's own staleness report — `astrale update --check --json`, run
|
|
862
|
+
* in the domain root. The CLI owns the detection; the studio only renders it.
|
|
863
|
+
* Skills are intentionally absent: they ride along with `astrale update`, so a
|
|
864
|
+
* stale CLI or SDK dep is the only thing worth surfacing. */
|
|
865
|
+
export interface StaleReport {
|
|
866
|
+
stale: boolean
|
|
867
|
+
cli: { stale: boolean; managed: boolean; current?: string; latest?: string; channel?: string }
|
|
868
|
+
sdk: {
|
|
869
|
+
stale: boolean
|
|
870
|
+
inProject: boolean
|
|
871
|
+
outdated: { pkg: string; current: string; latest: string }[]
|
|
872
|
+
}
|
|
873
|
+
}
|