@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
@@ -11,7 +11,7 @@ afterEach(() => {
11
11
  while (roots.length) rmSync(roots.pop()!, { recursive: true, force: true })
12
12
  })
13
13
 
14
- test('annotates the schema definition behind a current barrel', () => {
14
+ test('workspace creation annotates the schema definition behind a current barrel', () => {
15
15
  const root = mkdtempSync(join(tmpdir(), 'studio-create-origin-'))
16
16
  roots.push(root)
17
17
  mkdirSync(join(root, 'schema', 'application'), { recursive: true })
@@ -1,5 +1,5 @@
1
1
  /**
2
- * state/create.ts — scaffold a brand-new domain into the workspace and bring it
2
+ * Scaffold a brand-new domain into the workspace and bring it
3
3
  * online. This is the studio's ONE write that ADDS a domain (every other state
4
4
  * module operates on an existing one).
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * git.ts — best-effort git enrichment for change tracking. The fixtures are not
2
+ * Best-effort workspace Git enrichment for change tracking. The fixtures are not
3
3
  * git repos, so EVERY function here degrades gracefully and NEVER throws. The
4
4
  * baseline (baseline.ts) is the primary tracker; git only enriches when present.
5
5
  */
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Workspace update bridge for the header Update badge.
3
+ *
4
+ * We don't reimplement staleness: the `astrale` CLI owns it. `astrale update
5
+ * --check --json`, run in the DOMAIN ROOT (so its @astrale-os/* SDK-dep axis sees
6
+ * THIS project), emits a unified `{ stale, cli, sdk }` report. We run it with
7
+ * stdout piped and read it regardless of exit code — a stale result exits 10 by
8
+ * design, which is not an error here. Best-effort: anything unexpected (no
9
+ * bad output) collapses to "nothing stale" so the badge stays
10
+ * hidden rather than nagging on a hiccup.
11
+ */
12
+ import type { StaleReport } from '../../shared/types'
13
+
14
+ import { decodeJsonObject, runStudioCliJson, runStudioCliText } from '../cli'
15
+
16
+ const NOT_STALE: StaleReport = {
17
+ stale: false,
18
+ cli: { stale: false, managed: true },
19
+ sdk: { stale: false, inProject: false, outdated: [] },
20
+ }
21
+
22
+ export async function getUpdates(root: string): Promise<StaleReport> {
23
+ const result = await runStudioCliJson(['update', '--check', '--json'], decodeStaleReport, {
24
+ cwd: root,
25
+ acceptedExitCodes: [0, 10],
26
+ })
27
+ return result.ok && result.data ? result.data : NOT_STALE
28
+ }
29
+
30
+ function decodeStaleReport(value: unknown): StaleReport | null {
31
+ const report = decodeJsonObject(value)
32
+ const cli = decodeJsonObject(report?.cli)
33
+ const sdk = decodeJsonObject(report?.sdk)
34
+ if (
35
+ typeof report?.stale !== 'boolean' ||
36
+ typeof cli?.stale !== 'boolean' ||
37
+ typeof cli.managed !== 'boolean' ||
38
+ typeof sdk?.stale !== 'boolean' ||
39
+ typeof sdk.inProject !== 'boolean' ||
40
+ !Array.isArray(sdk.outdated)
41
+ ) {
42
+ return null
43
+ }
44
+ const outdated = sdk.outdated.flatMap((value) => {
45
+ const item = decodeJsonObject(value)
46
+ return typeof item?.pkg === 'string' &&
47
+ typeof item.current === 'string' &&
48
+ typeof item.latest === 'string'
49
+ ? [{ pkg: item.pkg, current: item.current, latest: item.latest }]
50
+ : []
51
+ })
52
+ if (outdated.length !== sdk.outdated.length) return null
53
+ return {
54
+ stale: report.stale,
55
+ cli: {
56
+ stale: cli.stale,
57
+ managed: cli.managed,
58
+ ...(typeof cli.current === 'string' ? { current: cli.current } : {}),
59
+ ...(typeof cli.latest === 'string' ? { latest: cli.latest } : {}),
60
+ ...(typeof cli.channel === 'string' ? { channel: cli.channel } : {}),
61
+ },
62
+ sdk: { stale: sdk.stale, inProject: sdk.inProject, outdated },
63
+ }
64
+ }
65
+
66
+ export interface UpdateApplyResult {
67
+ ok: boolean
68
+ output: string
69
+ }
70
+
71
+ /**
72
+ * Apply the update for the header "Update now" button — `astrale update --yes`,
73
+ * run in the domain root. The CLI does the work non-interactively and resiliently
74
+ * (binary + skills + SDK deps; a binary that can't self-update warns but doesn't
75
+ * block the others), so we just spawn it and capture the combined output to show.
76
+ */
77
+ export async function applyUpdates(root: string): Promise<UpdateApplyResult> {
78
+ const result = await runStudioCliText(['update', '--yes'], { cwd: root })
79
+ return {
80
+ ok: result.ok,
81
+ output: `${result.stdout}${result.stderr}`.trim() || result.detail,
82
+ }
83
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * workspace-state.ts — process-global workspace context shared by the entrypoint
3
3
  * (index.ts), the live watcher (workspace-watch.ts), and the create-domain
4
- * endpoint (state/create.ts): the scanned ROOT (where new domains are
4
+ * endpoint (workspace/create.ts): the scanned ROOT (where new domains are
5
5
  * scaffolded), the schema-dir name, and the `domainId → file-watcher stop` map.
6
6
  *
7
7
  * It exists so the create endpoint can scaffold into the same root the studio
@@ -0,0 +1,16 @@
1
+ # Studio shared contract boundaries
2
+
3
+ `../types.ts` is the compatibility facade used by existing server and client
4
+ imports. Definitions live under one semantic owner:
5
+
6
+ - `schema.ts` owns the render IR and all schema/anatomy introspection results.
7
+ - `workspace.ts` owns persisted and workspace-facing state, including the sole
8
+ `LayoutState` and `VisibilityState` definitions.
9
+ - `agent.ts` owns the harness-neutral agent protocol and harness configuration.
10
+ - `runtime.ts` owns Studio runtime configuration, SSE events, and CLI staleness.
11
+ - `../schema/identity.ts` owns pure canonical reference/key identity helpers.
12
+
13
+ Allowed dependency direction is identity → schema → workspace → agent → runtime.
14
+ Shared contracts never import server or client implementations. New consumers
15
+ may import an owning module directly; `@shared/types` remains supported for
16
+ compatibility.
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Shared agent and harness protocol.
3
+ *
4
+ * These shapes are harness-neutral and describe Studio's recorded conversation,
5
+ * capability, loadout, usage, and gateway configuration surfaces.
6
+ */
7
+
8
+ import type { MergeResult } from './workspace'
9
+
10
+ /** Kinds of activity the studio surfaces while a local agent runs a turn. */
11
+ export type AgentEventKind = 'status' | 'thinking' | 'message' | 'tool' | 'reply' | 'error'
12
+
13
+ export interface AgentEvent {
14
+ id: string
15
+ ts: string
16
+ kind: AgentEventKind
17
+ text: string
18
+ /** for kind:'tool' — the tool name (Edit/Write/Bash/Read…) */
19
+ tool?: string
20
+ /** for kind:'tool' — a compact target (file path, command, pattern) */
21
+ target?: string
22
+ /** for kind:'reply' — the comment id the reply landed on */
23
+ commentId?: string
24
+ }
25
+
26
+ export const AGENT_EFFORT_LEVELS = [
27
+ 'minimal',
28
+ 'low',
29
+ 'medium',
30
+ 'high',
31
+ 'xhigh',
32
+ 'max',
33
+ 'ultracode',
34
+ ] as const
35
+ export type AgentEffort = (typeof AGENT_EFFORT_LEVELS)[number]
36
+ export const AGENT_ACCESS_LEVELS = ['workspace', 'full'] as const
37
+ export type AgentAccess = (typeof AGENT_ACCESS_LEVELS)[number]
38
+
39
+ export interface AgentPromptSnapshot {
40
+ createdAt: string
41
+ /** appended to the harness default system prompt */
42
+ systemPrompt: string
43
+ /** piped to the harness on stdin */
44
+ turnPrompt: string
45
+ /** true when this turn started a new harness conversation */
46
+ firstTurn: boolean
47
+ /** true when this turn used a prior harness session id */
48
+ resumed: boolean
49
+ sessionId?: string
50
+ /** Explicit Studio model override used for this turn; absent means harness-native default. */
51
+ model?: string
52
+ /** Harness-native reasoning effort used for this turn. */
53
+ effort?: AgentEffort
54
+ /** Filesystem/network authority granted to the harness for this turn. */
55
+ access?: AgentAccess
56
+ /** generated MCP bridge tools exposed to the harness for live write-back */
57
+ mcpTools: string[]
58
+ }
59
+
60
+ export interface AgentSystemPromptInfo {
61
+ bridge: boolean
62
+ systemPrompt: string
63
+ }
64
+
65
+ export type AgentRunStatus =
66
+ | 'queued'
67
+ | 'running'
68
+ | 'succeeded'
69
+ | 'failed'
70
+ | 'canceled'
71
+ /** the studio process died mid-turn (restart/crash) — the spawned agent went with
72
+ * it, but the CONVERSATION is preserved, so the next submit resumes it. */
73
+ | 'interrupted'
74
+
75
+ /** One agent turn for a domain: the live transcript + outcome. */
76
+ export interface AgentRun {
77
+ id: string
78
+ domainId: string
79
+ harness: string
80
+ status: AgentRunStatus
81
+ createdAt: string
82
+ finishedAt?: string
83
+ /** the harness session id (so the next turn resumes the same conversation) */
84
+ sessionId?: string
85
+ /** true ⇒ this turn resumed an existing conversation (vs. started a new one) */
86
+ resumed?: boolean
87
+ /** short human label of what this turn was asked to do */
88
+ summary: string
89
+ /** comment ids this turn was started to answer */
90
+ targetCommentIds: string[]
91
+ events: AgentEvent[]
92
+ costUsd?: number
93
+ numTurns?: number
94
+ /** total token usage reported by the harness for this turn */
95
+ tokens?: number
96
+ error?: string
97
+ /** how many threads the agent answered live via the bridge tools this turn */
98
+ liveReplies?: number
99
+ /** result of merging the agent's final machine-state reply block, if any */
100
+ merge?: MergeResult
101
+ /** exact prompt inputs sent to the harness for this turn */
102
+ prompt?: AgentPromptSnapshot
103
+ }
104
+
105
+ /** The ongoing, resumable conversation for a domain and selected harness.
106
+ * Survives studio restarts (persisted on disk). */
107
+ export interface ConversationInfo {
108
+ /** a resumable session exists → the next submit continues it (vs. starting fresh) */
109
+ active: boolean
110
+ /** successful turns recorded in the current conversation */
111
+ turns: number
112
+ /** which harness the conversation belongs to (resume only applies within it) */
113
+ harness?: string
114
+ }
115
+
116
+ /** The agent's raw resumable session id, surfaced for manual view/edit in Settings. */
117
+ export interface AgentSessionInfo {
118
+ sessionId: string | null
119
+ turns: number
120
+ harness?: string
121
+ }
122
+
123
+ export interface HarnessCapabilities {
124
+ effortLevels: readonly AgentEffort[]
125
+ accessLevels: readonly AgentAccess[]
126
+ /** Stable aliases advertised even when the harness has no catalog API. */
127
+ modelOptions?: readonly HarnessModelOption[]
128
+ ask: boolean
129
+ loadout: boolean
130
+ /** Custom model-gateway wire contract this harness can consume in Studio. */
131
+ gateway: 'anthropic' | 'responses' | 'none'
132
+ }
133
+
134
+ /** Whether the selected agent harness is installed, invokable, and configurable. */
135
+ export interface HarnessStatus {
136
+ id: string
137
+ label: string
138
+ /** the binary/command probed (e.g. 'claude') */
139
+ bin: string
140
+ ok: boolean
141
+ version?: string
142
+ /** human message — install / PATH guidance when not ok */
143
+ message: string
144
+ /** known harnesses for the selector (locked to one for now) */
145
+ options: { id: string; label: string }[]
146
+ /** an environment/CLI override owns the selection, so the GUI cannot change it */
147
+ locked: boolean
148
+ source: 'environment' | 'domain' | 'default'
149
+ capabilities: HarnessCapabilities
150
+ }
151
+
152
+ /** One MCP server the harness loaded, with its live connection status. */
153
+ export interface McpServerInfo {
154
+ name: string
155
+ /** harness-reported status: 'connected' | 'needs-auth' | 'failed' | 'pending' | … */
156
+ status: string
157
+ }
158
+
159
+ /** One skill, reconciled between what is installed on disk and what the harness
160
+ * actually LOADED for this domain's cwd. */
161
+ export interface LoadoutSkill {
162
+ /** the slash-command the harness invokes it by — e.g. 'astrale-domain' or 'vercel:nextjs' */
163
+ command: string
164
+ /** display name from SKILL.md frontmatter (falls back to `command`) */
165
+ name: string
166
+ description?: string
167
+ /** where it lives on disk */
168
+ source: 'project' | 'user' | 'plugin'
169
+ /** the providing plugin, when source==='plugin' */
170
+ plugin?: string
171
+ /** present in the harness's loaded slash-commands for this cwd */
172
+ loaded: boolean
173
+ /** absolute path to the skill's SKILL.md (so the UI can show its content) */
174
+ path?: string
175
+ }
176
+
177
+ /** What the harness actually loaded for a domain's cwd. */
178
+ export interface HarnessLoadout {
179
+ /** the probe ran and returned an init event */
180
+ ok: boolean
181
+ /** reason when !ok (binary missing / probe timed out / no init event) */
182
+ detail?: string
183
+ /** Model the harness resolves before Studio applies its optional override. */
184
+ nativeModel?: string
185
+ model?: string
186
+ /** Where the effective model came from. */
187
+ modelSource?: 'studio' | 'config' | 'default' | 'runtime'
188
+ /** Models the harness currently advertises for easy selection. */
189
+ models?: HarnessModelOption[]
190
+ permissionMode?: string
191
+ /** how the harness is authed: 'none' | 'ANTHROPIC_API_KEY' | … */
192
+ apiKeySource?: string
193
+ /** the cwd the harness was probed in (the domain root) */
194
+ cwd?: string
195
+ /** built-in tool names loaded (Read, Edit, Bash, …) */
196
+ tools: string[]
197
+ mcpServers: McpServerInfo[]
198
+ skills: LoadoutSkill[]
199
+ /** subagent types available to the harness (incl. plugin-provided) */
200
+ agents: string[]
201
+ /** count of loaded slash-commands that are built-in/harness commands, not skills */
202
+ builtinCommandCount: number
203
+ /** epoch ms when probed */
204
+ probedAt: number
205
+ /** Claude exposes a live init event; Codex exposes configured/installed state. */
206
+ source?: 'runtime' | 'configured'
207
+ }
208
+
209
+ export interface HarnessModelOption {
210
+ /** Stable model slug passed to the harness, e.g. `gpt-5.6-sol`. */
211
+ id: string
212
+ /** Human-friendly catalog label. */
213
+ label: string
214
+ description?: string
215
+ /** The harness catalog's built-in default when no config layer overrides it. */
216
+ isDefault?: boolean
217
+ }
218
+
219
+ /** Domain-attributable agent spend — accumulated from this studio's own runs on
220
+ * this domain (NOT machine-wide). Stored at `.domain-studio/usage.json`. */
221
+ export interface DomainUsage {
222
+ /** runs that reported usage (succeeded or not — a failed turn still costs) */
223
+ runs: number
224
+ /** cumulative tokens (input + output + cache) across those runs */
225
+ tokens: number
226
+ /** cumulative USD across those runs */
227
+ costUsd: number
228
+ lastRunAt?: string
229
+ lastTokens?: number
230
+ lastCostUsd?: number
231
+ }
232
+
233
+ /** Snapshot returned by GET /agent — drives the activity drawer. */
234
+ export interface AgentRunSnapshot {
235
+ harness: string
236
+ available: boolean
237
+ /** the active or most-recent run for this domain (null if none yet) */
238
+ run: AgentRun | null
239
+ /** the resumable conversation behind the runs (turns, whether one is live) */
240
+ conversation: ConversationInfo
241
+ }
242
+
243
+ /** How the harness gets its bearer token for a custom model gateway. */
244
+ export type HarnessGatewayAuth =
245
+ | { mode: 'mint'; instance?: string }
246
+ | { mode: 'token'; token: string }
247
+ | { mode: 'host' }
248
+
249
+ export interface HarnessGatewayConfig {
250
+ /** master switch — off ⇒ the harness uses its own default auth */
251
+ enabled: boolean
252
+ /** ANTHROPIC_BASE_URL used by the spawned harness child only. */
253
+ baseUrl: string
254
+ /** ANTHROPIC_MODEL label; the gateway may pin the real model by URL. */
255
+ model?: string
256
+ /** how the bearer token is obtained */
257
+ auth: HarnessGatewayAuth
258
+ }
259
+
260
+ /** The layered harness-gateway config for a domain. */
261
+ export interface HarnessGatewayState {
262
+ /** per-domain override (`.domain-studio/harness-gateway.json`); null ⇒ inherits global */
263
+ local: HarnessGatewayConfig | null
264
+ /** studio-wide default — applies to every domain that has no local override */
265
+ global: HarnessGatewayConfig | null
266
+ /** the config that actually takes effect, else null */
267
+ effective: HarnessGatewayConfig | null
268
+ /** which layer `effective` came from */
269
+ source: 'domain' | 'global' | 'none'
270
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Shared Studio runtime and API transport contracts.
3
+ *
4
+ * This owner contains cross-process notifications, Studio runtime settings, and
5
+ * CLI-owned update reports. It does not define schema or persisted workspace state.
6
+ */
7
+
8
+ import type { AgentAccess, AgentEffort, AgentEvent, AgentRun } from './agent'
9
+
10
+ export type StudioEvent =
11
+ | { type: 'schema-diff'; domainId: string; renderFingerprint: string }
12
+ | { type: 'anatomy-diff'; domainId: string }
13
+ | { type: 'comments'; domainId: string }
14
+ | { type: 'compile-error'; domainId: string; message: string }
15
+ | { type: 'resolving'; domainId: string }
16
+ | { type: 'agent-run'; domainId: string; run: AgentRun }
17
+ | { type: 'agent-event'; domainId: string; runId: string; event: AgentEvent }
18
+ | { type: 'hello'; domains: string[] }
19
+ | { type: 'workspace'; domains: string[] }
20
+
21
+ /** Per-domain overrides stored at `.domain-studio/settings.json`. */
22
+ export interface StudioSettings {
23
+ /** Harness-native reasoning effort (default 'high') */
24
+ agentEffort: AgentEffort
25
+ /** workspace = sandboxed edits; full = unrestricted local automation */
26
+ agentAccess: AgentAccess
27
+ /** Optional model override, independently remembered for each harness id. */
28
+ agentModels: Record<string, string>
29
+ /** folder under the domain root scanned for integrations (default 'integrations') */
30
+ integrationsDir: string
31
+ /** schema/core extraction subprocess timeout in ms (default 20000) */
32
+ introspectTimeoutMs: number
33
+ /** how often the per-domain instance status refreshes, ms (default 30000) */
34
+ instancePollMs: number
35
+ /** how often the studio re-checks for stale schema / updates, ms (default 600000) */
36
+ updatesPollMs: number
37
+ /** timeout when probing a live view URL from the instance, ms (default 8000) */
38
+ viewProbeTimeoutMs: number
39
+ }
40
+
41
+ /** The Astrale CLI's `astrale update --check --json` report. */
42
+ export interface StaleReport {
43
+ stale: boolean
44
+ cli: { stale: boolean; managed: boolean; current?: string; latest?: string; channel?: string }
45
+ sdk: {
46
+ stale: boolean
47
+ inProject: boolean
48
+ outdated: { pkg: string; current: string; latest: string }[]
49
+ }
50
+ }