@astrale-os/cli 1.0.0-beta.32 → 1.0.0-beta.43
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/CHANGELOG.md +928 -0
- package/README.md +53 -43
- package/THIRD-PARTY-NOTICES.md +37 -1
- package/dist/astrale.js +349631 -83669
- package/dist/public/connect-core.js +16 -47
- package/dist/public/keys/index.js +1 -1
- package/dist/types/admin/contract.d.ts +11 -0
- package/dist/types/admin/graph/index.d.ts +1 -0
- package/dist/types/admin/graph/nodes.d.ts +12 -0
- package/dist/types/admin/instance/client.d.ts +2 -0
- package/dist/types/connection/lifetime.d.ts +1 -1
- package/dist/types/errors.d.ts +3 -0
- package/dist/types/lib/proc.d.ts +1 -0
- package/dist/types/lib/update.d.ts +15 -7
- package/package.json +8 -6
- package/studio/client/dist/assets/index-5C1uT6ML.css +2 -0
- package/studio/client/dist/assets/index-C4kNlvwF.js +80 -0
- package/studio/client/dist/assets/schema-studio-BR9d0faB.js +8 -0
- package/studio/client/dist/index.html +13 -2
- package/studio/package.json +2 -1
- package/studio/server/agent/ask.test.ts +7 -1
- package/studio/server/agent/bridge/grant.ts +15 -3
- package/studio/server/agent/prompts/system.test.ts +5 -0
- package/studio/server/agent/prompts/system.ts +19 -4
- package/studio/server/agent/routes.test.ts +39 -1
- package/studio/server/agent/routes.ts +3 -0
- package/studio/server/agent/run/coordinator.test.ts +7 -1
- package/studio/server/agent/run/preparation.ts +1 -0
- package/studio/server/agent/run/transcript.test.ts +47 -2
- package/studio/server/agent/run/transcript.ts +32 -3
- package/studio/server/api/documents.test.ts +31 -0
- package/studio/server/api/documents.ts +35 -1
- package/studio/server/api-agent-loadout.test.ts +7 -1
- package/studio/server/api.test.ts +7 -1
- package/studio/server/cache.ts +4 -4
- package/studio/server/detect.ts +9 -12
- package/studio/server/domain.test.ts +83 -3
- package/studio/server/domain.ts +205 -27
- package/studio/server/handoff/service.ts +1 -1
- package/studio/server/index.ts +5 -8
- package/studio/server/introspect/extractor.ts +111 -17
- package/studio/server/introspect/overlay-tsmorph.test.ts +9 -9
- package/studio/server/introspect/overlay.ts +1 -1
- package/studio/server/introspect/runtime.ts +9 -1
- package/studio/server/introspect/source-overlay/spans.ts +2 -5
- package/studio/server/lifecycle.ts +1 -1
- package/studio/server/state/baseline.test.ts +14 -0
- package/studio/server/state/baseline.ts +16 -2
- package/studio/server/watch.test.ts +2 -1
- package/studio/server/watch.ts +5 -2
- package/studio/server/workspace/create.ts +9 -8
- package/studio/server/workspace-state.ts +4 -6
- package/studio/server/workspace-watch.ts +33 -22
- package/studio/shared/contracts/agent.ts +3 -0
- package/viewer/dist/main.js +12 -12
- package/src/__tests__/fixtures/publication.ts +0 -20
- package/src/admin/.spec/api.d.ts +0 -3
- package/src/admin/.spec/architecture.md +0 -22
- package/src/admin/.spec/icon.svg +0 -3
- package/src/admin/.spec/layout.ts +0 -6
- package/src/admin/__tests__/fixture.ts +0 -25
- package/src/admin/catalog/.spec/api.d.ts +0 -63
- package/src/admin/catalog/.spec/architecture.md +0 -7
- package/src/admin/catalog/.spec/icon.svg +0 -3
- package/src/admin/catalog/.spec/layout.ts +0 -6
- package/src/admin/catalog/__tests__/client.test.ts +0 -245
- package/src/admin/catalog/client.ts +0 -195
- package/src/admin/catalog/index.ts +0 -13
- package/src/admin/catalog/model.ts +0 -41
- package/src/admin/catalog/tsconfig.json +0 -8
- package/src/admin/contract.ts +0 -47
- package/src/admin/graph/.spec/api.d.ts +0 -22
- package/src/admin/graph/.spec/architecture.md +0 -5
- package/src/admin/graph/.spec/icon.svg +0 -3
- package/src/admin/graph/.spec/layout.ts +0 -3
- package/src/admin/graph/index.ts +0 -6
- package/src/admin/graph/nodes.ts +0 -56
- package/src/admin/index.ts +0 -2
- package/src/admin/instance/.spec/api.d.ts +0 -62
- package/src/admin/instance/.spec/architecture.md +0 -10
- package/src/admin/instance/.spec/icon.svg +0 -3
- package/src/admin/instance/.spec/layout.ts +0 -6
- package/src/admin/instance/__tests__/client.test.ts +0 -273
- package/src/admin/instance/client.ts +0 -191
- package/src/admin/instance/index.ts +0 -15
- package/src/admin/instance/model.ts +0 -59
- package/src/admin/instance/tsconfig.json +0 -8
- package/src/commands/__tests__/admin-instance.test.ts +0 -91
- package/src/commands/__tests__/auth-login.test.ts +0 -231
- package/src/commands/__tests__/auth-token.test.ts +0 -223
- package/src/commands/__tests__/call-describe.test.ts +0 -80
- package/src/commands/__tests__/call.test.ts +0 -63
- package/src/commands/__tests__/domain-install-operation.test.ts +0 -145
- package/src/commands/__tests__/domain-install-owned.test.ts +0 -191
- package/src/commands/__tests__/domain-list.test.ts +0 -133
- package/src/commands/__tests__/domain-uninstall.test.ts +0 -53
- package/src/commands/__tests__/install-direct.test.ts +0 -128
- package/src/commands/__tests__/install-identity-override.test.ts +0 -76
- package/src/commands/__tests__/instance-bookmark.test.ts +0 -166
- package/src/commands/__tests__/instance-list-admin.test.ts +0 -26
- package/src/commands/__tests__/instance-list-rows.test.ts +0 -64
- package/src/commands/__tests__/instance-status.test.ts +0 -139
- package/src/commands/__tests__/instance-use.test.ts +0 -67
- package/src/commands/__tests__/introspect-parse.test.ts +0 -100
- package/src/commands/__tests__/logs.test.ts +0 -345
- package/src/commands/__tests__/read-commands.test.ts +0 -377
- package/src/commands/__tests__/setup-plan.test.ts +0 -61
- package/src/commands/__tests__/studio-descriptor.test.ts +0 -22
- package/src/commands/__tests__/token-ttl.test.ts +0 -66
- package/src/commands/__tests__/update.test.ts +0 -95
- package/src/commands/__tests__/view-build.test.ts +0 -58
- package/src/commands/__tests__/view.test.ts +0 -197
- package/src/commands/admin/status.ts +0 -61
- package/src/commands/admin/use.ts +0 -100
- package/src/commands/auth/login.ts +0 -82
- package/src/commands/auth/logout.ts +0 -53
- package/src/commands/auth/status.ts +0 -86
- package/src/commands/auth/token.ts +0 -174
- package/src/commands/browser.ts +0 -236
- package/src/commands/call-describe.ts +0 -123
- package/src/commands/call.ts +0 -230
- package/src/commands/domain/install.ts +0 -575
- package/src/commands/domain/list.ts +0 -155
- package/src/commands/domain/publish.ts +0 -136
- package/src/commands/domain/uninstall.ts +0 -128
- package/src/commands/get.ts +0 -69
- package/src/commands/identity/__tests__/register.test.ts +0 -93
- package/src/commands/identity/create.ts +0 -35
- package/src/commands/identity/delete.ts +0 -24
- package/src/commands/identity/export.ts +0 -46
- package/src/commands/identity/import.ts +0 -61
- package/src/commands/identity/list.ts +0 -56
- package/src/commands/identity/register.ts +0 -195
- package/src/commands/identity/sync.ts +0 -38
- package/src/commands/identity/unsync.ts +0 -34
- package/src/commands/identity/use.ts +0 -24
- package/src/commands/identity/whoami.ts +0 -34
- package/src/commands/idp/add.ts +0 -150
- package/src/commands/idp/list.ts +0 -57
- package/src/commands/idp/refresh.ts +0 -38
- package/src/commands/idp/remove.ts +0 -36
- package/src/commands/idp/show.ts +0 -29
- package/src/commands/instance/active.ts +0 -73
- package/src/commands/instance/bookmark.ts +0 -101
- package/src/commands/instance/create.ts +0 -61
- package/src/commands/instance/delete.ts +0 -69
- package/src/commands/instance/forget.ts +0 -26
- package/src/commands/instance/list.ts +0 -197
- package/src/commands/instance/status.ts +0 -92
- package/src/commands/instance/use.ts +0 -263
- package/src/commands/introspect.ts +0 -129
- package/src/commands/logs.ts +0 -371
- package/src/commands/mutate.ts +0 -122
- package/src/commands/query.ts +0 -142
- package/src/commands/session/analyze.ts +0 -72
- package/src/commands/session/list.ts +0 -36
- package/src/commands/setup.ts +0 -54
- package/src/commands/status.ts +0 -60
- package/src/commands/studio.ts +0 -434
- package/src/commands/token.ts +0 -121
- package/src/commands/ui/__tests__/commands.test.ts +0 -152
- package/src/commands/ui/add.ts +0 -51
- package/src/commands/ui/doctor.ts +0 -21
- package/src/commands/ui/init.ts +0 -38
- package/src/commands/ui/list.ts +0 -26
- package/src/commands/ui/preset-apply.ts +0 -19
- package/src/commands/ui/preset-list.ts +0 -12
- package/src/commands/ui/shared.ts +0 -25
- package/src/commands/update.ts +0 -356
- package/src/commands/use.ts +0 -86
- package/src/commands/view-serve.ts +0 -26
- package/src/commands/view.ts +0 -658
- package/src/connect-core.test.ts +0 -38
- package/src/connect-core.ts +0 -42
- package/src/connection/.spec/api.d.ts +0 -110
- package/src/connection/.spec/architecture.md +0 -58
- package/src/connection/.spec/capabilities/connection.ts +0 -13
- package/src/connection/.spec/examples/call.ts +0 -7
- package/src/connection/.spec/flows/command.ts +0 -20
- package/src/connection/.spec/flows/session.ts +0 -62
- package/src/connection/.spec/laws/connection.ts +0 -213
- package/src/connection/.spec/layout.ts +0 -22
- package/src/connection/__tests__/auth.test.ts +0 -129
- package/src/connection/__tests__/ca-fetch.test.ts +0 -60
- package/src/connection/__tests__/call.test.ts +0 -17
- package/src/connection/__tests__/credential.test.ts +0 -254
- package/src/connection/__tests__/errors.test.ts +0 -577
- package/src/connection/__tests__/exchange.test.ts +0 -404
- package/src/connection/__tests__/failure-fixtures.ts +0 -39
- package/src/connection/__tests__/failure-safety.test.ts +0 -75
- package/src/connection/__tests__/fixtures/localhost-cert.pem +0 -19
- package/src/connection/__tests__/fixtures/localhost-key.base64 +0 -1
- package/src/connection/__tests__/managed.test.ts +0 -39
- package/src/connection/__tests__/reasons.test.ts +0 -78
- package/src/connection/__tests__/self.test.ts +0 -71
- package/src/connection/__tests__/session.test.ts +0 -144
- package/src/connection/__tests__/target.test.ts +0 -95
- package/src/connection/auth.ts +0 -265
- package/src/connection/call.ts +0 -7
- package/src/connection/command.ts +0 -67
- package/src/connection/credential.ts +0 -138
- package/src/connection/errors.ts +0 -1
- package/src/connection/exchange.ts +0 -394
- package/src/connection/failure/classify.ts +0 -110
- package/src/connection/failure/index.ts +0 -18
- package/src/connection/failure/model.ts +0 -28
- package/src/connection/failure/render.ts +0 -116
- package/src/connection/index.ts +0 -8
- package/src/connection/lifetime.ts +0 -25
- package/src/connection/reasons.ts +0 -209
- package/src/connection/self.ts +0 -138
- package/src/connection/session.ts +0 -203
- package/src/connection/target.ts +0 -112
- package/src/connection/tsconfig.json +0 -6
- package/src/errors.ts +0 -66
- package/src/graph/.spec/api.d.ts +0 -41
- package/src/graph/.spec/laws/documents.ts +0 -24
- package/src/graph/.spec/laws/projection.ts +0 -13
- package/src/graph/.spec/layout.ts +0 -14
- package/src/graph/__tests__/mutation.test.ts +0 -51
- package/src/graph/__tests__/projection.test.ts +0 -22
- package/src/graph/__tests__/query.test.ts +0 -180
- package/src/graph/class.ts +0 -30
- package/src/graph/index.ts +0 -4
- package/src/graph/mutation.ts +0 -46
- package/src/graph/projection.ts +0 -21
- package/src/graph/query.ts +0 -95
- package/src/graph/tsconfig.json +0 -6
- package/src/identity/.history/ard/bootstrap-root-transfer.md +0 -57
- package/src/identity/.history/ard/domain-mediated-registration.md +0 -36
- package/src/identity/.spec/api.d.ts +0 -124
- package/src/identity/.spec/architecture.md +0 -33
- package/src/identity/.spec/capabilities/identity.ts +0 -7
- package/src/identity/.spec/flows/bootstrap-root.ts +0 -79
- package/src/identity/.spec/flows/domain-mediated-registration.ts +0 -51
- package/src/identity/.spec/flows/import.ts +0 -29
- package/src/identity/.spec/laws/identity.ts +0 -56
- package/src/identity/.spec/layout.ts +0 -13
- package/src/identity/__tests__/fixtures/registry-journey.ts +0 -65
- package/src/identity/__tests__/registration.test.ts +0 -64
- package/src/identity/__tests__/registry.test.ts +0 -74
- package/src/identity/__tests__/transfer.test.ts +0 -198
- package/src/identity/index.ts +0 -23
- package/src/identity/registration.ts +0 -72
- package/src/identity/registry.ts +0 -181
- package/src/identity/transfer.ts +0 -187
- package/src/identity/tsconfig.json +0 -6
- package/src/index.ts +0 -1
- package/src/keys/.spec/api.d.ts +0 -74
- package/src/keys/.spec/architecture.md +0 -13
- package/src/keys/.spec/laws/keys.ts +0 -43
- package/src/keys/.spec/layout.ts +0 -6
- package/src/keys/__tests__/algorithm.test.ts +0 -39
- package/src/keys/__tests__/keys.test.ts +0 -172
- package/src/keys/algorithm.ts +0 -33
- package/src/keys/credential.ts +0 -113
- package/src/keys/index.ts +0 -14
- package/src/keys/pair.ts +0 -219
- package/src/keys/tsconfig.json +0 -6
- package/src/lib/__tests__/admin-target.test.ts +0 -184
- package/src/lib/__tests__/binary.test.ts +0 -70
- package/src/lib/__tests__/browser-retention.test.ts +0 -212
- package/src/lib/__tests__/command-dx.test.ts +0 -102
- package/src/lib/__tests__/concurrency.test.ts +0 -62
- package/src/lib/__tests__/config.test.ts +0 -81
- package/src/lib/__tests__/design.test.ts +0 -99
- package/src/lib/__tests__/domain-publication.test.ts +0 -138
- package/src/lib/__tests__/format.test.ts +0 -22
- package/src/lib/__tests__/idp-session.driver.ts +0 -60
- package/src/lib/__tests__/idp-session.test.ts +0 -404
- package/src/lib/__tests__/idp.test.ts +0 -415
- package/src/lib/__tests__/instance-candidates.test.ts +0 -146
- package/src/lib/__tests__/instance-target.test.ts +0 -213
- package/src/lib/__tests__/instance.test.ts +0 -192
- package/src/lib/__tests__/local-status.test.ts +0 -202
- package/src/lib/__tests__/log-errors.test.ts +0 -64
- package/src/lib/__tests__/log.test.ts +0 -31
- package/src/lib/__tests__/meta.test.ts +0 -55
- package/src/lib/__tests__/output.test.ts +0 -162
- package/src/lib/__tests__/panel.test.ts +0 -40
- package/src/lib/__tests__/port.test.ts +0 -44
- package/src/lib/__tests__/prompt.test.ts +0 -25
- package/src/lib/__tests__/sdk-deps.test.ts +0 -68
- package/src/lib/__tests__/self.test.ts +0 -50
- package/src/lib/__tests__/skills.test.ts +0 -834
- package/src/lib/__tests__/studio-server-deps.test.ts +0 -111
- package/src/lib/__tests__/table.test.ts +0 -53
- package/src/lib/__tests__/update.test.ts +0 -511
- package/src/lib/__tests__/use-target.test.ts +0 -56
- package/src/lib/__tests__/validation.test.ts +0 -34
- package/src/lib/__tests__/view-assets.test.ts +0 -171
- package/src/lib/__tests__/view-external-open-intent.test.ts +0 -150
- package/src/lib/__tests__/view-external-open-origins.test.ts +0 -27
- package/src/lib/__tests__/view-open-intent.test.ts +0 -280
- package/src/lib/__tests__/view-port-allocation.test.ts +0 -82
- package/src/lib/__tests__/view-server.test.ts +0 -91
- package/src/lib/__tests__/view-session.test.ts +0 -100
- package/src/lib/__tests__/view-snapshot.test.ts +0 -77
- package/src/lib/admin-domain.ts +0 -43
- package/src/lib/admin-instance.ts +0 -56
- package/src/lib/admin-target.ts +0 -290
- package/src/lib/binary.ts +0 -127
- package/src/lib/browser-retention.ts +0 -210
- package/src/lib/browser.ts +0 -150
- package/src/lib/ca-fetch.ts +0 -133
- package/src/lib/command-dx.ts +0 -191
- package/src/lib/concurrency.ts +0 -31
- package/src/lib/config.ts +0 -57
- package/src/lib/credential-lifetime.ts +0 -24
- package/src/lib/domain-publication.ts +0 -104
- package/src/lib/failure-debug.ts +0 -26
- package/src/lib/format.ts +0 -4
- package/src/lib/idp-session.ts +0 -156
- package/src/lib/idp.ts +0 -926
- package/src/lib/instance-candidates.ts +0 -49
- package/src/lib/instance-target.ts +0 -197
- package/src/lib/instance.ts +0 -468
- package/src/lib/invocation.ts +0 -11
- package/src/lib/local-status.ts +0 -152
- package/src/lib/log.ts +0 -143
- package/src/lib/login-flow.ts +0 -201
- package/src/lib/meta.ts +0 -90
- package/src/lib/output.ts +0 -238
- package/src/lib/panel.ts +0 -61
- package/src/lib/port.ts +0 -41
- package/src/lib/proc.ts +0 -87
- package/src/lib/prompt.ts +0 -136
- package/src/lib/provision-instance.ts +0 -139
- package/src/lib/sdk-deps.ts +0 -104
- package/src/lib/self.ts +0 -22
- package/src/lib/skills/lock.ts +0 -117
- package/src/lib/skills/sync.ts +0 -878
- package/src/lib/skills.ts +0 -120
- package/src/lib/table.ts +0 -62
- package/src/lib/update.ts +0 -568
- package/src/lib/use-target.ts +0 -24
- package/src/lib/validation.ts +0 -59
- package/src/lib/view/assets.ts +0 -87
- package/src/lib/view/external-open-intent.ts +0 -41
- package/src/lib/view/external-open-origins.ts +0 -37
- package/src/lib/view/host-capabilities.ts +0 -17
- package/src/lib/view/open-intent.ts +0 -67
- package/src/lib/view/port-allocation.ts +0 -19
- package/src/lib/view/resolve.ts +0 -111
- package/src/lib/view/server.ts +0 -259
- package/src/lib/view/session.ts +0 -154
- package/src/lib/view/snapshot.ts +0 -101
- package/src/paths/.spec/api.d.ts +0 -13
- package/src/paths/.spec/architecture.md +0 -5
- package/src/paths/.spec/layout.ts +0 -3
- package/src/paths/index.ts +0 -13
- package/src/program/.spec/api.d.ts +0 -43
- package/src/program/.spec/architecture.md +0 -18
- package/src/program/.spec/laws/program.ts +0 -29
- package/src/program/.spec/layout.ts +0 -14
- package/src/program/__tests__/program.test.ts +0 -556
- package/src/program/argv.ts +0 -14
- package/src/program/build.ts +0 -205
- package/src/program/command.ts +0 -43
- package/src/program/index.ts +0 -3
- package/src/program/options.ts +0 -41
- package/src/program/registry.ts +0 -64
- package/src/program/tsconfig.json +0 -6
- package/src/setup/__tests__/instance-step.test.ts +0 -256
- package/src/setup/__tests__/util.test.ts +0 -29
- package/src/setup/engine.ts +0 -83
- package/src/setup/render.ts +0 -107
- package/src/setup/steps/admin.ts +0 -93
- package/src/setup/steps/agent-browser.ts +0 -81
- package/src/setup/steps/auth.ts +0 -54
- package/src/setup/steps/domain.ts +0 -68
- package/src/setup/steps/index.ts +0 -18
- package/src/setup/steps/instance.ts +0 -206
- package/src/setup/steps/skills-bridge.ts +0 -70
- package/src/setup/steps/skills.ts +0 -61
- package/src/setup/types.ts +0 -61
- package/src/setup/util.ts +0 -34
- package/src/state/.spec/api.d.ts +0 -152
- package/src/state/.spec/architecture.md +0 -45
- package/src/state/.spec/capabilities/state.ts +0 -7
- package/src/state/.spec/flows/identity-update.ts +0 -22
- package/src/state/.spec/laws/state.ts +0 -73
- package/src/state/.spec/layout.ts +0 -15
- package/src/state/__tests__/exchange-credentials.test.ts +0 -341
- package/src/state/__tests__/files.test.ts +0 -136
- package/src/state/__tests__/fixtures/identity-transition.ts +0 -37
- package/src/state/__tests__/fixtures/session-route-process.ts +0 -93
- package/src/state/__tests__/identities.test.ts +0 -142
- package/src/state/__tests__/paths.test.ts +0 -28
- package/src/state/__tests__/session-routes.test.ts +0 -138
- package/src/state/exchange-credentials.ts +0 -250
- package/src/state/files.ts +0 -170
- package/src/state/identities.ts +0 -229
- package/src/state/index.ts +0 -31
- package/src/state/paths.ts +0 -64
- package/src/state/session-routes.ts +0 -34
- package/src/state/tsconfig.json +0 -6
- package/src/telemetry/__tests__/analyze-log.test.ts +0 -38
- package/src/telemetry/__tests__/gate.test.ts +0 -63
- package/src/telemetry/__tests__/recorder.test.ts +0 -111
- package/src/telemetry/__tests__/redact.test.ts +0 -79
- package/src/telemetry/__tests__/retention.test.ts +0 -267
- package/src/telemetry/__tests__/session.test.ts +0 -166
- package/src/telemetry/__tests__/settings.test.ts +0 -102
- package/src/telemetry/__tests__/store-scan.test.ts +0 -128
- package/src/telemetry/__tests__/trigger.test.ts +0 -78
- package/src/telemetry/adapters/__tests__/claude-code.test.ts +0 -89
- package/src/telemetry/adapters/__tests__/codex.test.ts +0 -138
- package/src/telemetry/adapters/__tests__/index.test.ts +0 -88
- package/src/telemetry/adapters/claude-code.ts +0 -90
- package/src/telemetry/adapters/codex.ts +0 -160
- package/src/telemetry/adapters/index.ts +0 -45
- package/src/telemetry/adapters/types.ts +0 -21
- package/src/telemetry/analyze.ts +0 -249
- package/src/telemetry/gate.ts +0 -79
- package/src/telemetry/recorder.ts +0 -68
- package/src/telemetry/redact.ts +0 -53
- package/src/telemetry/retention.ts +0 -176
- package/src/telemetry/session.ts +0 -94
- package/src/telemetry/settings.ts +0 -79
- package/src/telemetry/store.ts +0 -174
- package/src/telemetry/trigger.ts +0 -107
- package/src/telemetry/types.ts +0 -64
- package/src/test-utils.ts +0 -18
- package/src/ui/.spec/api.d.ts +0 -14
- package/src/ui/.spec/architecture.md +0 -14
- package/src/ui/.spec/laws.ts +0 -50
- package/src/ui/.spec/layout.ts +0 -16
- package/src/ui/__tests__/ui.test.ts +0 -1742
- package/src/ui/index.ts +0 -13
- package/src/ui/lock.ts +0 -89
- package/src/ui/model.ts +0 -83
- package/src/ui/operations.ts +0 -1044
- package/src/ui/project.ts +0 -333
- package/src/ui/release.ts +0 -398
- package/src/ui/runner.ts +0 -18
- package/studio/client/dist/assets/index-BFVFs_8x.js +0 -81
- package/studio/client/dist/assets/index-DuB9iUdu.css +0 -2
- package/studio/client/dist/assets/schema-studio-DH6oEWME.js +0 -8
- package/studio/tsconfig.json +0 -24
- package/viewer/tsconfig.json +0 -13
package/src/commands/logs.ts
DELETED
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
import { Path } from '@astrale-os/sdk/graph/path'
|
|
2
|
-
import { K } from '@astrale-os/sdk/schema'
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
|
|
5
|
-
import type { ConnectionContext, KernelCommandOpts } from '../connection'
|
|
6
|
-
import type { Column, ListProjection } from '../lib/output'
|
|
7
|
-
import type { CommandDefinition } from '../program/index'
|
|
8
|
-
|
|
9
|
-
import { createPathCall, expandSelfInPath, runKernelCommand } from '../connection'
|
|
10
|
-
import { failInput } from '../lib/log'
|
|
11
|
-
import { isMachine, output, presentList } from '../lib/output'
|
|
12
|
-
|
|
13
|
-
const JOURNAL_PATH = Path.project(K.functions.journal.ref).raw
|
|
14
|
-
const DEFAULT_LIMIT = 200
|
|
15
|
-
const FOLLOW_INTERVAL_MS = 2_000
|
|
16
|
-
|
|
17
|
-
type LogsOpts = KernelCommandOpts & {
|
|
18
|
-
since?: string
|
|
19
|
-
until?: string
|
|
20
|
-
topic?: string
|
|
21
|
-
topicPrefix?: string
|
|
22
|
-
principal?: string
|
|
23
|
-
limit?: string
|
|
24
|
-
cursor?: string
|
|
25
|
-
follow?: boolean
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface JournalRecord {
|
|
29
|
-
readonly sequence: number
|
|
30
|
-
readonly timestamp: string
|
|
31
|
-
readonly topic: string
|
|
32
|
-
readonly payload: unknown
|
|
33
|
-
readonly occurredAt?: string
|
|
34
|
-
readonly committedAt?: string
|
|
35
|
-
readonly principal?: string
|
|
36
|
-
readonly correlation?: JournalCorrelation
|
|
37
|
-
readonly correlationId?: string
|
|
38
|
-
readonly causationId?: string
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface JournalCorrelation {
|
|
42
|
-
readonly operationId?: string
|
|
43
|
-
readonly parentOperationId?: string
|
|
44
|
-
readonly invocationId?: string
|
|
45
|
-
readonly rootInvocationId?: string
|
|
46
|
-
readonly parentInvocationId?: string
|
|
47
|
-
readonly traceId?: string
|
|
48
|
-
readonly spanId?: string
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface JournalPage {
|
|
52
|
-
readonly records: readonly JournalRecord[]
|
|
53
|
-
readonly cursor?: string
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface JournalInput {
|
|
57
|
-
readonly topics?: { readonly exact?: readonly string[]; readonly prefixes?: readonly string[] }
|
|
58
|
-
readonly principal?: string
|
|
59
|
-
readonly since?: string
|
|
60
|
-
readonly until?: string
|
|
61
|
-
readonly cursor?: string
|
|
62
|
-
readonly limit: number
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/
|
|
66
|
-
const CURSOR_TOKEN = /^[A-Za-z0-9._:+=/-]{8,}$/
|
|
67
|
-
|
|
68
|
-
/** Map flags to the exact public journal syscall input without legacy glob/sequence lowering. */
|
|
69
|
-
export function buildJournalInput(opts: LogsOpts): JournalInput {
|
|
70
|
-
const exact = nonEmpty(opts.topic)
|
|
71
|
-
const prefix = nonEmpty(opts.topicPrefix)
|
|
72
|
-
const since = timestampFlag('--since', opts.since)
|
|
73
|
-
const until = timestampFlag('--until', opts.until)
|
|
74
|
-
if (since !== undefined && until !== undefined && Date.parse(since) > Date.parse(until)) {
|
|
75
|
-
throw new TypeError('--since must be earlier than or equal to --until')
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
...(exact === undefined && prefix === undefined
|
|
79
|
-
? {}
|
|
80
|
-
: {
|
|
81
|
-
topics: {
|
|
82
|
-
...(exact === undefined ? {} : { exact: [exact] }),
|
|
83
|
-
...(prefix === undefined ? {} : { prefixes: [prefix] }),
|
|
84
|
-
},
|
|
85
|
-
}),
|
|
86
|
-
...(nonEmpty(opts.principal) === undefined ? {} : { principal: opts.principal }),
|
|
87
|
-
...(since === undefined ? {} : { since }),
|
|
88
|
-
...(until === undefined ? {} : { until }),
|
|
89
|
-
...(opts.cursor === undefined ? {} : { cursor: cursorFlag(opts.cursor) }),
|
|
90
|
-
limit: opts.limit === undefined ? DEFAULT_LIMIT : positiveInteger('--limit', opts.limit),
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function timestampFlag(name: string, raw: string | undefined): string | undefined {
|
|
95
|
-
const value = nonEmpty(raw)
|
|
96
|
-
if (value === undefined) return undefined
|
|
97
|
-
if (!ISO_TIMESTAMP.test(value) || Number.isNaN(Date.parse(value))) {
|
|
98
|
-
throw new TypeError(`${name} must be an ISO-8601 timestamp (e.g. 2026-08-19T16:51:10.049Z)`)
|
|
99
|
-
}
|
|
100
|
-
return value
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function cursorFlag(raw: string): string {
|
|
104
|
-
const value = raw.trim()
|
|
105
|
-
if (!CURSOR_TOKEN.test(value)) {
|
|
106
|
-
throw new TypeError('--cursor must be an opaque journal resume token (at least 8 characters)')
|
|
107
|
-
}
|
|
108
|
-
return value
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** Validate the record fields the CLI presentation consumes and retain the opaque cursor. */
|
|
112
|
-
export function acceptJournalPage(input: unknown): JournalPage {
|
|
113
|
-
if (!isRecord(input) || !Array.isArray(input.records)) {
|
|
114
|
-
throw new TypeError('Kernel journal response must contain a records array')
|
|
115
|
-
}
|
|
116
|
-
const records = input.records.map((record, index) => acceptRecord(record, index))
|
|
117
|
-
if (input.cursor !== undefined && typeof input.cursor !== 'string') {
|
|
118
|
-
throw new TypeError('Kernel journal cursor must be text')
|
|
119
|
-
}
|
|
120
|
-
return Object.freeze({
|
|
121
|
-
records: Object.freeze(records),
|
|
122
|
-
...(input.cursor === undefined ? {} : { cursor: input.cursor }),
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async function fetchPage(context: ConnectionContext, opts: LogsOpts): Promise<JournalPage> {
|
|
127
|
-
return acceptJournalPage(
|
|
128
|
-
await context.session.call(createPathCall(JOURNAL_PATH, buildJournalInput(opts))),
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async function runOnce(opts: LogsOpts): Promise<void> {
|
|
133
|
-
await runKernelCommand({
|
|
134
|
-
opts,
|
|
135
|
-
label: 'Kernel journal',
|
|
136
|
-
fn: async (context) => fetchPage(context, await resolveLogsOpts(opts, context)),
|
|
137
|
-
format: (page, format) => {
|
|
138
|
-
if (isMachine(format) || format.format !== undefined) output(page, format)
|
|
139
|
-
else {
|
|
140
|
-
presentList([...page.records], format, journalProjection)
|
|
141
|
-
if (page.cursor) process.stderr.write(` cursor: ${page.cursor}\n`)
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
})
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
type FollowDependencies = {
|
|
148
|
-
readonly run: typeof runKernelCommand
|
|
149
|
-
readonly pause: (milliseconds: number) => Promise<void>
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/** Follow one admitted journal stream. Dependencies are explicit so routing is proven at the command boundary. */
|
|
153
|
-
export async function followLogs(
|
|
154
|
-
opts: LogsOpts,
|
|
155
|
-
dependencies: FollowDependencies = {
|
|
156
|
-
run: runKernelCommand,
|
|
157
|
-
pause: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
|
|
158
|
-
},
|
|
159
|
-
): Promise<void> {
|
|
160
|
-
validateLogsOpts(opts)
|
|
161
|
-
await dependencies.run({
|
|
162
|
-
opts,
|
|
163
|
-
label: 'Kernel journal',
|
|
164
|
-
fn: async (context): Promise<never> => {
|
|
165
|
-
const resolved = await resolveLogsOpts(opts, context)
|
|
166
|
-
let cursor = resolved.cursor
|
|
167
|
-
for (;;) {
|
|
168
|
-
const page = await fetchPage(context, { ...resolved, cursor })
|
|
169
|
-
for (const record of page.records) printRecord(record, opts)
|
|
170
|
-
cursor = page.cursor ?? cursor
|
|
171
|
-
await dependencies.pause(FOLLOW_INTERVAL_MS)
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
})
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function journalProjection(records: JournalRecord[]): ListProjection {
|
|
178
|
-
const columns: Column[] = [
|
|
179
|
-
{ key: 'sequence', header: 'SEQ', color: chalk.dim },
|
|
180
|
-
{ key: 'timestamp', header: 'TIME', color: chalk.dim },
|
|
181
|
-
{ key: 'topic', header: 'TOPIC', color: chalk.cyan },
|
|
182
|
-
{ key: 'principal', header: 'PRINCIPAL', color: chalk.dim },
|
|
183
|
-
]
|
|
184
|
-
return {
|
|
185
|
-
columns,
|
|
186
|
-
rows: records.map((record) => ({
|
|
187
|
-
sequence: String(record.sequence),
|
|
188
|
-
timestamp: record.timestamp,
|
|
189
|
-
topic: record.topic,
|
|
190
|
-
principal: record.principal ?? '',
|
|
191
|
-
})),
|
|
192
|
-
paths: records.map((record) => String(record.sequence)),
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function printRecord(record: JournalRecord, opts: LogsOpts): void {
|
|
197
|
-
if (isMachine(opts) || opts.format === 'json') {
|
|
198
|
-
process.stdout.write(formatFollowRecord(record))
|
|
199
|
-
return
|
|
200
|
-
}
|
|
201
|
-
process.stdout.write(
|
|
202
|
-
`${chalk.dim(String(record.sequence).padStart(6))} ${chalk.dim(record.timestamp)} ${chalk.cyan(record.topic)} ${chalk.dim(record.principal ?? '')}\n`,
|
|
203
|
-
)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/** Machine follow is an NDJSON stream: one complete admitted record per line. */
|
|
207
|
-
export function formatFollowRecord(record: JournalRecord): string {
|
|
208
|
-
return `${JSON.stringify(record)}\n`
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export function validateLogsOpts(opts: LogsOpts): void {
|
|
212
|
-
buildJournalInput(opts)
|
|
213
|
-
if (opts.follow && opts.format === 'yaml' && !opts.json && !opts.raw) {
|
|
214
|
-
throw new TypeError('--follow does not support YAML; use --json for an NDJSON stream')
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function acceptRecord(input: unknown, index: number): JournalRecord {
|
|
219
|
-
if (
|
|
220
|
-
!isRecord(input) ||
|
|
221
|
-
!Number.isSafeInteger(input.sequence) ||
|
|
222
|
-
typeof input.topic !== 'string'
|
|
223
|
-
) {
|
|
224
|
-
throw new TypeError(`Kernel journal record ${index} is invalid`)
|
|
225
|
-
}
|
|
226
|
-
const occurredAt = optionalText(input.occurredAt, index, 'occurredAt')
|
|
227
|
-
const timestamp = optionalText(input.timestamp, index, 'timestamp') ?? occurredAt
|
|
228
|
-
if (timestamp === undefined) {
|
|
229
|
-
throw new TypeError(`Kernel journal record ${index} is missing occurredAt/timestamp`)
|
|
230
|
-
}
|
|
231
|
-
const correlation = acceptCorrelation(input.correlation, index)
|
|
232
|
-
const legacyCorrelationId = optionalIdentifier(input.correlationId, index, 'correlationId')
|
|
233
|
-
const structuredCorrelationId = correlation?.invocationId
|
|
234
|
-
if (
|
|
235
|
-
legacyCorrelationId !== undefined &&
|
|
236
|
-
structuredCorrelationId !== undefined &&
|
|
237
|
-
legacyCorrelationId !== structuredCorrelationId
|
|
238
|
-
) {
|
|
239
|
-
throw new TypeError(`Kernel journal record ${index} has conflicting correlation identifiers`)
|
|
240
|
-
}
|
|
241
|
-
const correlationId = structuredCorrelationId ?? legacyCorrelationId
|
|
242
|
-
const principal = optionalText(input.principal, index, 'principal')
|
|
243
|
-
return Object.freeze({
|
|
244
|
-
sequence: input.sequence as number,
|
|
245
|
-
timestamp,
|
|
246
|
-
topic: input.topic,
|
|
247
|
-
payload: input.payload,
|
|
248
|
-
...(occurredAt === undefined ? {} : { occurredAt }),
|
|
249
|
-
...(optionalText(input.committedAt, index, 'committedAt') === undefined
|
|
250
|
-
? {}
|
|
251
|
-
: { committedAt: input.committedAt as string }),
|
|
252
|
-
...(principal === undefined ? {} : { principal }),
|
|
253
|
-
...(correlation === undefined ? {} : { correlation }),
|
|
254
|
-
...(correlationId === undefined ? {} : { correlationId }),
|
|
255
|
-
...(optionalIdentifier(input.causationId, index, 'causationId') === undefined
|
|
256
|
-
? {}
|
|
257
|
-
: { causationId: input.causationId as string }),
|
|
258
|
-
})
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const correlationFields = [
|
|
262
|
-
'operationId',
|
|
263
|
-
'parentOperationId',
|
|
264
|
-
'invocationId',
|
|
265
|
-
'rootInvocationId',
|
|
266
|
-
'parentInvocationId',
|
|
267
|
-
'traceId',
|
|
268
|
-
'spanId',
|
|
269
|
-
] as const
|
|
270
|
-
|
|
271
|
-
function acceptCorrelation(input: unknown, index: number): JournalCorrelation | undefined {
|
|
272
|
-
if (input === undefined) return undefined
|
|
273
|
-
if (!isRecord(input)) {
|
|
274
|
-
throw new TypeError(`Kernel journal record ${index}.correlation must be an object`)
|
|
275
|
-
}
|
|
276
|
-
const unknown = Object.keys(input).find(
|
|
277
|
-
(field) => !correlationFields.includes(field as (typeof correlationFields)[number]),
|
|
278
|
-
)
|
|
279
|
-
if (unknown !== undefined) {
|
|
280
|
-
throw new TypeError(`Kernel journal record ${index}.correlation.${unknown} is unsupported`)
|
|
281
|
-
}
|
|
282
|
-
return Object.freeze(
|
|
283
|
-
Object.fromEntries(
|
|
284
|
-
correlationFields.flatMap((field) => {
|
|
285
|
-
const value = optionalIdentifier(input[field], index, `correlation.${field}`)
|
|
286
|
-
return value === undefined ? [] : [[field, value]]
|
|
287
|
-
}),
|
|
288
|
-
),
|
|
289
|
-
)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function optionalIdentifier(input: unknown, index: number, field: string): string | undefined {
|
|
293
|
-
const value = optionalText(input, index, field)
|
|
294
|
-
if (value === undefined) return undefined
|
|
295
|
-
if (value.trim() === '' || new TextEncoder().encode(value).byteLength > 256) {
|
|
296
|
-
throw new TypeError(
|
|
297
|
-
`Kernel journal record ${index}.${field} must be non-empty and at most 256 UTF-8 bytes`,
|
|
298
|
-
)
|
|
299
|
-
}
|
|
300
|
-
return value
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
function optionalText(input: unknown, index: number, field: string): string | undefined {
|
|
304
|
-
if (input === undefined) return undefined
|
|
305
|
-
if (typeof input !== 'string') {
|
|
306
|
-
throw new TypeError(`Kernel journal record ${index}.${field} must be text`)
|
|
307
|
-
}
|
|
308
|
-
return input
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function positiveInteger(flag: string, raw: string): number {
|
|
312
|
-
if (!/^\d+$/.test(raw)) throw new TypeError(`${flag} must be a positive integer`)
|
|
313
|
-
const value = Number.parseInt(raw, 10)
|
|
314
|
-
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
315
|
-
throw new TypeError(`${flag} must be a positive integer`)
|
|
316
|
-
}
|
|
317
|
-
return value
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
async function resolveLogsOpts(opts: LogsOpts, context: ConnectionContext): Promise<LogsOpts> {
|
|
321
|
-
const principal = nonEmpty(opts.principal)
|
|
322
|
-
if (principal !== '@self') return opts
|
|
323
|
-
const { path } = await expandSelfInPath('@self', context)
|
|
324
|
-
return { ...opts, principal: path.startsWith('@') ? path.slice(1) : path }
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function nonEmpty(input: string | undefined): string | undefined {
|
|
328
|
-
const value = input?.trim()
|
|
329
|
-
return value ? value : undefined
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function isRecord(input: unknown): input is Record<string, unknown> {
|
|
333
|
-
return input !== null && typeof input === 'object' && !Array.isArray(input)
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export default {
|
|
337
|
-
name: 'logs',
|
|
338
|
-
description: 'Read or follow the authorized Kernel journal',
|
|
339
|
-
afterHelpText: `
|
|
340
|
-
Behavior:
|
|
341
|
-
Calls the public Kernel journal syscall and emits its { records, cursor }
|
|
342
|
-
page. Topic selection is exact or prefix-based; cursors and timestamps are
|
|
343
|
-
opaque strings owned by the journal backend. --follow reuses one Client Session
|
|
344
|
-
and advances only with the returned cursor. With --json, follow output is
|
|
345
|
-
NDJSON with one complete admitted record per line; YAML follow is unsupported.
|
|
346
|
-
|
|
347
|
-
Examples:
|
|
348
|
-
$ astrale logs -i staging --limit 50
|
|
349
|
-
$ astrale logs --topic op:function.failed
|
|
350
|
-
$ astrale logs --topic-prefix op:function. --follow
|
|
351
|
-
`,
|
|
352
|
-
options: [
|
|
353
|
-
{ flags: '--since <timestamp>', description: 'Inclusive journal timestamp lower bound' },
|
|
354
|
-
{ flags: '--until <timestamp>', description: 'Inclusive journal timestamp upper bound' },
|
|
355
|
-
{ flags: '--topic <topic>', description: 'Match one exact topic' },
|
|
356
|
-
{ flags: '--topic-prefix <prefix>', description: 'Match one topic prefix' },
|
|
357
|
-
{ flags: '--principal <id>', description: 'Filter by triggering identity ID' },
|
|
358
|
-
{ flags: '--limit <n>', description: `Maximum records (default: ${DEFAULT_LIMIT})` },
|
|
359
|
-
{ flags: '--cursor <token>', description: 'Resume from an opaque journal cursor' },
|
|
360
|
-
{ flags: '--follow', description: 'Poll using returned cursors until interrupted' },
|
|
361
|
-
],
|
|
362
|
-
action: async (opts: LogsOpts) => {
|
|
363
|
-
try {
|
|
364
|
-
validateLogsOpts(opts)
|
|
365
|
-
} catch (error) {
|
|
366
|
-
failInput(error, opts)
|
|
367
|
-
}
|
|
368
|
-
if (opts.follow) await followLogs(opts)
|
|
369
|
-
else await runOnce(opts)
|
|
370
|
-
},
|
|
371
|
-
} satisfies CommandDefinition
|
package/src/commands/mutate.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import type { MutationResult } from '@astrale-os/sdk/mutation'
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
import { readFile } from 'node:fs/promises'
|
|
5
|
-
|
|
6
|
-
import type { KernelCommandOpts } from '../connection'
|
|
7
|
-
import type { CommandDefinition } from '../program/index'
|
|
8
|
-
|
|
9
|
-
import { runKernelCommand } from '../connection'
|
|
10
|
-
import { AstraleError } from '../errors'
|
|
11
|
-
import { prepareMutation } from '../graph/index'
|
|
12
|
-
import { failInput } from '../lib/log'
|
|
13
|
-
import { output } from '../lib/output'
|
|
14
|
-
import { renderTable } from '../lib/table'
|
|
15
|
-
|
|
16
|
-
type MutateOpts = KernelCommandOpts & {
|
|
17
|
-
data?: string
|
|
18
|
-
file?: string
|
|
19
|
-
dry?: boolean
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function mutateCommand(opts: MutateOpts): Promise<void> {
|
|
23
|
-
let mutation
|
|
24
|
-
try {
|
|
25
|
-
mutation = prepareMutation(await readDocument(opts))
|
|
26
|
-
} catch (error) {
|
|
27
|
-
failInput(error, opts)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (opts.dry) {
|
|
31
|
-
output(mutation, opts)
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
await runKernelCommand<MutationResult>({
|
|
36
|
-
opts,
|
|
37
|
-
label: 'Mutate',
|
|
38
|
-
fn: ({ graph }) => graph.mutate(mutation),
|
|
39
|
-
format: (result, format, machine) => {
|
|
40
|
-
if (machine || format.format !== undefined) output(result, format)
|
|
41
|
-
else printResult(result)
|
|
42
|
-
},
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function readDocument(opts: MutateOpts): Promise<unknown> {
|
|
47
|
-
const authored = [opts.data !== undefined, opts.file !== undefined].filter(Boolean).length
|
|
48
|
-
if (authored > 1) throw new TypeError('--data and --file are mutually exclusive')
|
|
49
|
-
if (opts.data !== undefined) return parseJson(opts.data, '--data')
|
|
50
|
-
if (opts.file !== undefined) {
|
|
51
|
-
let raw: string
|
|
52
|
-
try {
|
|
53
|
-
raw = await readFile(opts.file, 'utf8')
|
|
54
|
-
} catch (error) {
|
|
55
|
-
throw new AstraleError('FILE_READ_FAILED', `Cannot read --file ${opts.file}.`, undefined, {
|
|
56
|
-
cause: error,
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
return parseJson(raw, opts.file)
|
|
60
|
-
}
|
|
61
|
-
if (process.stdin.isTTY) {
|
|
62
|
-
throw new TypeError('No mutation provided; use --data, --file, or stdin')
|
|
63
|
-
}
|
|
64
|
-
const chunks: Buffer[] = []
|
|
65
|
-
for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk))
|
|
66
|
-
const raw = Buffer.concat(chunks).toString('utf8').trim()
|
|
67
|
-
if (raw.length === 0) throw new TypeError('No mutation provided on stdin')
|
|
68
|
-
return parseJson(raw, 'stdin')
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function parseJson(raw: string, source: string): unknown {
|
|
72
|
-
try {
|
|
73
|
-
return JSON.parse(raw)
|
|
74
|
-
} catch {
|
|
75
|
-
throw new TypeError(`${source} must contain valid JSON`)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function printResult(result: MutationResult): void {
|
|
80
|
-
const rows = Object.entries(result.createdNodes).map(([binding, id]) => ({ binding, id }))
|
|
81
|
-
if (rows.length === 0) {
|
|
82
|
-
console.log(chalk.dim(' applied — no Nodes created'))
|
|
83
|
-
return
|
|
84
|
-
}
|
|
85
|
-
console.log(` ${chalk.bold('Created nodes:')}`)
|
|
86
|
-
console.log(
|
|
87
|
-
renderTable(rows, {
|
|
88
|
-
columns: [
|
|
89
|
-
{ key: 'binding', header: 'BINDING', color: chalk.cyan },
|
|
90
|
-
{ key: 'id', header: 'ID', color: chalk.dim },
|
|
91
|
-
],
|
|
92
|
-
showHeader: true,
|
|
93
|
-
}),
|
|
94
|
-
)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export default {
|
|
98
|
-
name: 'mutate',
|
|
99
|
-
description: 'Apply one atomic Mutation V3 graph transition',
|
|
100
|
-
afterHelpText: `
|
|
101
|
-
Behavior:
|
|
102
|
-
Accepts a canonical astrale.graph.mutation/v3 document or its exact
|
|
103
|
-
{ preconditions, operations } authoring input. Source is --data, --file,
|
|
104
|
-
or stdin. --dry admits and prints the canonical document without opening a
|
|
105
|
-
Kernel connection. The result contains the real createdNodes binding map.
|
|
106
|
-
|
|
107
|
-
Legacy PatchData nodes/edges arms and createdEdges IDs are not part of
|
|
108
|
-
Mutation V3 and are rejected rather than approximated.
|
|
109
|
-
|
|
110
|
-
Examples:
|
|
111
|
-
$ astrale mutate --file mutation.v3.json
|
|
112
|
-
$ astrale mutate --data '{"preconditions":[],"operations":[]}' --dry
|
|
113
|
-
`,
|
|
114
|
-
options: [
|
|
115
|
-
{ flags: '-d, --data <json>', description: 'Mutation V3 JSON document' },
|
|
116
|
-
{ flags: '-f, --file <path>', description: 'Read a Mutation V3 document from a file' },
|
|
117
|
-
{ flags: '--dry', description: 'Admit and print canonical Mutation V3 without dispatch' },
|
|
118
|
-
],
|
|
119
|
-
action: async (opts) => {
|
|
120
|
-
await mutateCommand(opts as MutateOpts)
|
|
121
|
-
},
|
|
122
|
-
} satisfies CommandDefinition
|
package/src/commands/query.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import type { QueryDirection } from '@astrale-os/sdk/query'
|
|
2
|
-
|
|
3
|
-
import { readFile } from 'node:fs/promises'
|
|
4
|
-
|
|
5
|
-
import type { KernelCommandOpts, SelfExpansionMeta } from '../connection'
|
|
6
|
-
import type { CommandDefinition } from '../program/index'
|
|
7
|
-
|
|
8
|
-
import { expandSelfInPath, runKernelCommand, withSelfHint } from '../connection'
|
|
9
|
-
import { AstraleError } from '../errors'
|
|
10
|
-
import { prepareQuery, type QueryCommandInput } from '../graph/index'
|
|
11
|
-
import { failInput } from '../lib/log'
|
|
12
|
-
import { isMachine, output } from '../lib/output'
|
|
13
|
-
|
|
14
|
-
type QueryOpts = KernelCommandOpts & {
|
|
15
|
-
ast?: string
|
|
16
|
-
file?: string
|
|
17
|
-
class?: string
|
|
18
|
-
edge?: string
|
|
19
|
-
direction?: QueryDirection
|
|
20
|
-
limit?: string
|
|
21
|
-
cursor?: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function queryCommand(sources: string[], opts: QueryOpts): Promise<void> {
|
|
25
|
-
let input: QueryCommandInput
|
|
26
|
-
try {
|
|
27
|
-
const ast = await readAst(opts)
|
|
28
|
-
input = {
|
|
29
|
-
sources,
|
|
30
|
-
...(ast === undefined ? {} : { ast }),
|
|
31
|
-
class: opts.class,
|
|
32
|
-
edge: opts.edge,
|
|
33
|
-
direction: opts.direction,
|
|
34
|
-
limit: opts.limit,
|
|
35
|
-
cursor: opts.cursor,
|
|
36
|
-
}
|
|
37
|
-
} catch (error) {
|
|
38
|
-
failInput(error, opts)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
let prepared
|
|
42
|
-
try {
|
|
43
|
-
prepared = prepareQuery(input)
|
|
44
|
-
} catch (error) {
|
|
45
|
-
failInput(error, opts)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
await runKernelCommand({
|
|
49
|
-
opts,
|
|
50
|
-
label: 'Query',
|
|
51
|
-
fn: async (context) => {
|
|
52
|
-
const expanded = await Promise.all(sources.map((source) => expandSelfInPath(source, context)))
|
|
53
|
-
const meta: SelfExpansionMeta | undefined = expanded.find(
|
|
54
|
-
(entry) => entry.meta !== undefined,
|
|
55
|
-
)?.meta
|
|
56
|
-
const resolved =
|
|
57
|
-
meta === undefined
|
|
58
|
-
? prepared
|
|
59
|
-
: prepareQuery({ ...input, sources: expanded.map(({ path }) => path) })
|
|
60
|
-
return withSelfHint(() => context.graph.query(resolved.ast, { page: resolved.page }), meta)
|
|
61
|
-
},
|
|
62
|
-
format: (response, format) => {
|
|
63
|
-
output(
|
|
64
|
-
response.page.next === undefined
|
|
65
|
-
? response.result
|
|
66
|
-
: { ...response.result, page: { next: response.page.next } },
|
|
67
|
-
format,
|
|
68
|
-
)
|
|
69
|
-
if (response.page.next && !isMachine(format)) {
|
|
70
|
-
process.stderr.write(` cursor: ${response.page.next}\n`)
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function readAst(opts: QueryOpts): Promise<unknown | undefined> {
|
|
77
|
-
if (opts.ast !== undefined && opts.file !== undefined) {
|
|
78
|
-
throw new TypeError('--ast and --file are mutually exclusive')
|
|
79
|
-
}
|
|
80
|
-
if (opts.ast !== undefined) return parseJson(opts.ast, '--ast')
|
|
81
|
-
if (opts.file === undefined) return undefined
|
|
82
|
-
let raw: string
|
|
83
|
-
try {
|
|
84
|
-
raw = await readFile(opts.file, 'utf8')
|
|
85
|
-
} catch (error) {
|
|
86
|
-
throw new AstraleError('FILE_READ_FAILED', `Cannot read --file ${opts.file}.`, undefined, {
|
|
87
|
-
cause: error,
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
return parseJson(raw, opts.file)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function parseJson(raw: string, source: string): unknown {
|
|
94
|
-
try {
|
|
95
|
-
return JSON.parse(raw)
|
|
96
|
-
} catch {
|
|
97
|
-
throw new TypeError(`${source} must contain valid JSON`)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export default {
|
|
102
|
-
name: 'query',
|
|
103
|
-
description: 'Run one canonical Query V6 graph read',
|
|
104
|
-
afterHelpText: `
|
|
105
|
-
Behavior:
|
|
106
|
-
Positional Paths and --class author a finite Query V6 read. --edge adds
|
|
107
|
-
one exact Edge-Class expansion; --direction defaults to outgoing. --ast and
|
|
108
|
-
--file accept a complete canonical astrale.graph.query/v6 document, including
|
|
109
|
-
Property ordering and Node or Edge reference/value projections. --cursor resumes
|
|
110
|
-
one caller-bound query scope. Machine output adds page.next only when another
|
|
111
|
-
page exists; pass that opaque value back through --cursor.
|
|
112
|
-
|
|
113
|
-
Legacy depth/children selector JSON and raw Cypher are not portable Kernel
|
|
114
|
-
V2 query contracts and are not accepted.
|
|
115
|
-
|
|
116
|
-
Examples:
|
|
117
|
-
$ astrale query /:notes.example.dev:class.Note --limit 50
|
|
118
|
-
$ astrale query --class /:notes.example.dev:class.Note --limit 50
|
|
119
|
-
$ astrale query @note --edge /:notes.example.dev:class.references --direction outgoing --limit 25
|
|
120
|
-
$ astrale query --file query.v6.json --cursor "$CURSOR"
|
|
121
|
-
`,
|
|
122
|
-
arguments: [{ name: 'sources...', description: 'Canonical source Paths', required: false }],
|
|
123
|
-
options: [
|
|
124
|
-
{ flags: '--ast <json>', description: 'Canonical Query V6 JSON document' },
|
|
125
|
-
{ flags: '-f, --file <path>', description: 'Read a canonical Query V6 document from a file' },
|
|
126
|
-
{
|
|
127
|
-
flags: '--class <path>',
|
|
128
|
-
description: 'Select Nodes satisfying one exact Class',
|
|
129
|
-
},
|
|
130
|
-
{ flags: '--edge <class>', description: 'Expand one exact Edge Class' },
|
|
131
|
-
{
|
|
132
|
-
flags: '--direction <direction>',
|
|
133
|
-
description: 'Edge direction (requires --edge)',
|
|
134
|
-
choices: ['outgoing', 'incoming', 'incident'],
|
|
135
|
-
},
|
|
136
|
-
{ flags: '--limit <n>', description: 'Finite selected binding limit (default: 100)' },
|
|
137
|
-
{ flags: '--cursor <token>', description: 'Resume one live query scope' },
|
|
138
|
-
],
|
|
139
|
-
action: async (sources, opts) => {
|
|
140
|
-
await queryCommand((sources as string[] | undefined) ?? [], opts as QueryOpts)
|
|
141
|
-
},
|
|
142
|
-
} satisfies CommandDefinition
|