@1agh/maude 1.0.9 → 1.2.0
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/apps/studio/acp/bridge.ts +18 -13
- package/apps/studio/acp/probe.ts +268 -16
- package/apps/studio/acp/transcript-io.ts +394 -0
- package/apps/studio/acp/transcript.ts +103 -38
- package/apps/studio/api.ts +139 -26
- package/apps/studio/bin/_import-figma.mjs +57 -11
- package/apps/studio/bin/_seed-fixture.mjs +163 -0
- package/apps/studio/canvas-imports.ts +89 -0
- package/apps/studio/client/app.jsx +257 -7
- package/apps/studio/client/export-center.jsx +15 -7
- package/apps/studio/client/panels/ReadinessList.jsx +7 -1
- package/apps/studio/client/panels/SyncPanel.jsx +125 -4
- package/apps/studio/client/report-bug.jsx +19 -1
- package/apps/studio/client/styles/3-shell-maude.css +34 -0
- package/apps/studio/client/styles/4-components.css +26 -0
- package/apps/studio/collab/persistence.ts +132 -16
- package/apps/studio/collab/registry.ts +10 -18
- package/apps/studio/debug-bundle.ts +13 -0
- package/apps/studio/dist/client.bundle.js +1128 -1128
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/export-dialog.tsx +54 -0
- package/apps/studio/exporters/degraded.ts +19 -3
- package/apps/studio/exporters/ghostscript.ts +194 -0
- package/apps/studio/exporters/pdf-fonts.ts +261 -0
- package/apps/studio/exporters/pdf.ts +152 -3
- package/apps/studio/exporters/remote.ts +36 -1
- package/apps/studio/fs-watch.ts +45 -1
- package/apps/studio/http.ts +7 -1
- package/apps/studio/mem.ts +45 -9
- package/apps/studio/readiness.ts +42 -7
- package/apps/studio/server.ts +11 -4
- package/apps/studio/sync/agent.ts +136 -29
- package/apps/studio/sync/asset-push.ts +1 -47
- package/apps/studio/sync/codec.ts +122 -31
- package/apps/studio/sync/cold-start-apply.ts +7 -0
- package/apps/studio/sync/cold-start.ts +118 -22
- package/apps/studio/sync/comment-identity.ts +68 -0
- package/apps/studio/sync/connection-state.ts +15 -1
- package/apps/studio/sync/file-ledger.ts +117 -0
- package/apps/studio/sync/file-plane.ts +623 -27
- package/apps/studio/sync/index.ts +711 -20
- package/apps/studio/sync/journal-client.ts +13 -1
- package/apps/studio/sync/migrate-seed.ts +40 -3
- package/apps/studio/sync/presentation.ts +26 -3
- package/apps/studio/sync/retry-after.ts +169 -0
- package/apps/studio/sync/seed-progress.ts +218 -0
- package/apps/studio/sync/status.ts +122 -5
- package/apps/studio/sync/transport-error.ts +111 -0
- package/apps/studio/whats-new.json +91 -0
- package/cli/bin/maude.mjs +2 -0
- package/cli/commands/codex.mjs +191 -0
- package/cli/commands/harness.mjs +1051 -0
- package/cli/commands/help.mjs +13 -0
- package/cli/lib/design-link.mjs +190 -2
- package/cli/lib/harness/capabilities.mjs +302 -0
- package/cli/lib/harness/codex-runtime.mjs +889 -0
- package/cli/lib/harness/compatibility.mjs +27 -0
- package/cli/lib/harness/discover-claude.mjs +1393 -0
- package/cli/lib/harness/managed-state.mjs +1296 -0
- package/cli/lib/harness/model.mjs +86 -0
- package/cli/lib/harness/secrets.mjs +390 -0
- package/cli/lib/harness/targets/codex.mjs +1141 -0
- package/cli/lib/harness/targets/opencode.mjs +807 -0
- package/cli/lib/harness/transaction.mjs +1099 -0
- package/cli/lib/hubs-config.mjs +35 -8
- package/cli/templates/harness/opencode/maude-projector.ts +58 -0
- package/docs/harness-capability-matrix.md +125 -0
- package/docs/harness-environment-projection.md +95 -0
- package/package.json +32 -9
- package/plugins/flow/.claude-plugin/config.schema.json +8 -0
- package/apps/studio/.ai/cache/_stats.json +0 -7
- package/apps/studio/bin/_agent-browser-safe.test.mjs +0 -165
- package/apps/studio/bin/_curl-local.test.mjs +0 -280
- package/apps/studio/bin/_pw-launch.test.mjs +0 -90
- package/apps/studio/bin/_smart-frames.test.mjs +0 -195
- package/apps/studio/bin/_transcribe.test.mjs +0 -80
- package/apps/studio/bun.lock +0 -928
- package/apps/studio/draw/test/animate.test.ts +0 -172
- package/apps/studio/draw/test/brush.test.ts +0 -213
- package/apps/studio/draw/test/composition.test.ts +0 -141
- package/apps/studio/draw/test/geometry.test.ts +0 -199
- package/apps/studio/draw/test/gradient.test.ts +0 -167
- package/apps/studio/draw/test/layout.test.ts +0 -120
- package/apps/studio/draw/test/morph.test.ts +0 -107
- package/apps/studio/draw/test/optimize.test.ts +0 -40
- package/apps/studio/draw/test/palette.test.ts +0 -123
- package/apps/studio/draw/test/primitives.test.ts +0 -129
- package/apps/studio/draw/test/serialize-animate.test.ts +0 -142
- package/apps/studio/draw/test/serialize.test.ts +0 -105
- package/apps/studio/figma/assets.test.ts +0 -464
- package/apps/studio/figma/client.test.ts +0 -395
- package/apps/studio/figma/codegen-client.test.ts +0 -276
- package/apps/studio/figma/codegen-fonts.test.ts +0 -103
- package/apps/studio/figma/codegen-values.test.ts +0 -179
- package/apps/studio/figma/comments-to-strokes.test.ts +0 -194
- package/apps/studio/figma/fig-decode.test.ts +0 -788
- package/apps/studio/figma/fig-differential.test.ts +0 -182
- package/apps/studio/figma/fig-translator.test.ts +0 -192
- package/apps/studio/figma/fig-vector.test.ts +0 -113
- package/apps/studio/figma/from-codegen.test.ts +0 -408
- package/apps/studio/figma/sanitize.test.ts +0 -325
- package/apps/studio/figma/tailwind-map.test.ts +0 -142
- package/apps/studio/figma/to-artboard.test.ts +0 -808
- package/apps/studio/figma/to-render.test.ts +0 -180
- package/apps/studio/figma/to-strokes-roundtrip.test.ts +0 -152
- package/apps/studio/figma/to-strokes.test.ts +0 -705
- package/apps/studio/figma/to-tokens.test.ts +0 -321
- package/apps/studio/figma/url.test.ts +0 -167
- package/apps/studio/footage/schema.test.ts +0 -287
- package/apps/studio/generation/adapters/groq.test.ts +0 -80
- package/apps/studio/generation/audio-library.test.ts +0 -95
- package/apps/studio/generation/captions.test.ts +0 -78
- package/apps/studio/generation/elevenlabs.test.ts +0 -223
- package/apps/studio/generation/gemini.test.ts +0 -350
- package/apps/studio/generation/jobs.test.ts +0 -128
- package/apps/studio/generation/keys.test.ts +0 -75
- package/apps/studio/generation/prefs.test.ts +0 -95
- package/apps/studio/generation/types.test.ts +0 -123
- package/apps/studio/generation/whisper-models.test.ts +0 -179
- package/apps/studio/test/_helpers.ts +0 -108
- package/apps/studio/test/acp-activity-endpoint.test.ts +0 -183
- package/apps/studio/test/acp-activity.test.ts +0 -154
- package/apps/studio/test/acp-ai-activity.test.ts +0 -182
- package/apps/studio/test/acp-attachment-serve.test.ts +0 -74
- package/apps/studio/test/acp-bootstrap-brief.test.ts +0 -178
- package/apps/studio/test/acp-branch-guard.test.ts +0 -123
- package/apps/studio/test/acp-bridge-lifetime.test.ts +0 -475
- package/apps/studio/test/acp-bridge.test.ts +0 -301
- package/apps/studio/test/acp-capabilities.test.ts +0 -123
- package/apps/studio/test/acp-caps-bridge.test.ts +0 -279
- package/apps/studio/test/acp-commands.test.ts +0 -119
- package/apps/studio/test/acp-elicitation-bridge.test.ts +0 -480
- package/apps/studio/test/acp-elicitation.test.ts +0 -251
- package/apps/studio/test/acp-env.test.ts +0 -95
- package/apps/studio/test/acp-mode-banner.test.ts +0 -45
- package/apps/studio/test/acp-origin-gate.test.ts +0 -160
- package/apps/studio/test/acp-permission-prompt.test.ts +0 -251
- package/apps/studio/test/acp-permission.test.ts +0 -278
- package/apps/studio/test/acp-plugin-bootstrap.test.ts +0 -89
- package/apps/studio/test/acp-session-allowed-tools.test.ts +0 -235
- package/apps/studio/test/acp-session-plugins.test.ts +0 -209
- package/apps/studio/test/acp-toolgroup.test.ts +0 -76
- package/apps/studio/test/acp-transcript-view.test.ts +0 -71
- package/apps/studio/test/acp-transcript.test.ts +0 -238
- package/apps/studio/test/acp-usage-bridge.test.ts +0 -141
- package/apps/studio/test/acp-usage.test.ts +0 -143
- package/apps/studio/test/acp-write-gate.test.ts +0 -323
- package/apps/studio/test/acp-write-scope.test.ts +0 -533
- package/apps/studio/test/active-state.test.ts +0 -186
- package/apps/studio/test/activity.test.ts +0 -189
- package/apps/studio/test/ai-activity.test.ts +0 -113
- package/apps/studio/test/annotate-write.test.ts +0 -1074
- package/apps/studio/test/annotation-strokes-command.test.ts +0 -166
- package/apps/studio/test/annotations-align.test.ts +0 -88
- package/apps/studio/test/annotations-api.test.ts +0 -145
- package/apps/studio/test/annotations-bindings.test.ts +0 -262
- package/apps/studio/test/annotations-draw-modifiers.test.ts +0 -206
- package/apps/studio/test/annotations-groups.test.ts +0 -231
- package/apps/studio/test/annotations-layer.test.ts +0 -1011
- package/apps/studio/test/annotations-roundtrip.test.ts +0 -663
- package/apps/studio/test/annotations-snap.test.ts +0 -135
- package/apps/studio/test/annotations-text-format.test.ts +0 -396
- package/apps/studio/test/artboard-activity-overlay.test.tsx +0 -56
- package/apps/studio/test/artboard-guides-overlay.test.tsx +0 -152
- package/apps/studio/test/artboard-hug-commit.test.ts +0 -36
- package/apps/studio/test/artboard-kinds.test.tsx +0 -83
- package/apps/studio/test/artboard-selection-attrs.test.ts +0 -69
- package/apps/studio/test/asset-api.test.ts +0 -149
- package/apps/studio/test/assets-s3.test.ts +0 -249
- package/apps/studio/test/binary-smoke.test.ts +0 -47
- package/apps/studio/test/boot-self-heal.test.ts +0 -87
- package/apps/studio/test/browse-posture.test.tsx +0 -107
- package/apps/studio/test/bundle-smoke.test.ts +0 -46
- package/apps/studio/test/camera-reveal.test.tsx +0 -173
- package/apps/studio/test/canvas-artifacts.test.ts +0 -125
- package/apps/studio/test/canvas-build-sandbox.test.ts +0 -69
- package/apps/studio/test/canvas-build.test.ts +0 -141
- package/apps/studio/test/canvas-create-api.test.ts +0 -676
- package/apps/studio/test/canvas-cursors.test.ts +0 -164
- package/apps/studio/test/canvas-edit.test.ts +0 -470
- package/apps/studio/test/canvas-freshness-deps.test.ts +0 -64
- package/apps/studio/test/canvas-header.test.ts +0 -127
- package/apps/studio/test/canvas-hide-chrome.test.ts +0 -88
- package/apps/studio/test/canvas-hmr-runtime.test.tsx +0 -114
- package/apps/studio/test/canvas-lib-inline.test.ts +0 -146
- package/apps/studio/test/canvas-lib-motion.test.ts +0 -131
- package/apps/studio/test/canvas-lib-resolver.test.ts +0 -111
- package/apps/studio/test/canvas-list-watch.test.ts +0 -388
- package/apps/studio/test/canvas-media-drop.test.ts +0 -187
- package/apps/studio/test/canvas-meta-api.test.ts +0 -707
- package/apps/studio/test/canvas-move-api.test.ts +0 -587
- package/apps/studio/test/canvas-origin-gate.test.ts +0 -417
- package/apps/studio/test/canvas-pipeline.test.ts +0 -180
- package/apps/studio/test/canvas-rects.test.ts +0 -198
- package/apps/studio/test/canvas-reorder.test.ts +0 -211
- package/apps/studio/test/canvas-route.test.ts +0 -179
- package/apps/studio/test/canvas-shell-base.test.ts +0 -107
- package/apps/studio/test/canvas-shell-build-error.test.ts +0 -52
- package/apps/studio/test/canvas-url.test.ts +0 -138
- package/apps/studio/test/canvas-wheel-delta.test.ts +0 -42
- package/apps/studio/test/canvas-zoom-floor.test.ts +0 -73
- package/apps/studio/test/capture-core.test.ts +0 -32
- package/apps/studio/test/capture-determinism-shape.test.ts +0 -135
- package/apps/studio/test/chat-attachments.test.ts +0 -117
- package/apps/studio/test/chat-context.test.ts +0 -129
- package/apps/studio/test/chat-markdown.test.tsx +0 -58
- package/apps/studio/test/clip-addressing.test.ts +0 -738
- package/apps/studio/test/clip-ops.test.ts +0 -922
- package/apps/studio/test/cloud-build.test.ts +0 -95
- package/apps/studio/test/cloud-connect-note.test.ts +0 -135
- package/apps/studio/test/cloud-endpoints.test.ts +0 -590
- package/apps/studio/test/cloud-history-hardening.test.ts +0 -165
- package/apps/studio/test/cloud-history-posture.test.ts +0 -230
- package/apps/studio/test/cloud-managed-save-surfaces.test.ts +0 -90
- package/apps/studio/test/cloud-renew.test.ts +0 -205
- package/apps/studio/test/cloud-session-role.test.ts +0 -161
- package/apps/studio/test/cloud-shell-surfaces.test.ts +0 -170
- package/apps/studio/test/cold-start-apply.test.ts +0 -303
- package/apps/studio/test/collab-annotations-bridge.test.ts +0 -55
- package/apps/studio/test/collab-awareness-bridge.test.ts +0 -223
- package/apps/studio/test/collab-bridge.test.ts +0 -79
- package/apps/studio/test/collab-loopback.test.ts +0 -63
- package/apps/studio/test/collab-origin-gate.test.ts +0 -323
- package/apps/studio/test/collab-protocol.test.ts +0 -146
- package/apps/studio/test/collab-readonly-gate.test.ts +0 -194
- package/apps/studio/test/collab-reseed-guard.test.ts +0 -78
- package/apps/studio/test/collab-room.test.ts +0 -188
- package/apps/studio/test/collab-session-survival.test.tsx +0 -176
- package/apps/studio/test/collab-stress.test.ts +0 -129
- package/apps/studio/test/comment-mount.test.ts +0 -97
- package/apps/studio/test/comment-relay-origin-gate.test.ts +0 -117
- package/apps/studio/test/comments-api.test.ts +0 -277
- package/apps/studio/test/comments-fs-rebroadcast.test.ts +0 -155
- package/apps/studio/test/comments-overlay.test.ts +0 -117
- package/apps/studio/test/compile-entry.test.ts +0 -133
- package/apps/studio/test/component-map.test.ts +0 -48
- package/apps/studio/test/config-projection.test.ts +0 -104
- package/apps/studio/test/config-reload.test.ts +0 -230
- package/apps/studio/test/config-version.test.ts +0 -88
- package/apps/studio/test/context-resolve-tokens.test.ts +0 -97
- package/apps/studio/test/convert-to-absolute.test.ts +0 -333
- package/apps/studio/test/credential-grammar.test.ts +0 -107
- package/apps/studio/test/csp-canvas-shell.test.ts +0 -62
- package/apps/studio/test/csrf-write-guard.test.ts +0 -141
- package/apps/studio/test/debug-bundle.test.ts +0 -105
- package/apps/studio/test/design-setup-readiness.test.ts +0 -155
- package/apps/studio/test/detach-component.test.ts +0 -94
- package/apps/studio/test/dns-rebinding-guard.test.ts +0 -101
- package/apps/studio/test/dom-selection.test.ts +0 -198
- package/apps/studio/test/dynamic-text-edit.test.ts +0 -162
- package/apps/studio/test/edit-css-occurrence.test.ts +0 -81
- package/apps/studio/test/edit-persistence.test.ts +0 -91
- package/apps/studio/test/edit-scope-api.test.ts +0 -119
- package/apps/studio/test/edit-source-command.test.ts +0 -142
- package/apps/studio/test/edit-suppress.test.ts +0 -170
- package/apps/studio/test/editing-presence.test.ts +0 -103
- package/apps/studio/test/element-resize.test.ts +0 -136
- package/apps/studio/test/element-structural-api.test.ts +0 -434
- package/apps/studio/test/element-structural-edit.test.ts +0 -750
- package/apps/studio/test/ensure-browser.test.ts +0 -92
- package/apps/studio/test/equal-spacing-detector.test.ts +0 -257
- package/apps/studio/test/export-assemble.test.ts +0 -53
- package/apps/studio/test/export-browser-lane.test.ts +0 -126
- package/apps/studio/test/export-capture-fidelity.test.ts +0 -146
- package/apps/studio/test/export-capture-hygiene.test.ts +0 -675
- package/apps/studio/test/export-center.test.tsx +0 -287
- package/apps/studio/test/export-e2e-lanes.test.ts +0 -857
- package/apps/studio/test/export-format-scope-coherence.test.ts +0 -89
- package/apps/studio/test/export-lane.test.ts +0 -245
- package/apps/studio/test/export-shim-multi-capture.test.ts +0 -83
- package/apps/studio/test/exporters/canva.test.ts +0 -63
- package/apps/studio/test/exporters/degraded-propagation.test.ts +0 -123
- package/apps/studio/test/exporters/endpoint.test.ts +0 -121
- package/apps/studio/test/exporters/history.test.ts +0 -107
- package/apps/studio/test/exporters/html.test.ts +0 -26
- package/apps/studio/test/exporters/jobs.test.ts +0 -342
- package/apps/studio/test/exporters/pdf.test.ts +0 -85
- package/apps/studio/test/exporters/png.test.ts +0 -103
- package/apps/studio/test/exporters/pptx-deck.test.ts +0 -112
- package/apps/studio/test/exporters/pptx.test.ts +0 -31
- package/apps/studio/test/exporters/pw-launch.test.ts +0 -49
- package/apps/studio/test/exporters/runtime.test.ts +0 -59
- package/apps/studio/test/exporters/scope.test.ts +0 -292
- package/apps/studio/test/exporters/svg.test.ts +0 -29
- package/apps/studio/test/exporters/unsupported-media.test.ts +0 -123
- package/apps/studio/test/exporters/zip.test.ts +0 -104
- package/apps/studio/test/fetch-asset-gate.test.ts +0 -189
- package/apps/studio/test/figjam-v3-model.test.ts +0 -342
- package/apps/studio/test/figma-explode.test.ts +0 -438
- package/apps/studio/test/figma-provenance.test.ts +0 -108
- package/apps/studio/test/figma-routes.test.ts +0 -294
- package/apps/studio/test/file-lock.test.ts +0 -84
- package/apps/studio/test/fixtures/fake-claude-auth.mjs +0 -13
- package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +0 -1
- package/apps/studio/test/fixtures/mock-acp-agent-caps.mjs +0 -158
- package/apps/studio/test/fixtures/mock-acp-agent-commands.mjs +0 -44
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-flood.mjs +0 -46
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-url.mjs +0 -42
- package/apps/studio/test/fixtures/mock-acp-agent-elicit.mjs +0 -63
- package/apps/studio/test/fixtures/mock-acp-agent-permission-flood.mjs +0 -51
- package/apps/studio/test/fixtures/mock-acp-agent-permission.mjs +0 -50
- package/apps/studio/test/fixtures/mock-acp-agent-slow.mjs +0 -45
- package/apps/studio/test/fixtures/mock-acp-agent-usage.mjs +0 -56
- package/apps/studio/test/fixtures/mock-acp-agent-wedged.mjs +0 -37
- package/apps/studio/test/fixtures/mock-acp-agent-write.mjs +0 -118
- package/apps/studio/test/fixtures/mock-acp-agent.mjs +0 -69
- package/apps/studio/test/fixtures/perf-canvas.mjs +0 -201
- package/apps/studio/test/fixtures/phase-20-annotations.svg +0 -1
- package/apps/studio/test/fixtures/phase-21-annotations.svg +0 -1
- package/apps/studio/test/fixtures/tiny-subset.woff2 +0 -0
- package/apps/studio/test/fixtures/video-comp-fixture.tsx +0 -82
- package/apps/studio/test/footage-store.test.ts +0 -100
- package/apps/studio/test/fs-mkdir-api.test.ts +0 -248
- package/apps/studio/test/fs-watch.test.ts +0 -41
- package/apps/studio/test/gemma-models.test.ts +0 -245
- package/apps/studio/test/generate-route.test.ts +0 -106
- package/apps/studio/test/git-api.test.ts +0 -0
- package/apps/studio/test/git-branches.test.ts +0 -341
- package/apps/studio/test/git-cloud-posture.test.ts +0 -59
- package/apps/studio/test/git-grouping.test.ts +0 -106
- package/apps/studio/test/git-lifecycle.test.ts +0 -100
- package/apps/studio/test/git-log-format.test.ts +0 -95
- package/apps/studio/test/git-safe-rel.test.ts +0 -132
- package/apps/studio/test/git-system-engine.test.ts +0 -135
- package/apps/studio/test/git-watch.test.ts +0 -97
- package/apps/studio/test/github-api.test.ts +0 -577
- package/apps/studio/test/grid-track-handles.test.ts +0 -160
- package/apps/studio/test/handoff-static-frames.test.ts +0 -215
- package/apps/studio/test/handoff.test.ts +0 -329
- package/apps/studio/test/history-rollback.test.ts +0 -88
- package/apps/studio/test/hmr-broadcast.test.ts +0 -236
- package/apps/studio/test/hmr-classify.test.ts +0 -87
- package/apps/studio/test/hub-link.test.ts +0 -80
- package/apps/studio/test/identity-cache.test.ts +0 -83
- package/apps/studio/test/import-asset-browser.test.ts +0 -64
- package/apps/studio/test/import-asset-route.test.ts +0 -71
- package/apps/studio/test/import-asset.test.ts +0 -427
- package/apps/studio/test/import-brand-browser.test.ts +0 -88
- package/apps/studio/test/import-brand-route.test.ts +0 -120
- package/apps/studio/test/import-brand.test.ts +0 -206
- package/apps/studio/test/import-figma.test.ts +0 -667
- package/apps/studio/test/import-tokens.test.ts +0 -722
- package/apps/studio/test/index-data-canvas-ds.test.ts +0 -97
- package/apps/studio/test/input-router.test.ts +0 -757
- package/apps/studio/test/inspect-script-syntax.test.ts +0 -53
- package/apps/studio/test/inspect-selections.test.ts +0 -219
- package/apps/studio/test/knob-props-authored.test.ts +0 -87
- package/apps/studio/test/layers-synthetic-groups.test.ts +0 -96
- package/apps/studio/test/locator.test.ts +0 -214
- package/apps/studio/test/marquee-overlay.test.ts +0 -94
- package/apps/studio/test/media-commit-chain.test.ts +0 -210
- package/apps/studio/test/mode-toggle.test.tsx +0 -226
- package/apps/studio/test/motion-sample.test.ts +0 -35
- package/apps/studio/test/move-artboards-command.test.ts +0 -108
- package/apps/studio/test/participants-chrome.test.ts +0 -65
- package/apps/studio/test/paths.test.ts +0 -88
- package/apps/studio/test/pdf-print-boxes.test.ts +0 -359
- package/apps/studio/test/peer-selection-follows-camera.test.tsx +0 -131
- package/apps/studio/test/perf-harness.ts +0 -193
- package/apps/studio/test/phase-3.6-smoke.test.ts +0 -79
- package/apps/studio/test/photo-bg-remove-validation.test.ts +0 -71
- package/apps/studio/test/photo-canvas-bundle.test.ts +0 -79
- package/apps/studio/test/photo-edit-api.test.ts +0 -201
- package/apps/studio/test/photo-filters.test.ts +0 -149
- package/apps/studio/test/photo-pipeline.test.ts +0 -106
- package/apps/studio/test/photo-taxonomy.test.ts +0 -96
- package/apps/studio/test/print-marks.test.ts +0 -113
- package/apps/studio/test/print-units.test.ts +0 -173
- package/apps/studio/test/read-annotations.test.ts +0 -727
- package/apps/studio/test/read-only-gate.test.ts +0 -188
- package/apps/studio/test/read-only-role.test.ts +0 -95
- package/apps/studio/test/readiness.test.ts +0 -226
- package/apps/studio/test/remote-ahead-behind-cache.test.ts +0 -89
- package/apps/studio/test/reorder-api.test.ts +0 -210
- package/apps/studio/test/repo-concurrency.test.ts +0 -146
- package/apps/studio/test/repo-lock.test.ts +0 -350
- package/apps/studio/test/report-proxy.test.ts +0 -125
- package/apps/studio/test/ripple.test.ts +0 -197
- package/apps/studio/test/runtime-bundle-error-mapping.test.ts +0 -43
- package/apps/studio/test/runtime-bundle.test.ts +0 -69
- package/apps/studio/test/sanitize-annotation-svg.test.ts +0 -238
- package/apps/studio/test/scaffold-design.test.ts +0 -122
- package/apps/studio/test/server-lifecycle.test.ts +0 -38
- package/apps/studio/test/session-runtime-state.test.ts +0 -226
- package/apps/studio/test/session-scope.test.ts +0 -100
- package/apps/studio/test/shared-doc-cell-pairing.test.ts +0 -642
- package/apps/studio/test/shared-doc-convergence.test.ts +0 -265
- package/apps/studio/test/shared-doc-foundation.test.ts +0 -63
- package/apps/studio/test/shared-doc-migrate.test.ts +0 -369
- package/apps/studio/test/shared-doc-projection.test.ts +0 -238
- package/apps/studio/test/shell-importmap.test.ts +0 -56
- package/apps/studio/test/sizing-mode.test.ts +0 -102
- package/apps/studio/test/slash-commands.test.ts +0 -117
- package/apps/studio/test/snap-distance-pill.test.ts +0 -68
- package/apps/studio/test/spacing-handles.test.ts +0 -138
- package/apps/studio/test/specimen-select.test.ts +0 -88
- package/apps/studio/test/sync-agent.test.ts +0 -660
- package/apps/studio/test/sync-annotations-cold-start.test.ts +0 -302
- package/apps/studio/test/sync-asset-push.test.ts +0 -931
- package/apps/studio/test/sync-atomic-write.test.ts +0 -62
- package/apps/studio/test/sync-attach-incremental.test.ts +0 -527
- package/apps/studio/test/sync-autocommit.test.ts +0 -537
- package/apps/studio/test/sync-canvas-path.test.ts +0 -200
- package/apps/studio/test/sync-cell-write-nudge.test.ts +0 -346
- package/apps/studio/test/sync-codec.test.ts +0 -230
- package/apps/studio/test/sync-cold-seed-dedup.test.ts +0 -187
- package/apps/studio/test/sync-cold-start.test.ts +0 -304
- package/apps/studio/test/sync-connect-honesty.test.ts +0 -114
- package/apps/studio/test/sync-connection-state.test.ts +0 -337
- package/apps/studio/test/sync-ctl-channel.test.ts +0 -508
- package/apps/studio/test/sync-decide-file.test.ts +0 -420
- package/apps/studio/test/sync-doc-name.test.ts +0 -281
- package/apps/studio/test/sync-echo-guard.test.ts +0 -96
- package/apps/studio/test/sync-file-ledger.test.ts +0 -334
- package/apps/studio/test/sync-file-membership.test.ts +0 -347
- package/apps/studio/test/sync-file-plane.test.ts +0 -976
- package/apps/studio/test/sync-file-pull.test.ts +0 -333
- package/apps/studio/test/sync-fresh-link-parity.test.ts +0 -267
- package/apps/studio/test/sync-fs-mirror.test.ts +0 -181
- package/apps/studio/test/sync-hardening.test.ts +0 -586
- package/apps/studio/test/sync-hub-listing.test.ts +0 -46
- package/apps/studio/test/sync-hubs-config.test.ts +0 -133
- package/apps/studio/test/sync-incident-replay.test.ts +0 -211
- package/apps/studio/test/sync-journal.test.ts +0 -176
- package/apps/studio/test/sync-meta-codec.test.ts +0 -199
- package/apps/studio/test/sync-migrate-flat-fallback.test.ts +0 -98
- package/apps/studio/test/sync-move-retirement.test.ts +0 -231
- package/apps/studio/test/sync-panel-surface.test.ts +0 -153
- package/apps/studio/test/sync-path-pull.test.ts +0 -531
- package/apps/studio/test/sync-presentation.test.ts +0 -262
- package/apps/studio/test/sync-pull-budget.test.ts +0 -169
- package/apps/studio/test/sync-remote-docs.test.ts +0 -333
- package/apps/studio/test/sync-resync-routes.test.ts +0 -168
- package/apps/studio/test/sync-runtime.test.ts +0 -1675
- package/apps/studio/test/sync-seed-defers-to-hub.test.ts +0 -83
- package/apps/studio/test/sync-settings-routes.test.ts +0 -195
- package/apps/studio/test/sync-settings.test.ts +0 -151
- package/apps/studio/test/sync-status.test.ts +0 -261
- package/apps/studio/test/sync-supervisor.test.ts +0 -262
- package/apps/studio/test/sync-tombstone-apply.test.ts +0 -111
- package/apps/studio/test/sync-trash.test.ts +0 -132
- package/apps/studio/test/sync-two-peer-discovery.test.ts +0 -343
- package/apps/studio/test/sync-untrusted.test.ts +0 -103
- package/apps/studio/test/system-endpoint.test.ts +0 -144
- package/apps/studio/test/text-editability-stamp.test.ts +0 -131
- package/apps/studio/test/timeline-comp-target.test.ts +0 -139
- package/apps/studio/test/timeline-media-cache.test.ts +0 -41
- package/apps/studio/test/timeline-parse.test.ts +0 -184
- package/apps/studio/test/timeline-scale.test.ts +0 -65
- package/apps/studio/test/timeline-snap.test.ts +0 -85
- package/apps/studio/test/tool-palette-insert-anchor.test.ts +0 -86
- package/apps/studio/test/tool-palette.test.tsx +0 -55
- package/apps/studio/test/tour-overlay.test.tsx +0 -90
- package/apps/studio/test/trusted-request-host.test.ts +0 -66
- package/apps/studio/test/undo-sequence-byte-compare.test.ts +0 -211
- package/apps/studio/test/undo-stack.test.ts +0 -244
- package/apps/studio/test/use-agent-presence.test.tsx +0 -117
- package/apps/studio/test/use-annotation-resize.test.ts +0 -402
- package/apps/studio/test/use-annotation-selection.test.tsx +0 -77
- package/apps/studio/test/use-artboard-drag.test.ts +0 -324
- package/apps/studio/test/use-canvas-activity.test.tsx +0 -206
- package/apps/studio/test/use-collab.test.ts +0 -0
- package/apps/studio/test/use-cursor-modifiers.test.ts +0 -59
- package/apps/studio/test/use-keyboard-discipline.test.ts +0 -27
- package/apps/studio/test/use-selection-set.test.tsx +0 -166
- package/apps/studio/test/use-snap-guides.test.ts +0 -271
- package/apps/studio/test/use-tool-mode.test.tsx +0 -186
- package/apps/studio/test/use-undo-stack.test.tsx +0 -223
- package/apps/studio/test/video-asset.test.ts +0 -163
- package/apps/studio/test/video-comp-fixture.test.ts +0 -50
- package/apps/studio/test/video-comp.test.ts +0 -270
- package/apps/studio/test/video-encode-lib.test.ts +0 -63
- package/apps/studio/test/video-render-bridge.test.ts +0 -171
- package/apps/studio/test/whats-new.test.ts +0 -113
- package/apps/studio/test/whisper-setup.test.ts +0 -97
- package/apps/studio/test/workspace-containment.test.ts +0 -382
- package/apps/studio/test/workspace-signin.test.ts +0 -292
- package/apps/studio/test/ws-handshake.test.ts +0 -33
- package/cli/commands/cache.test.mjs +0 -166
- package/cli/commands/design-link.test.mjs +0 -419
- package/cli/commands/design.test.mjs +0 -240
- package/cli/commands/doctor.test.mjs +0 -237
- package/cli/commands/hub-workspace.test.mjs +0 -275
- package/cli/commands/hub.test.mjs +0 -225
- package/cli/commands/kg.test.mjs +0 -142
- package/cli/commands/preflight.test.mjs +0 -46
- package/cli/lib/argv.test.mjs +0 -46
- package/cli/lib/cache.test.mjs +0 -303
- package/cli/lib/cell-plan.test.mjs +0 -225
- package/cli/lib/config-lint.test.mjs +0 -117
- package/cli/lib/ddr-to-kgai.test.mjs +0 -118
- package/cli/lib/design-ownership.test.mjs +0 -329
- package/cli/lib/fetch-asset.test.mjs +0 -213
- package/cli/lib/figma-codegen-reachability.test.mjs +0 -104
- package/cli/lib/figma-import-controls.test.mjs +0 -70
- package/cli/lib/flow-design-integration.test.mjs +0 -165
- package/cli/lib/gitignore-block.test.mjs +0 -136
- package/cli/lib/gitignore-drift.test.mjs +0 -156
- package/cli/lib/hubs-config.test.mjs +0 -165
- package/cli/lib/pkg-root.test.mjs +0 -111
- package/cli/lib/plugin-cli-reachability.test.mjs +0 -57
- package/cli/lib/plugin-name-namespace.test.mjs +0 -71
- package/cli/lib/reconstruct-toolset.test.mjs +0 -194
- package/cli/lib/stack-detect.test.mjs +0 -121
- package/cli/lib/update-check.test.mjs +0 -32
- package/cli/lib/workspace-plan.test.mjs +0 -699
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
// Proves the session-capabilities channel end-to-end against a mock ACP agent
|
|
2
|
-
// (fixtures/mock-acp-agent-caps.mjs) — no real `claude` needed. Covers Tasks
|
|
3
|
-
// A1/A2/A3/A4 of feature-acp-panel-dynamic-claude-code-capabilities:
|
|
4
|
-
// • AcpBridge captures modes/configOptions from session/new and fires onCaps
|
|
5
|
-
// once the resume-replay window is closed.
|
|
6
|
-
// • AcpBridge.setMode/setConfigOption drive LIVE changes on an established
|
|
7
|
-
// session (no respawn) and the full refreshed configOptions echoes back.
|
|
8
|
-
// • setConfig's persisted model/effort/mode picks are applied ONCE, best-
|
|
9
|
-
// effort, right after a session establishes (never onto an already-live one).
|
|
10
|
-
// • The Acp manager (index.ts) validates `set-mode`/`set-config` frames
|
|
11
|
-
// against the bridge's last-advertised caps before ever calling the bridge
|
|
12
|
-
// (DDR-125 F1 — the dynamic replacement for VALID_MODELS/VALID_EFFORT).
|
|
13
|
-
|
|
14
|
-
import { afterEach, describe, expect, test } from 'bun:test';
|
|
15
|
-
import { mkdtemp, rm } from 'node:fs/promises';
|
|
16
|
-
import { tmpdir } from 'node:os';
|
|
17
|
-
import { join } from 'node:path';
|
|
18
|
-
|
|
19
|
-
import type { ServerWebSocket } from 'bun';
|
|
20
|
-
|
|
21
|
-
import { AcpBridge } from '../acp/bridge.ts';
|
|
22
|
-
import { createAcp } from '../acp/index.ts';
|
|
23
|
-
import type { Context } from '../context.ts';
|
|
24
|
-
import type { WsData } from '../ws.ts';
|
|
25
|
-
|
|
26
|
-
const FIXTURE = join(import.meta.dir, 'fixtures', 'mock-acp-agent-caps.mjs');
|
|
27
|
-
const TEST_ENV_KEYS = ['MAUDE_ACP_ADAPTER_ENTRY', 'MAUDE_ACP_RUNTIME', 'MAUDE_CLAUDE_BIN'];
|
|
28
|
-
|
|
29
|
-
function useMockAgent() {
|
|
30
|
-
process.env.MAUDE_ACP_ADAPTER_ENTRY = FIXTURE;
|
|
31
|
-
process.env.MAUDE_ACP_RUNTIME = process.execPath;
|
|
32
|
-
process.env.MAUDE_CLAUDE_BIN = process.execPath;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
afterEach(() => {
|
|
36
|
-
for (const key of TEST_ENV_KEYS) delete process.env[key];
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
async function until<T>(fn: () => T | undefined, timeoutMs = 12000): Promise<T> {
|
|
40
|
-
const start = performance.now();
|
|
41
|
-
for (;;) {
|
|
42
|
-
const v = fn();
|
|
43
|
-
if (v !== undefined) return v;
|
|
44
|
-
if (performance.now() - start > timeoutMs) throw new Error('timeout waiting for condition');
|
|
45
|
-
await new Promise((r) => setTimeout(r, 25));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function fakeWs(id: string) {
|
|
50
|
-
const frames: Array<Record<string, unknown>> = [];
|
|
51
|
-
const ws = {
|
|
52
|
-
data: { id } as WsData,
|
|
53
|
-
send: (raw: string) => {
|
|
54
|
-
frames.push(JSON.parse(raw));
|
|
55
|
-
},
|
|
56
|
-
} as unknown as ServerWebSocket<WsData>;
|
|
57
|
-
return { ws, frames };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
describe('AcpBridge — capability channel (Tasks A1/A2/A3)', () => {
|
|
61
|
-
test('onCaps fires with the initial modes + configOptions once a session establishes', async () => {
|
|
62
|
-
useMockAgent();
|
|
63
|
-
const caps: Array<[unknown, unknown]> = [];
|
|
64
|
-
const bridge = new AcpBridge({
|
|
65
|
-
repoRoot: process.cwd(),
|
|
66
|
-
onUpdate: () => {},
|
|
67
|
-
onCaps: (modes, configOptions) => caps.push([modes, configOptions]),
|
|
68
|
-
});
|
|
69
|
-
try {
|
|
70
|
-
await bridge.warmUp('c1');
|
|
71
|
-
const [modes, configOptions] = await until(() =>
|
|
72
|
-
caps.length ? caps[caps.length - 1] : undefined
|
|
73
|
-
);
|
|
74
|
-
expect((modes as { currentModeId: string }).currentModeId).toBe('default');
|
|
75
|
-
expect(
|
|
76
|
-
(modes as { availableModes: Array<{ id: string }> }).availableModes.map((m) => m.id)
|
|
77
|
-
).toEqual(['default', 'plan']);
|
|
78
|
-
const ids = (configOptions as Array<{ id: string }>).map((o) => o.id);
|
|
79
|
-
expect(ids).toEqual(['model', 'effort', 'mode']);
|
|
80
|
-
expect(bridge.modes?.currentModeId).toBe('default');
|
|
81
|
-
expect(bridge.configOptions.length).toBe(3);
|
|
82
|
-
} finally {
|
|
83
|
-
await bridge.stop();
|
|
84
|
-
}
|
|
85
|
-
}, 15000);
|
|
86
|
-
|
|
87
|
-
test('onSessionInfo fires with the agent-generated title', async () => {
|
|
88
|
-
useMockAgent();
|
|
89
|
-
const infos: Array<{ title?: string | null }> = [];
|
|
90
|
-
const bridge = new AcpBridge({
|
|
91
|
-
repoRoot: process.cwd(),
|
|
92
|
-
onUpdate: () => {},
|
|
93
|
-
onSessionInfo: (info) => infos.push(info),
|
|
94
|
-
});
|
|
95
|
-
try {
|
|
96
|
-
await bridge.warmUp('c1');
|
|
97
|
-
const info = await until(() => (infos.length ? infos[infos.length - 1] : undefined));
|
|
98
|
-
expect(info.title).toBe('New chat');
|
|
99
|
-
} finally {
|
|
100
|
-
await bridge.stop();
|
|
101
|
-
}
|
|
102
|
-
}, 15000);
|
|
103
|
-
|
|
104
|
-
test('setMode live-changes the mode on an established session (no respawn) and lastModes cross-derives from config_option_update', async () => {
|
|
105
|
-
useMockAgent();
|
|
106
|
-
const caps: Array<[unknown, unknown]> = [];
|
|
107
|
-
const bridge = new AcpBridge({
|
|
108
|
-
repoRoot: process.cwd(),
|
|
109
|
-
onUpdate: () => {},
|
|
110
|
-
onCaps: (modes, configOptions) => caps.push([modes, configOptions]),
|
|
111
|
-
});
|
|
112
|
-
try {
|
|
113
|
-
await bridge.warmUp('c1');
|
|
114
|
-
await until(() => (caps.length ? true : undefined));
|
|
115
|
-
const procBefore = bridge.connected;
|
|
116
|
-
|
|
117
|
-
await bridge.setMode('c1', 'plan');
|
|
118
|
-
await until(() => {
|
|
119
|
-
const last = caps[caps.length - 1];
|
|
120
|
-
const modes = last?.[0] as { currentModeId: string } | null;
|
|
121
|
-
return modes?.currentModeId === 'plan' ? true : undefined;
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
expect(bridge.connected).toBe(procBefore); // never tore down / respawned
|
|
125
|
-
expect(bridge.modes?.currentModeId).toBe('plan');
|
|
126
|
-
const modeOpt = bridge.configOptions.find((o) => o.id === 'mode') as
|
|
127
|
-
| { currentValue?: unknown }
|
|
128
|
-
| undefined;
|
|
129
|
-
expect(modeOpt?.currentValue).toBe('plan');
|
|
130
|
-
} finally {
|
|
131
|
-
await bridge.stop();
|
|
132
|
-
}
|
|
133
|
-
}, 15000);
|
|
134
|
-
|
|
135
|
-
test('setConfigOption live-changes the model and the FULL refreshed option set echoes back through onCaps', async () => {
|
|
136
|
-
useMockAgent();
|
|
137
|
-
const caps: Array<[unknown, unknown]> = [];
|
|
138
|
-
const bridge = new AcpBridge({
|
|
139
|
-
repoRoot: process.cwd(),
|
|
140
|
-
onUpdate: () => {},
|
|
141
|
-
onCaps: (modes, configOptions) => caps.push([modes, configOptions]),
|
|
142
|
-
});
|
|
143
|
-
try {
|
|
144
|
-
await bridge.warmUp('c1');
|
|
145
|
-
await until(() => (caps.length ? true : undefined));
|
|
146
|
-
expect(bridge.configOptions.some((o) => o.id === 'fast')).toBe(false);
|
|
147
|
-
|
|
148
|
-
await bridge.setConfigOption('c1', 'model', 'opus');
|
|
149
|
-
await until(() => (bridge.configOptions.some((o) => o.id === 'fast') ? true : undefined));
|
|
150
|
-
|
|
151
|
-
const modelOpt = bridge.configOptions.find((o) => o.id === 'model') as
|
|
152
|
-
| { currentValue?: unknown }
|
|
153
|
-
| undefined;
|
|
154
|
-
expect(modelOpt?.currentValue).toBe('opus');
|
|
155
|
-
// Switching to opus offers a NEW "fast" option in this fixture — proves
|
|
156
|
-
// the bridge feeds back the full refreshed set, not just the changed field.
|
|
157
|
-
expect(bridge.configOptions.some((o) => o.id === 'fast')).toBe(true);
|
|
158
|
-
} finally {
|
|
159
|
-
await bridge.stop();
|
|
160
|
-
}
|
|
161
|
-
}, 15000);
|
|
162
|
-
|
|
163
|
-
test('setConfig persists a pick applied ONCE on a fresh session — never forced onto an already-live one', async () => {
|
|
164
|
-
useMockAgent();
|
|
165
|
-
const bridge = new AcpBridge({ repoRoot: process.cwd(), onUpdate: () => {} });
|
|
166
|
-
try {
|
|
167
|
-
bridge.setConfig('opus', 'high', 'plan');
|
|
168
|
-
await bridge.warmUp('c1');
|
|
169
|
-
await until(() => (bridge.configOptions.length ? true : undefined));
|
|
170
|
-
|
|
171
|
-
const modelOpt = bridge.configOptions.find((o) => o.id === 'model') as
|
|
172
|
-
| { currentValue?: unknown }
|
|
173
|
-
| undefined;
|
|
174
|
-
const effortOpt = bridge.configOptions.find((o) => o.id === 'effort') as
|
|
175
|
-
| { currentValue?: unknown }
|
|
176
|
-
| undefined;
|
|
177
|
-
expect(modelOpt?.currentValue).toBe('opus');
|
|
178
|
-
expect(effortOpt?.currentValue).toBe('high');
|
|
179
|
-
expect(bridge.modes?.currentModeId).toBe('plan');
|
|
180
|
-
|
|
181
|
-
// A DIFFERENT persisted pick set later must NOT retroactively change this
|
|
182
|
-
// already-established chat — it only affects the NEXT fresh session.
|
|
183
|
-
bridge.setConfig('sonnet', 'default', 'default');
|
|
184
|
-
await bridge.prompt('hi', 'c1');
|
|
185
|
-
const modelAfter = bridge.configOptions.find((o) => o.id === 'model') as
|
|
186
|
-
| { currentValue?: unknown }
|
|
187
|
-
| undefined;
|
|
188
|
-
expect(modelAfter?.currentValue).toBe('opus'); // unchanged — no forced respawn
|
|
189
|
-
} finally {
|
|
190
|
-
await bridge.stop();
|
|
191
|
-
}
|
|
192
|
-
}, 15000);
|
|
193
|
-
|
|
194
|
-
test('an unsupported persisted pick is skipped, not thrown — the session keeps its own default', async () => {
|
|
195
|
-
useMockAgent();
|
|
196
|
-
const bridge = new AcpBridge({ repoRoot: process.cwd(), onUpdate: () => {} });
|
|
197
|
-
try {
|
|
198
|
-
bridge.setConfig('does-not-exist-model', null, 'does-not-exist-mode');
|
|
199
|
-
await bridge.warmUp('c1'); // must not throw
|
|
200
|
-
await until(() => (bridge.configOptions.length ? true : undefined));
|
|
201
|
-
const modelOpt = bridge.configOptions.find((o) => o.id === 'model') as
|
|
202
|
-
| { currentValue?: unknown }
|
|
203
|
-
| undefined;
|
|
204
|
-
expect(modelOpt?.currentValue).toBe('sonnet'); // session's own default, untouched
|
|
205
|
-
expect(bridge.modes?.currentModeId).toBe('default');
|
|
206
|
-
} finally {
|
|
207
|
-
await bridge.stop();
|
|
208
|
-
}
|
|
209
|
-
}, 15000);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
describe('Acp manager — set-mode/set-config frames validate against last-advertised caps (DDR-125 F1)', () => {
|
|
213
|
-
test('a caps frame is broadcast on establish; set-mode/set-config apply live; unadvertised values are rejected silently', async () => {
|
|
214
|
-
useMockAgent();
|
|
215
|
-
const designRoot = await mkdtemp(join(tmpdir(), 'acp-caps-test-'));
|
|
216
|
-
const ctx = { paths: { repoRoot: process.cwd(), designRoot } } as unknown as Context;
|
|
217
|
-
const acp = createAcp(ctx);
|
|
218
|
-
|
|
219
|
-
const a = fakeWs('caps-ws-a');
|
|
220
|
-
try {
|
|
221
|
-
acp.onOpen(a.ws);
|
|
222
|
-
acp.onMessage(a.ws, JSON.stringify({ t: 'warm', chat: 'c1' }));
|
|
223
|
-
const capsFrame = await until(() => a.frames.find((f) => f.t === 'caps'));
|
|
224
|
-
expect((capsFrame.modes as { currentModeId: string }).currentModeId).toBe('default');
|
|
225
|
-
|
|
226
|
-
// Valid live mode change — advertised by the caps frame above.
|
|
227
|
-
acp.onMessage(a.ws, JSON.stringify({ t: 'set-mode', chat: 'c1', modeId: 'plan' }));
|
|
228
|
-
await until(() =>
|
|
229
|
-
a.frames.find(
|
|
230
|
-
(f) =>
|
|
231
|
-
f.t === 'caps' &&
|
|
232
|
-
(f.modes as { currentModeId?: string } | null)?.currentModeId === 'plan'
|
|
233
|
-
)
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
// An unadvertised modeId must be rejected BEFORE ever reaching the bridge
|
|
237
|
-
// — no new caps frame, no error frame, no crash.
|
|
238
|
-
const framesBefore = a.frames.length;
|
|
239
|
-
acp.onMessage(
|
|
240
|
-
a.ws,
|
|
241
|
-
JSON.stringify({ t: 'set-mode', chat: 'c1', modeId: 'bypassPermissions' })
|
|
242
|
-
);
|
|
243
|
-
await new Promise((r) => setTimeout(r, 150));
|
|
244
|
-
expect(a.frames.length).toBe(framesBefore); // nothing new sent
|
|
245
|
-
|
|
246
|
-
// An unadvertised config value is likewise rejected pre-call.
|
|
247
|
-
acp.onMessage(
|
|
248
|
-
a.ws,
|
|
249
|
-
JSON.stringify({ t: 'set-config', chat: 'c1', configId: 'model', value: 'gpt-5' })
|
|
250
|
-
);
|
|
251
|
-
await new Promise((r) => setTimeout(r, 150));
|
|
252
|
-
expect(a.frames.length).toBe(framesBefore);
|
|
253
|
-
|
|
254
|
-
// A valid config change still works after the rejected attempts.
|
|
255
|
-
acp.onMessage(
|
|
256
|
-
a.ws,
|
|
257
|
-
JSON.stringify({ t: 'set-config', chat: 'c1', configId: 'model', value: 'opus' })
|
|
258
|
-
);
|
|
259
|
-
await until(() =>
|
|
260
|
-
a.frames.find(
|
|
261
|
-
(f) =>
|
|
262
|
-
f.t === 'caps' &&
|
|
263
|
-
(f.configOptions as Array<{ id: string; currentValue?: unknown }>).find(
|
|
264
|
-
(o) => o.id === 'model'
|
|
265
|
-
)?.currentValue === 'opus'
|
|
266
|
-
)
|
|
267
|
-
);
|
|
268
|
-
} finally {
|
|
269
|
-
acp.onClose(a.ws);
|
|
270
|
-
// Task 8 — `onClose` DETACHES now; it no longer stops the bridge (that is
|
|
271
|
-
// the point: a page reload must not kill a running turn). So a test that
|
|
272
|
-
// relied on socket-close for teardown leaks the adapter subprocess for the
|
|
273
|
-
// whole DETACHED_TTL_MS. Tear down explicitly.
|
|
274
|
-
acp.stopAll();
|
|
275
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
276
|
-
await rm(designRoot, { recursive: true, force: true });
|
|
277
|
-
}
|
|
278
|
-
}, 20000);
|
|
279
|
-
});
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// Proves the slash-command catalogue path end-to-end against a mock ACP agent
|
|
2
|
-
// (fixtures/mock-acp-agent-commands.mjs) — no real `claude` needed:
|
|
3
|
-
// • AcpBridge.warmUp() creates a session (no prompt) and surfaces the agent's
|
|
4
|
-
// `available_commands_update` via onCommands.
|
|
5
|
-
// • The Acp manager caches it, broadcasts a `{t:'commands'}` frame, and replays
|
|
6
|
-
// the cached list to a freshly-opened socket.
|
|
7
|
-
|
|
8
|
-
import { afterEach, describe, expect, test } from 'bun:test';
|
|
9
|
-
import { mkdtemp, rm } from 'node:fs/promises';
|
|
10
|
-
import { tmpdir } from 'node:os';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
|
|
13
|
-
import type { ServerWebSocket } from 'bun';
|
|
14
|
-
|
|
15
|
-
import { AcpBridge } from '../acp/bridge.ts';
|
|
16
|
-
import { createAcp } from '../acp/index.ts';
|
|
17
|
-
import type { Context } from '../context.ts';
|
|
18
|
-
import type { WsData } from '../ws.ts';
|
|
19
|
-
|
|
20
|
-
const FIXTURE = join(import.meta.dir, 'fixtures', 'mock-acp-agent-commands.mjs');
|
|
21
|
-
const TEST_ENV_KEYS = ['MAUDE_ACP_ADAPTER_ENTRY', 'MAUDE_ACP_RUNTIME', 'MAUDE_CLAUDE_BIN'];
|
|
22
|
-
|
|
23
|
-
function useMockAgent() {
|
|
24
|
-
process.env.MAUDE_ACP_ADAPTER_ENTRY = FIXTURE;
|
|
25
|
-
process.env.MAUDE_ACP_RUNTIME = process.execPath;
|
|
26
|
-
process.env.MAUDE_CLAUDE_BIN = process.execPath;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
for (const key of TEST_ENV_KEYS) delete process.env[key];
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
async function until<T>(fn: () => T | undefined, timeoutMs = 12000): Promise<T> {
|
|
34
|
-
const start = performance.now();
|
|
35
|
-
for (;;) {
|
|
36
|
-
const v = fn();
|
|
37
|
-
if (v !== undefined) return v;
|
|
38
|
-
if (performance.now() - start > timeoutMs) throw new Error('timeout waiting for condition');
|
|
39
|
-
await new Promise((r) => setTimeout(r, 25));
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Minimal fake ServerWebSocket capturing every sent frame. */
|
|
44
|
-
function fakeWs(id: string) {
|
|
45
|
-
const frames: Array<Record<string, unknown>> = [];
|
|
46
|
-
const ws = {
|
|
47
|
-
data: { id } as WsData,
|
|
48
|
-
send: (raw: string) => {
|
|
49
|
-
frames.push(JSON.parse(raw));
|
|
50
|
-
},
|
|
51
|
-
} as unknown as ServerWebSocket<WsData>;
|
|
52
|
-
return { ws, frames };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
describe('AcpBridge.warmUp — publishes the command catalogue without a prompt', () => {
|
|
56
|
-
test('onCommands fires with the agent catalogue on warm-up', async () => {
|
|
57
|
-
useMockAgent();
|
|
58
|
-
const seen: Array<Array<{ name: string }>> = [];
|
|
59
|
-
const bridge = new AcpBridge({
|
|
60
|
-
repoRoot: process.cwd(),
|
|
61
|
-
onUpdate: () => {},
|
|
62
|
-
onCommands: (cmds) => seen.push(cmds as Array<{ name: string }>),
|
|
63
|
-
});
|
|
64
|
-
try {
|
|
65
|
-
await bridge.warmUp('c1');
|
|
66
|
-
expect(bridge.connected).toBe(true);
|
|
67
|
-
const cmds = await until(() => (seen.length ? seen[seen.length - 1] : undefined));
|
|
68
|
-
expect(cmds.map((c) => c.name)).toEqual(['design:edit', 'flow:plan']);
|
|
69
|
-
} finally {
|
|
70
|
-
await bridge.stop();
|
|
71
|
-
}
|
|
72
|
-
}, 20000);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('Acp manager — warm frame broadcasts + open replays commands', () => {
|
|
76
|
-
test('a {t:warm} frame yields a {t:commands} frame, replayed to a new socket', async () => {
|
|
77
|
-
useMockAgent();
|
|
78
|
-
// Isolated tmp designRoot — `warm` now also writes a session-store sidecar
|
|
79
|
-
// (bridge.ts sessionFor's resume path), so this must not land in a real
|
|
80
|
-
// repo path.
|
|
81
|
-
const designRoot = await mkdtemp(join(tmpdir(), 'acp-commands-test-'));
|
|
82
|
-
const ctx = { paths: { repoRoot: process.cwd(), designRoot } } as unknown as Context;
|
|
83
|
-
const acp = createAcp(ctx);
|
|
84
|
-
|
|
85
|
-
const a = fakeWs('ws-a');
|
|
86
|
-
try {
|
|
87
|
-
acp.onOpen(a.ws);
|
|
88
|
-
// first frame is `ready`; no cached commands yet on a cold manager
|
|
89
|
-
expect(a.frames[0]).toMatchObject({ t: 'ready' });
|
|
90
|
-
expect(a.frames.some((f) => f.t === 'commands')).toBe(false);
|
|
91
|
-
|
|
92
|
-
acp.onMessage(a.ws, JSON.stringify({ t: 'warm', chat: 'c1' }));
|
|
93
|
-
const cmdFrame = await until(() => a.frames.find((f) => f.t === 'commands'));
|
|
94
|
-
expect((cmdFrame.commands as Array<{ name: string }>).map((c) => c.name)).toEqual([
|
|
95
|
-
'design:edit',
|
|
96
|
-
'flow:plan',
|
|
97
|
-
]);
|
|
98
|
-
|
|
99
|
-
// a second socket opening now replays the cached catalogue immediately
|
|
100
|
-
const b = fakeWs('ws-b');
|
|
101
|
-
acp.onOpen(b.ws);
|
|
102
|
-
const replay = b.frames.find((f) => f.t === 'commands');
|
|
103
|
-
expect(replay).toBeDefined();
|
|
104
|
-
const replayCommands = replay?.commands as Array<{ name: string }>;
|
|
105
|
-
expect(replayCommands.length).toBe(2);
|
|
106
|
-
acp.onClose(b.ws);
|
|
107
|
-
} finally {
|
|
108
|
-
acp.onClose(a.ws);
|
|
109
|
-
// Task 8 — `onClose` DETACHES now; it no longer stops the bridge (that is
|
|
110
|
-
// the point: a page reload must not kill a running turn). So a test that
|
|
111
|
-
// relied on socket-close for teardown leaks the adapter subprocess for the
|
|
112
|
-
// whole DETACHED_TTL_MS. Tear down explicitly.
|
|
113
|
-
acp.stopAll();
|
|
114
|
-
// give teardown a tick to kill the subprocess
|
|
115
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
116
|
-
await rm(designRoot, { recursive: true, force: true });
|
|
117
|
-
}
|
|
118
|
-
}, 20000);
|
|
119
|
-
});
|