@astrale-os/cli 1.0.0-beta.1 → 1.0.0-beta.11
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/README.md +23 -12
- package/dist/astrale.js +48048 -56798
- package/dist/public/connect-core.js +2011 -30765
- package/dist/public/keys/index.js +884 -29483
- package/dist/public/paths/index.js +13101 -41459
- package/dist/types/admin/binding.d.ts +19 -0
- package/dist/types/admin/instance/client.d.ts +22 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +5 -12
- package/dist/types/connection/auth.d.ts +3 -0
- package/dist/types/connection/call.d.ts +3 -0
- package/dist/types/connection/command.d.ts +27 -0
- package/dist/types/connection/credential.d.ts +14 -0
- package/dist/types/connection/errors.d.ts +1 -0
- package/dist/types/connection/exchange.d.ts +9 -0
- package/dist/types/connection/failure/classify.d.ts +2 -0
- package/dist/types/connection/failure/index.d.ts +5 -0
- package/dist/types/connection/failure/model.d.ts +25 -0
- package/dist/types/connection/failure/render.d.ts +3 -0
- package/dist/types/connection/index.d.ts +8 -0
- package/dist/types/connection/reasons.d.ts +37 -0
- package/dist/types/connection/self.d.ts +37 -0
- package/dist/types/connection/session.d.ts +31 -0
- package/dist/types/connection/target.d.ts +38 -0
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/lib/admin-instance.d.ts +17 -0
- package/dist/types/lib/admin-target.d.ts +11 -36
- package/dist/types/lib/config.d.ts +7 -59
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +26 -168
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +30 -88
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/meta.d.ts +2 -2
- package/dist/types/lib/proc.d.ts +43 -0
- package/dist/types/lib/self.d.ts +9 -0
- package/dist/types/lib/update.d.ts +91 -0
- package/dist/types/lib/validation.d.ts +4 -1
- package/package.json +16 -19
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/__tests__/binding.test.ts +31 -0
- package/src/admin/__tests__/fixture.ts +101 -0
- package/src/admin/binding.ts +98 -0
- package/src/admin/catalog/.spec/api.d.ts +2 -2
- package/src/admin/catalog/__tests__/client.test.ts +20 -49
- package/src/admin/catalog/client.ts +36 -32
- package/src/admin/catalog/model.ts +3 -4
- package/src/admin/graph/.spec/api.d.ts +4 -10
- package/src/admin/graph/nodes.ts +1 -1
- package/src/admin/instance/.spec/api.d.ts +2 -2
- package/src/admin/instance/__tests__/client.test.ts +39 -164
- package/src/admin/instance/client.ts +35 -124
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +11 -20
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/auth-login.test.ts +54 -1
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +5 -1
- package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
- package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
- package/src/commands/__tests__/domain-list.test.ts +63 -4
- package/src/commands/__tests__/install-identity-override.test.ts +19 -19
- package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
- package/src/commands/__tests__/instance-status.test.ts +139 -0
- package/src/commands/__tests__/read-commands.test.ts +35 -10
- package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
- package/src/commands/__tests__/update.test.ts +48 -19
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +43 -56
- package/src/commands/domain/install.ts +13 -17
- package/src/commands/domain/list.ts +18 -13
- package/src/commands/domain/publish.ts +14 -11
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +14 -15
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +5 -4
- package/src/commands/instance/create.ts +8 -16
- package/src/commands/instance/delete.ts +12 -9
- package/src/commands/instance/list.ts +2 -2
- package/src/commands/instance/status.ts +66 -20
- package/src/commands/instance/use.ts +16 -12
- package/src/commands/introspect.ts +9 -16
- package/src/commands/logs.ts +24 -25
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +27 -30
- package/src/commands/studio.ts +20 -0
- package/src/commands/token.ts +8 -7
- package/src/commands/update.ts +38 -14
- package/src/commands/view.ts +7 -6
- package/src/connection/.spec/api.d.ts +7 -8
- package/src/connection/.spec/architecture.md +5 -4
- package/src/connection/.spec/flows/session.ts +2 -2
- package/src/connection/.spec/laws/connection.ts +6 -2
- package/src/connection/.spec/layout.ts +1 -0
- package/src/connection/__tests__/credential.test.ts +20 -1
- package/src/connection/__tests__/errors.test.ts +43 -32
- package/src/connection/__tests__/exchange.test.ts +36 -6
- package/src/connection/__tests__/failure-fixtures.ts +39 -0
- package/src/connection/__tests__/failure-safety.test.ts +75 -0
- package/src/connection/__tests__/self.test.ts +31 -11
- package/src/connection/__tests__/session.test.ts +3 -3
- package/src/connection/__tests__/target.test.ts +1 -0
- package/src/connection/auth.ts +13 -0
- package/src/connection/call.ts +1 -1
- package/src/connection/credential.ts +2 -2
- package/src/connection/errors.ts +1 -355
- package/src/connection/exchange.ts +52 -27
- package/src/connection/failure/classify.ts +110 -0
- package/src/connection/failure/index.ts +18 -0
- package/src/connection/failure/model.ts +28 -0
- package/src/connection/failure/render.ts +116 -0
- package/src/connection/reasons.ts +16 -0
- package/src/connection/self.ts +39 -21
- package/src/connection/session.ts +19 -8
- package/src/errors.ts +3 -2
- package/src/graph/.spec/api.d.ts +12 -5
- package/src/graph/.spec/layout.ts +9 -1
- package/src/graph/__tests__/mutation.test.ts +2 -2
- package/src/graph/__tests__/query.test.ts +25 -6
- package/src/graph/class.ts +30 -0
- package/src/graph/index.ts +1 -0
- package/src/graph/query.ts +21 -32
- package/src/identity/.spec/api.d.ts +2 -2
- package/src/identity/__tests__/registration.test.ts +1 -1
- package/src/identity/registration.ts +3 -3
- package/src/keys/__tests__/keys.test.ts +4 -0
- package/src/keys/credential.ts +1 -0
- package/src/lib/__tests__/admin-target.test.ts +12 -0
- package/src/lib/__tests__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/domain-publication.test.ts +138 -0
- package/src/lib/__tests__/idp-session.test.ts +22 -0
- package/src/lib/__tests__/idp.test.ts +36 -4
- package/src/lib/__tests__/instance-candidates.test.ts +1 -3
- package/src/lib/__tests__/instance-target.test.ts +7 -39
- package/src/lib/__tests__/instance.test.ts +6 -0
- package/src/lib/__tests__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
- package/src/lib/__tests__/update.test.ts +113 -8
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +18 -3
- package/src/lib/__tests__/view-session.test.ts +1 -1
- package/src/lib/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/domain-publication.ts +104 -0
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +39 -4
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +22 -12
- package/src/lib/log.ts +16 -9
- package/src/lib/login-flow.ts +13 -3
- package/src/lib/meta.ts +2 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/update.ts +124 -30
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/resolve.ts +1 -1
- package/src/lib/view/server.ts +17 -3
- package/src/program/__tests__/program.test.ts +20 -4
- package/src/program/build.ts +2 -2
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
- package/studio/client/dist/assets/index-7YHdeCxp.js +81 -0
- package/studio/client/dist/assets/index-C0FAnwNw.css +2 -0
- package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
- package/studio/client/dist/assets/schema-studio-BilUNb6Z.css +1 -0
- package/studio/client/dist/assets/schema-studio-CABpTfvH.js +8 -0
- package/studio/client/dist/index.html +3 -2
- package/studio/package.json +10 -14
- package/studio/server/agent/ask.test.ts +1 -1
- package/studio/server/agent/bridge/grant.test.ts +1 -1
- package/studio/server/agent/bridge/routes.test.ts +1 -1
- package/studio/server/agent/bridge/stdio.ts +8 -1
- package/studio/server/agent/conversation.test.ts +10 -5
- package/studio/server/agent/conversation.ts +56 -8
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/codex/loadout.ts +18 -21
- package/studio/server/agent/harness/gateway/config.ts +20 -18
- package/studio/server/agent/harness/selection.ts +9 -1
- package/studio/server/agent/prompts/anchors.test.ts +32 -36
- package/studio/server/agent/prompts/anchors.ts +20 -49
- package/studio/server/agent/prompts/system.test.ts +3 -2
- package/studio/server/agent/prompts/system.ts +6 -5
- package/studio/server/agent/prompts/turn.ts +13 -4
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/completion.ts +2 -2
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/agent/run/preparation.ts +6 -5
- package/studio/server/agent/run/transcript.test.ts +35 -1
- package/studio/server/agent/run/transcript.ts +169 -3
- package/studio/server/agent/run/usage.test.ts +24 -0
- package/studio/server/agent/run/usage.ts +26 -1
- package/studio/server/api/canvas.ts +43 -0
- package/studio/server/api/comments.ts +85 -0
- package/studio/server/api/context.ts +61 -0
- package/studio/server/api/deployment.ts +39 -0
- package/studio/server/api/documents.ts +55 -0
- package/studio/server/api/domain.ts +59 -0
- package/studio/server/api/http.ts +45 -0
- package/studio/server/api/project.ts +57 -0
- package/studio/server/api/schema.ts +12 -0
- package/studio/server/api/views.ts +57 -0
- package/studio/server/api/workspace.ts +60 -0
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +147 -0
- package/studio/server/api.ts +20 -422
- package/studio/server/cache.test.ts +122 -0
- package/studio/server/cache.ts +162 -11
- package/studio/server/cli-consumers.test.ts +494 -0
- package/studio/server/cli.test.ts +88 -0
- package/studio/server/cli.ts +240 -0
- package/studio/server/client-package.ts +25 -1
- package/studio/server/domain.test.ts +50 -40
- package/studio/server/domain.ts +83 -52
- package/studio/server/environment/dotenv-preview.test.ts +39 -0
- package/studio/server/environment/dotenv-preview.ts +27 -0
- package/studio/server/environment/files.test.ts +53 -0
- package/studio/server/{state/env.ts → environment/files.ts} +7 -48
- package/studio/server/{state → handoff}/copy.ts +21 -6
- package/studio/server/handoff/service.test.ts +22 -0
- package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/active.ts +72 -0
- package/studio/server/instances/deploy-record.test.ts +31 -0
- package/studio/server/instances/deploy-record.ts +37 -0
- package/studio/server/instances/deploy.ts +56 -0
- package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
- package/studio/server/instances/probe.ts +67 -0
- package/studio/server/instances/status.test.ts +12 -0
- package/studio/server/instances/status.ts +49 -0
- package/studio/server/introspect/anatomy/client-tree.ts +57 -0
- package/studio/server/introspect/anatomy/env-fields.ts +66 -0
- package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
- package/studio/server/introspect/anatomy/source.ts +181 -0
- package/studio/server/introspect/anatomy/views/routes.ts +114 -0
- package/studio/server/introspect/anatomy/views.ts +53 -0
- package/studio/server/introspect/anatomy-extras.test.ts +106 -35
- package/studio/server/introspect/anatomy-extras.ts +7 -726
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +52 -28
- package/studio/server/introspect/bundle.ts +15 -9
- package/studio/server/introspect/canonical-schema.test.ts +93 -309
- package/studio/server/introspect/canonical-schema.ts +257 -425
- package/studio/server/introspect/config-preview.test.ts +32 -0
- package/studio/server/introspect/config-preview.ts +119 -0
- package/studio/server/introspect/core-extractor.ts +18 -127
- package/studio/server/introspect/core.ts +1 -2
- package/studio/server/introspect/diff.test.ts +18 -18
- package/studio/server/introspect/diff.ts +44 -90
- package/studio/server/introspect/extractor.ts +23 -116
- package/studio/server/introspect/hash.ts +5 -2
- package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
- package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
- package/studio/server/introspect/overlay.test.ts +26 -54
- package/studio/server/introspect/overlay.ts +10 -37
- package/studio/server/introspect/revision.test.ts +54 -0
- package/studio/server/introspect/revision.ts +49 -0
- package/studio/server/introspect/runtime.test.ts +83 -143
- package/studio/server/introspect/runtime.ts +40 -11
- package/studio/server/introspect/schema-ir-json.test.ts +70 -0
- package/studio/server/introspect/schema-ir-json.ts +151 -0
- package/studio/server/introspect/schema-refs.test.ts +43 -88
- package/studio/server/introspect/schema-refs.ts +14 -49
- package/studio/server/introspect/source-overlay/annotations.ts +14 -0
- package/studio/server/introspect/source-overlay/handlers.ts +161 -0
- package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
- package/studio/server/introspect/source-overlay/project.ts +248 -0
- package/studio/server/introspect/source-overlay/spans.ts +330 -0
- package/studio/server/json.ts +46 -0
- package/studio/server/lifecycle.ts +5 -1
- package/studio/server/sse.test.ts +26 -0
- package/studio/server/sse.ts +4 -1
- package/studio/server/state/baseline.test.ts +223 -7
- package/studio/server/state/baseline.ts +148 -34
- package/studio/server/state/comments.test.ts +66 -1
- package/studio/server/state/comments.ts +173 -10
- package/studio/server/state/context.ts +34 -2
- package/studio/server/state/documents.ts +42 -1
- package/studio/server/state/integrations.ts +27 -1
- package/studio/server/state/layout.test.ts +34 -0
- package/studio/server/state/layout.ts +44 -17
- package/studio/server/state/settings.ts +29 -22
- package/studio/server/state/store.test.ts +122 -0
- package/studio/server/state/store.ts +66 -17
- package/studio/server/state/visibility.ts +22 -11
- package/studio/server/views/model.test.ts +57 -0
- package/studio/server/views/model.ts +66 -0
- package/studio/server/views/runtime.ts +40 -0
- package/studio/server/views/selection-repository.test.ts +31 -0
- package/studio/server/views/selection-repository.ts +60 -0
- package/studio/server/views/session.test.ts +73 -0
- package/studio/server/views/session.ts +166 -0
- package/studio/server/views/target.test.ts +78 -0
- package/studio/server/views/target.ts +222 -0
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +9 -5
- package/studio/server/workspace/catalog.test.ts +17 -0
- package/studio/server/workspace/catalog.ts +43 -0
- package/studio/server/{state → workspace}/create.test.ts +1 -1
- package/studio/server/{state → workspace}/create.ts +1 -1
- package/studio/server/{state → workspace}/git.ts +1 -1
- package/studio/server/workspace/updates.ts +83 -0
- package/studio/server/workspace-state.ts +1 -1
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/README.md +16 -0
- package/studio/shared/contracts/agent.ts +270 -0
- package/studio/shared/contracts/runtime.ts +50 -0
- package/studio/shared/contracts/schema.ts +393 -0
- package/studio/shared/contracts/surface.test.ts +317 -0
- package/studio/shared/contracts/workspace.ts +265 -0
- package/studio/shared/layout.test.ts +116 -0
- package/studio/shared/schema/identity.test.ts +34 -0
- package/studio/shared/schema/identity.ts +68 -0
- package/studio/shared/types.ts +11 -1099
- package/studio/tsconfig.json +1 -1
- package/viewer/dist/main.js +40 -61
- package/.check-workspace.cjs +0 -40
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/elk-api-D2xgMJvi.js +0 -1
- package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
- package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
- package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
- package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
- package/studio/server/state/catalog.ts +0 -117
- package/studio/server/state/instance.ts +0 -280
- package/studio/server/state/updates.ts +0 -63
- package/studio/server/state/views.test.ts +0 -286
- package/studio/server/state/views.ts +0 -535
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared workspace and persisted-state contracts.
|
|
3
|
+
*
|
|
4
|
+
* This module owns the JSON shapes written below `.domain-studio/` and the
|
|
5
|
+
* workspace summaries derived around them. Server stores consume these types;
|
|
6
|
+
* they do not redeclare the persisted state.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { SchemaRevision } from './schema'
|
|
10
|
+
|
|
11
|
+
/** A kernel instance the CLI knows about (a local bookmark or an admin-managed one). */
|
|
12
|
+
export interface InstanceInfo {
|
|
13
|
+
name: string
|
|
14
|
+
url: string
|
|
15
|
+
active: boolean
|
|
16
|
+
kind: 'bookmark' | 'managed'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Global (NOT per-domain) — the CLI's instances + which is active. Source of truth: `astrale instance list`. */
|
|
20
|
+
export interface InstancesState {
|
|
21
|
+
active: string | null
|
|
22
|
+
instances: InstanceInfo[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** What the studio recorded the last time it ran a deploy for this domain. */
|
|
26
|
+
export interface DeployRecord {
|
|
27
|
+
at: string
|
|
28
|
+
/** UI/cache fingerprint recorded by Studio; not a canonical schema revision. */
|
|
29
|
+
renderFingerprint: string
|
|
30
|
+
ok: boolean
|
|
31
|
+
url?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Per-domain deploy/install state (the active instance is global — see InstancesState). */
|
|
35
|
+
export interface InstanceStatus {
|
|
36
|
+
/** the domain's configured deploy target (astrale.config.ts prod.instance) */
|
|
37
|
+
deployTarget: string | null
|
|
38
|
+
/** has a `prod` script → deployable via `pnpm prod` */
|
|
39
|
+
deployable: boolean
|
|
40
|
+
/** GROUND TRUTH — queried from `astrale introspect <origin> --bundle`, not local state.
|
|
41
|
+
* 'unknown' = the instance couldn't be reached/queried (no target, not authed, offline). */
|
|
42
|
+
install: 'installed' | 'not-installed' | 'unknown'
|
|
43
|
+
/** local schema vs the schema actually INSTALLED on the instance (ground truth) */
|
|
44
|
+
drift: 'in-sync' | 'drifted' | 'unknown'
|
|
45
|
+
/** Canonical revisions compared only after local and installed SDK admission. */
|
|
46
|
+
localRevision: SchemaRevision | null
|
|
47
|
+
installedRevision: SchemaRevision | null
|
|
48
|
+
/** the studio's own last deploy — supplementary (service URL / when), not the source of truth */
|
|
49
|
+
lastDeploy: DeployRecord | null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface DeployResult {
|
|
53
|
+
ok: boolean
|
|
54
|
+
url: string | null
|
|
55
|
+
output: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type ThreadRole = 'user' | 'author'
|
|
59
|
+
export type ThreadEntryType = 'text' | 'choice'
|
|
60
|
+
|
|
61
|
+
export interface ThreadEntry {
|
|
62
|
+
id: string
|
|
63
|
+
role: ThreadRole
|
|
64
|
+
type: ThreadEntryType
|
|
65
|
+
text: string
|
|
66
|
+
options?: string[]
|
|
67
|
+
answer?: string | null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type AnchorKind = 'schema' | 'section' | 'file' | 'free'
|
|
71
|
+
|
|
72
|
+
export interface AnchorRef {
|
|
73
|
+
ref: string
|
|
74
|
+
kind: AnchorKind
|
|
75
|
+
file?: string
|
|
76
|
+
startLine?: number
|
|
77
|
+
endLine?: number
|
|
78
|
+
label?: string
|
|
79
|
+
/** Flow-canvas coordinates for section-level canvas comments. */
|
|
80
|
+
x?: number
|
|
81
|
+
y?: number
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface Comment {
|
|
85
|
+
id: string
|
|
86
|
+
/** annotate-compatible: array of string excerpts */
|
|
87
|
+
anchors: string[]
|
|
88
|
+
/** studio-only, index-aligned to `anchors` */
|
|
89
|
+
anchorRefs: AnchorRef[]
|
|
90
|
+
status: 'open' | 'closed'
|
|
91
|
+
closeNote?: string
|
|
92
|
+
thread: ThreadEntry[]
|
|
93
|
+
createdAt: string
|
|
94
|
+
/** derived: a thread whose first entry is role:'author' is a question */
|
|
95
|
+
kind: 'comment' | 'question'
|
|
96
|
+
/** set when the anchor ref no longer resolves against the current schema */
|
|
97
|
+
orphaned?: boolean
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface CommentStore {
|
|
101
|
+
/** Historical annotate wire key; contains Studio's render fingerprint. */
|
|
102
|
+
schemaVersion: string
|
|
103
|
+
comments: Comment[]
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface MergeResult {
|
|
107
|
+
merged: number
|
|
108
|
+
closed: number
|
|
109
|
+
unknownIds: string[]
|
|
110
|
+
schemaMismatch: boolean
|
|
111
|
+
pastedSchemaVersion?: string
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type SchemaChangeKind =
|
|
115
|
+
| 'schema-metadata-changed'
|
|
116
|
+
| 'import-added'
|
|
117
|
+
| 'import-removed'
|
|
118
|
+
| 'import-changed'
|
|
119
|
+
| 'class-added'
|
|
120
|
+
| 'class-removed'
|
|
121
|
+
| 'class-contract-changed'
|
|
122
|
+
| 'edge-added'
|
|
123
|
+
| 'edge-removed'
|
|
124
|
+
| 'edge-contract-changed'
|
|
125
|
+
| 'definition-metadata-changed'
|
|
126
|
+
| 'prop-added'
|
|
127
|
+
| 'prop-removed'
|
|
128
|
+
| 'prop-type-changed'
|
|
129
|
+
| 'prop-schema-changed'
|
|
130
|
+
| 'prop-required-changed'
|
|
131
|
+
| 'method-added'
|
|
132
|
+
| 'method-removed'
|
|
133
|
+
| 'method-signature-changed'
|
|
134
|
+
| 'method-metadata-changed'
|
|
135
|
+
| 'function-added'
|
|
136
|
+
| 'function-removed'
|
|
137
|
+
| 'function-signature-changed'
|
|
138
|
+
| 'function-metadata-changed'
|
|
139
|
+
| 'view-added'
|
|
140
|
+
| 'view-removed'
|
|
141
|
+
| 'view-changed'
|
|
142
|
+
| 'view-metadata-changed'
|
|
143
|
+
| 'policy-added'
|
|
144
|
+
| 'policy-removed'
|
|
145
|
+
| 'policy-changed'
|
|
146
|
+
| 'dependency-added'
|
|
147
|
+
| 'dependency-removed'
|
|
148
|
+
| 'dependency-changed'
|
|
149
|
+
| 'core-changed'
|
|
150
|
+
|
|
151
|
+
export interface SchemaChange {
|
|
152
|
+
kind: SchemaChangeKind
|
|
153
|
+
target: string
|
|
154
|
+
detail?: string
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface FileChange {
|
|
158
|
+
file: string
|
|
159
|
+
status: 'added' | 'modified' | 'removed'
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface ChangeSet {
|
|
163
|
+
source: 'baseline' | 'git'
|
|
164
|
+
hasGit: boolean
|
|
165
|
+
hasBaseline: boolean
|
|
166
|
+
schemaChanges: SchemaChange[]
|
|
167
|
+
fileChanges: FileChange[]
|
|
168
|
+
schemaDiffText?: string
|
|
169
|
+
/** Describes Studio-observed structure only; never a Runtime migration verdict. */
|
|
170
|
+
structuralStatus: 'none' | 'changed'
|
|
171
|
+
baselineRevision?: SchemaRevision
|
|
172
|
+
currentRevision?: SchemaRevision
|
|
173
|
+
baselineCapturedAt?: string
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface ContextItem {
|
|
177
|
+
id: string
|
|
178
|
+
bucket: 'user' | 'auto'
|
|
179
|
+
title: string
|
|
180
|
+
body: string
|
|
181
|
+
source?: string
|
|
182
|
+
updatedAt: string
|
|
183
|
+
/** auto items: included in the copy payload only when true */
|
|
184
|
+
includeInHandoff?: boolean
|
|
185
|
+
freshness?: string
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface ContextStore {
|
|
189
|
+
user: ContextItem[]
|
|
190
|
+
auto: ContextItem[]
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** A document the user drops in as context for the AI agent. */
|
|
194
|
+
export interface DocMeta {
|
|
195
|
+
id: string
|
|
196
|
+
name: string
|
|
197
|
+
type: string
|
|
198
|
+
size: number
|
|
199
|
+
addedAt: string
|
|
200
|
+
updatedAt?: string
|
|
201
|
+
/** relative path under the dotted folder (server-side) */
|
|
202
|
+
stored: string
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface Integration {
|
|
206
|
+
id: string
|
|
207
|
+
name: string
|
|
208
|
+
kind: string
|
|
209
|
+
status: 'planned' | 'active' | 'deprecated' | string
|
|
210
|
+
notes?: string
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface IntegrationsState {
|
|
214
|
+
integrations: Integration[]
|
|
215
|
+
detectedSubfolders: string[]
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** A domain in the catalog — local to this workspace, a faked external service, or the kernel. */
|
|
219
|
+
export interface DomainCatalogEntry {
|
|
220
|
+
origin: string
|
|
221
|
+
name: string
|
|
222
|
+
kind: 'kernel' | 'local' | 'external'
|
|
223
|
+
description: string
|
|
224
|
+
/** raw lucide-style SVG icon (stroke="currentColor") */
|
|
225
|
+
icon: string
|
|
226
|
+
/** kernel is always present + required */
|
|
227
|
+
required?: boolean
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface DomainSummary {
|
|
231
|
+
id: string
|
|
232
|
+
origin: string
|
|
233
|
+
path: string
|
|
234
|
+
schemaDir: string
|
|
235
|
+
depsInstalled: boolean
|
|
236
|
+
hasGit: boolean
|
|
237
|
+
configFile: string
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface CopyPayload {
|
|
241
|
+
markdown: string
|
|
242
|
+
openComments: number
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface NodePosition {
|
|
246
|
+
x: number
|
|
247
|
+
y: number
|
|
248
|
+
/** persisted size — only expanded module containers carry one. */
|
|
249
|
+
w?: number
|
|
250
|
+
h?: number
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Persisted manual graph layout. This is the sole authority for its JSON shape. */
|
|
254
|
+
export interface LayoutState {
|
|
255
|
+
renderFingerprint?: string
|
|
256
|
+
positions: Record<string, NodePosition>
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Persisted per-domain canvas visibility. This is the sole authority for its JSON shape. */
|
|
260
|
+
export interface VisibilityState {
|
|
261
|
+
/** Refs hidden on the canvas: `class.X` | `edge.X` | `domain.<origin>`. */
|
|
262
|
+
hidden: Record<string, true>
|
|
263
|
+
/** Whether local Class inheritance edges are rendered. */
|
|
264
|
+
showInheritedEdges: boolean
|
|
265
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test'
|
|
2
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs'
|
|
3
|
+
import { dirname, join, relative, resolve } from 'node:path'
|
|
4
|
+
|
|
5
|
+
const STUDIO_ROOT = resolve(import.meta.dir, '..')
|
|
6
|
+
const CLIENT_ROOT = join(STUDIO_ROOT, 'client', 'src')
|
|
7
|
+
const SERVER_ROOT = join(STUDIO_ROOT, 'server')
|
|
8
|
+
const SHARED_ROOT = join(STUDIO_ROOT, 'shared')
|
|
9
|
+
const STATE_ROOT = join(SERVER_ROOT, 'state')
|
|
10
|
+
|
|
11
|
+
function productionFiles(dir: string): string[] {
|
|
12
|
+
return readdirSync(dir)
|
|
13
|
+
.flatMap((entry) => {
|
|
14
|
+
const path = join(dir, entry)
|
|
15
|
+
if (statSync(path).isDirectory()) return productionFiles(path)
|
|
16
|
+
if (!/\.(?:ts|tsx)$/.test(path) || /\.test\.(?:ts|tsx)$/.test(path)) return []
|
|
17
|
+
return [path]
|
|
18
|
+
})
|
|
19
|
+
.sort()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const files = [
|
|
23
|
+
...productionFiles(CLIENT_ROOT),
|
|
24
|
+
...productionFiles(SERVER_ROOT),
|
|
25
|
+
...productionFiles(SHARED_ROOT),
|
|
26
|
+
]
|
|
27
|
+
const fileSet = new Set(files)
|
|
28
|
+
|
|
29
|
+
function resolveLocalImport(file: string, specifier: string): string | null {
|
|
30
|
+
const target = specifier.startsWith('@/')
|
|
31
|
+
? join(CLIENT_ROOT, specifier.slice(2))
|
|
32
|
+
: specifier.startsWith('@shared/')
|
|
33
|
+
? join(SHARED_ROOT, specifier.slice('@shared/'.length))
|
|
34
|
+
: specifier.startsWith('.')
|
|
35
|
+
? resolve(dirname(file), specifier)
|
|
36
|
+
: null
|
|
37
|
+
if (!target) return null
|
|
38
|
+
for (const candidate of [
|
|
39
|
+
target,
|
|
40
|
+
`${target}.ts`,
|
|
41
|
+
`${target}.tsx`,
|
|
42
|
+
join(target, 'index.ts'),
|
|
43
|
+
join(target, 'index.tsx'),
|
|
44
|
+
]) {
|
|
45
|
+
if (fileSet.has(candidate)) return candidate
|
|
46
|
+
}
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function imports(file: string): string[] {
|
|
51
|
+
const source = readFileSync(file, 'utf8')
|
|
52
|
+
const found: string[] = []
|
|
53
|
+
const pattern = /(?:from\s+|import\s*(?:\(\s*)?)['"]([^'"]+)['"]\s*\)?|import\s+['"]([^'"]+)['"]/g
|
|
54
|
+
for (const match of source.matchAll(pattern)) {
|
|
55
|
+
const target = resolveLocalImport(file, match[1] ?? match[2])
|
|
56
|
+
if (target) found.push(target)
|
|
57
|
+
}
|
|
58
|
+
return found
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const studioPath = (file: string) => relative(STUDIO_ROOT, file).replaceAll('\\', '/')
|
|
62
|
+
|
|
63
|
+
test('Studio production modules form an acyclic dependency graph', () => {
|
|
64
|
+
const graph = new Map(files.map((file) => [file, imports(file)]))
|
|
65
|
+
const visiting = new Set<string>()
|
|
66
|
+
const visited = new Set<string>()
|
|
67
|
+
const stack: string[] = []
|
|
68
|
+
const cycles: string[][] = []
|
|
69
|
+
|
|
70
|
+
const visit = (file: string) => {
|
|
71
|
+
if (visiting.has(file)) {
|
|
72
|
+
const start = stack.indexOf(file)
|
|
73
|
+
cycles.push([...stack.slice(start), file].map(studioPath))
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
if (visited.has(file)) return
|
|
77
|
+
visiting.add(file)
|
|
78
|
+
stack.push(file)
|
|
79
|
+
for (const dependency of graph.get(file) ?? []) visit(dependency)
|
|
80
|
+
stack.pop()
|
|
81
|
+
visiting.delete(file)
|
|
82
|
+
visited.add(file)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const file of files) visit(file)
|
|
86
|
+
expect(cycles).toEqual([])
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('production boundaries keep client/shared out of server and shared out of client', () => {
|
|
90
|
+
const violations = files.flatMap((file) =>
|
|
91
|
+
imports(file)
|
|
92
|
+
.filter(
|
|
93
|
+
(dependency) =>
|
|
94
|
+
(dependency.startsWith(SERVER_ROOT) &&
|
|
95
|
+
(file.startsWith(CLIENT_ROOT) || file.startsWith(SHARED_ROOT))) ||
|
|
96
|
+
(file.startsWith(SHARED_ROOT) && dependency.startsWith(CLIENT_ROOT)),
|
|
97
|
+
)
|
|
98
|
+
.map((dependency) => `${studioPath(file)} -> ${studioPath(dependency)}`),
|
|
99
|
+
)
|
|
100
|
+
expect(violations).toEqual([])
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('state repositories do not depend on workflow modules', () => {
|
|
104
|
+
const workflowRoots = ['api', 'environment', 'handoff', 'instances', 'views', 'workspace'].map(
|
|
105
|
+
(directory) => join(SERVER_ROOT, directory),
|
|
106
|
+
)
|
|
107
|
+
const edges = files
|
|
108
|
+
.filter((file) => file.startsWith(STATE_ROOT))
|
|
109
|
+
.flatMap((file) =>
|
|
110
|
+
imports(file)
|
|
111
|
+
.filter((dependency) => workflowRoots.some((root) => dependency.startsWith(root)))
|
|
112
|
+
.map((dependency) => `${studioPath(file)} -> ${studioPath(dependency)}`),
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
expect(edges).toEqual([])
|
|
116
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
classRefKey,
|
|
5
|
+
isIrClassRef,
|
|
6
|
+
isIrSchemaRef,
|
|
7
|
+
parseClassRefKey,
|
|
8
|
+
parseSchemaRefKey,
|
|
9
|
+
schemaRefKey,
|
|
10
|
+
} from './identity'
|
|
11
|
+
|
|
12
|
+
describe('schema identity', () => {
|
|
13
|
+
test('round-trips exact Class identity', () => {
|
|
14
|
+
const ref = { origin: 'docs.example.dev', kind: 'class' as const, name: 'Document' }
|
|
15
|
+
expect(classRefKey(ref)).toBe('docs.example.dev:class.Document')
|
|
16
|
+
expect(parseClassRefKey(classRefKey(ref))).toEqual(ref)
|
|
17
|
+
expect(isIrClassRef(ref)).toBe(true)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('preserves all supported schema reference kinds', () => {
|
|
21
|
+
const ref = { origin: 'docs.example.dev', kind: 'function' as const, name: 'search' }
|
|
22
|
+
expect(schemaRefKey(ref)).toBe('docs.example.dev:function.search')
|
|
23
|
+
expect(parseSchemaRefKey(schemaRefKey(ref))).toEqual(ref)
|
|
24
|
+
expect(isIrSchemaRef(ref)).toBe(true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('rejects removed Interface coordinates and malformed keys', () => {
|
|
28
|
+
expect(isIrSchemaRef({ origin: 'docs.example.dev', kind: 'interface', name: 'Named' })).toBe(
|
|
29
|
+
false,
|
|
30
|
+
)
|
|
31
|
+
expect(parseSchemaRefKey('docs.example.dev:interface.Named')).toBeUndefined()
|
|
32
|
+
expect(parseClassRefKey('docs.example.dev:function.search')).toBeUndefined()
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical Studio identity for DomainSchema references.
|
|
3
|
+
*
|
|
4
|
+
* These helpers validate and encode only the structural wire coordinate. SDK
|
|
5
|
+
* admission remains the authority for whether a reference is semantically valid.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const IR_SCHEMA_REF_KINDS = ['class', 'function', 'policy', 'view', 'core'] as const
|
|
9
|
+
|
|
10
|
+
export type IrSchemaRefKind = (typeof IR_SCHEMA_REF_KINDS)[number]
|
|
11
|
+
|
|
12
|
+
/** Exact structural coordinate embedded in a canonical DomainSchema V1 root. */
|
|
13
|
+
export interface IrSchemaRef {
|
|
14
|
+
origin: string
|
|
15
|
+
kind: IrSchemaRefKind
|
|
16
|
+
name: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Canonical DSL key for a schema member: `origin:kind.name`. */
|
|
20
|
+
export type IrSchemaKey = `${string}:${IrSchemaRefKind}.${string}`
|
|
21
|
+
|
|
22
|
+
export type IrClassRef = Omit<IrSchemaRef, 'kind'> & { kind: 'class' }
|
|
23
|
+
|
|
24
|
+
export type IrClassKey = `${string}:class.${string}`
|
|
25
|
+
|
|
26
|
+
const schemaKinds = new Set<string>(IR_SCHEMA_REF_KINDS)
|
|
27
|
+
const schemaKeyPattern = /^(.+):(class|function|policy|view|core)\.(.+)$/
|
|
28
|
+
|
|
29
|
+
/** Structural guard only; it deliberately does not perform SDK admission. */
|
|
30
|
+
export function isIrSchemaRef(value: unknown): value is IrSchemaRef {
|
|
31
|
+
if (!value || typeof value !== 'object') return false
|
|
32
|
+
const ref = value as Partial<IrSchemaRef>
|
|
33
|
+
return (
|
|
34
|
+
typeof ref.origin === 'string' &&
|
|
35
|
+
typeof ref.name === 'string' &&
|
|
36
|
+
typeof ref.kind === 'string' &&
|
|
37
|
+
schemaKinds.has(ref.kind)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isIrClassRef(value: unknown): value is IrClassRef {
|
|
42
|
+
return isIrSchemaRef(value) && value.kind === 'class'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function schemaRefKey(ref: IrSchemaRef): IrSchemaKey {
|
|
46
|
+
return `${ref.origin}:${ref.kind}.${ref.name}`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function classRefKey(ref: IrClassRef): IrClassKey {
|
|
50
|
+
return `${ref.origin}:${ref.kind}.${ref.name}`
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Parse a canonical key without asserting that the referenced member exists. */
|
|
54
|
+
export function parseSchemaRefKey(value: unknown): IrSchemaRef | undefined {
|
|
55
|
+
if (typeof value !== 'string') return undefined
|
|
56
|
+
const match = schemaKeyPattern.exec(value)
|
|
57
|
+
if (!match) return undefined
|
|
58
|
+
return {
|
|
59
|
+
origin: match[1],
|
|
60
|
+
kind: match[2] as IrSchemaRefKind,
|
|
61
|
+
name: match[3],
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function parseClassRefKey(value: unknown): IrClassRef | undefined {
|
|
66
|
+
const ref = parseSchemaRefKey(value)
|
|
67
|
+
return ref && isIrClassRef(ref) ? ref : undefined
|
|
68
|
+
}
|