@vellumai/assistant 0.4.17 → 0.4.19
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/docs/runbook-trusted-contacts.md +5 -3
- package/eslint.config.mjs +2 -2
- package/package.json +1 -1
- package/src/__tests__/access-request-decision.test.ts +128 -120
- package/src/__tests__/account-registry.test.ts +121 -110
- package/src/__tests__/active-skill-tools.test.ts +200 -172
- package/src/__tests__/actor-token-service.test.ts +341 -274
- package/src/__tests__/agent-loop-thinking.test.ts +28 -19
- package/src/__tests__/agent-loop.test.ts +798 -378
- package/src/__tests__/anthropic-provider.test.ts +405 -247
- package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
- package/src/__tests__/app-bundler.test.ts +112 -79
- package/src/__tests__/app-executors.test.ts +205 -178
- package/src/__tests__/app-git-history.test.ts +90 -73
- package/src/__tests__/app-git-service.test.ts +67 -53
- package/src/__tests__/app-open-proxy.test.ts +29 -25
- package/src/__tests__/approval-conversation-turn.test.ts +100 -81
- package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
- package/src/__tests__/approval-message-composer.test.ts +119 -119
- package/src/__tests__/approval-primitive.test.ts +264 -233
- package/src/__tests__/approval-routes-http.test.ts +4 -3
- package/src/__tests__/asset-materialize-tool.test.ts +250 -178
- package/src/__tests__/asset-search-tool.test.ts +251 -191
- package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
- package/src/__tests__/assistant-attachments.test.ts +254 -186
- package/src/__tests__/assistant-event-hub.test.ts +105 -63
- package/src/__tests__/assistant-event.test.ts +66 -58
- package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
- package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
- package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
- package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
- package/src/__tests__/attachments-store.test.ts +240 -183
- package/src/__tests__/attachments.test.ts +70 -62
- package/src/__tests__/audit-log-rotation.test.ts +50 -35
- package/src/__tests__/browser-fill-credential.test.ts +169 -101
- package/src/__tests__/browser-manager.test.ts +97 -75
- package/src/__tests__/browser-runtime-check.test.ts +16 -15
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
- package/src/__tests__/browser-skill-endstate.test.ts +97 -72
- package/src/__tests__/bundle-scanner.test.ts +47 -22
- package/src/__tests__/bundled-asset.test.ts +74 -47
- package/src/__tests__/call-constants.test.ts +19 -19
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-conversation-messages.test.ts +90 -65
- package/src/__tests__/call-domain.test.ts +149 -121
- package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
- package/src/__tests__/call-pointer-messages.test.ts +213 -154
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
- package/src/__tests__/call-recovery.test.ts +232 -212
- package/src/__tests__/call-routes-http.test.ts +0 -1
- package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
- package/src/__tests__/call-state-machine.test.ts +62 -51
- package/src/__tests__/call-state.test.ts +89 -75
- package/src/__tests__/call-store.test.ts +387 -316
- package/src/__tests__/callback-handoff-copy.test.ts +84 -82
- package/src/__tests__/canonical-guardian-store.test.ts +331 -280
- package/src/__tests__/channel-approval-routes.test.ts +1643 -1115
- package/src/__tests__/channel-approval.test.ts +139 -137
- package/src/__tests__/channel-approvals.test.ts +7 -2
- package/src/__tests__/channel-delivery-store.test.ts +232 -194
- package/src/__tests__/channel-guardian.test.ts +5 -3
- package/src/__tests__/channel-invite-transport.test.ts +107 -92
- package/src/__tests__/channel-policy.test.ts +42 -38
- package/src/__tests__/channel-readiness-service.test.ts +119 -102
- package/src/__tests__/channel-reply-delivery.test.ts +147 -118
- package/src/__tests__/channel-retry-sweep.test.ts +153 -110
- package/src/__tests__/checker.test.ts +3309 -1850
- package/src/__tests__/clarification-resolver.test.ts +91 -79
- package/src/__tests__/classifier.test.ts +64 -54
- package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
- package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
- package/src/__tests__/clawhub.test.ts +92 -82
- package/src/__tests__/cli.test.ts +30 -30
- package/src/__tests__/clipboard.test.ts +53 -46
- package/src/__tests__/commit-guarantee.test.ts +59 -52
- package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
- package/src/__tests__/compaction.benchmark.test.ts +33 -31
- package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
- package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
- package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
- package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
- package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
- package/src/__tests__/computer-use-tools.test.ts +121 -98
- package/src/__tests__/config-schema.test.ts +443 -347
- package/src/__tests__/config-watcher.test.ts +96 -81
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
- package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
- package/src/__tests__/conflict-policy.test.ts +151 -80
- package/src/__tests__/conflict-store.test.ts +203 -157
- package/src/__tests__/connection-policy.test.ts +89 -59
- package/src/__tests__/contacts-tools.test.ts +247 -178
- package/src/__tests__/context-memory-e2e.test.ts +306 -214
- package/src/__tests__/context-token-estimator.test.ts +114 -74
- package/src/__tests__/context-window-manager.test.ts +269 -167
- package/src/__tests__/contradiction-checker.test.ts +161 -135
- package/src/__tests__/conversation-attention-store.test.ts +350 -290
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-pairing.test.ts +220 -113
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
- package/src/__tests__/conversation-store.test.ts +390 -235
- package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
- package/src/__tests__/credential-broker-server-use.test.ts +283 -243
- package/src/__tests__/credential-broker.test.ts +128 -74
- package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
- package/src/__tests__/credential-metadata-store.test.ts +360 -311
- package/src/__tests__/credential-policy-validate.test.ts +81 -65
- package/src/__tests__/credential-resolve.test.ts +212 -145
- package/src/__tests__/credential-security-e2e.test.ts +144 -103
- package/src/__tests__/credential-security-invariants.test.ts +253 -208
- package/src/__tests__/credential-selection.test.ts +254 -146
- package/src/__tests__/credential-vault-unit.test.ts +531 -341
- package/src/__tests__/credential-vault.test.ts +761 -484
- package/src/__tests__/daemon-assistant-events.test.ts +91 -66
- package/src/__tests__/daemon-lifecycle.test.ts +258 -190
- package/src/__tests__/daemon-server-session-init.test.ts +2 -1
- package/src/__tests__/date-context.test.ts +314 -249
- package/src/__tests__/db-migration-rollback.test.ts +259 -130
- package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
- package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
- package/src/__tests__/dictation-mode-detection.test.ts +77 -55
- package/src/__tests__/dictation-profile-store.test.ts +70 -56
- package/src/__tests__/dictation-text-processing.test.ts +53 -35
- package/src/__tests__/diff.test.ts +102 -98
- package/src/__tests__/domain-normalize.test.ts +54 -54
- package/src/__tests__/domain-policy.test.ts +71 -55
- package/src/__tests__/dynamic-page-surface.test.ts +31 -33
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
- package/src/__tests__/edit-engine.test.ts +56 -56
- package/src/__tests__/elevenlabs-client.test.ts +117 -91
- package/src/__tests__/elevenlabs-config.test.ts +32 -31
- package/src/__tests__/email-classifier.test.ts +15 -12
- package/src/__tests__/email-cli.test.ts +121 -108
- package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
- package/src/__tests__/encrypted-store.test.ts +180 -154
- package/src/__tests__/entity-extractor.test.ts +108 -87
- package/src/__tests__/entity-search.test.ts +664 -258
- package/src/__tests__/ephemeral-permissions.test.ts +224 -188
- package/src/__tests__/event-bus.test.ts +81 -77
- package/src/__tests__/extract-email.test.ts +29 -20
- package/src/__tests__/file-edit-tool.test.ts +62 -44
- package/src/__tests__/file-ops-service.test.ts +131 -114
- package/src/__tests__/file-read-tool.test.ts +48 -31
- package/src/__tests__/file-write-tool.test.ts +43 -37
- package/src/__tests__/filesystem-tools.test.ts +238 -209
- package/src/__tests__/followup-tools.test.ts +237 -162
- package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
- package/src/__tests__/frontmatter.test.ts +96 -81
- package/src/__tests__/fuzzy-match-property.test.ts +75 -81
- package/src/__tests__/fuzzy-match.test.ts +71 -65
- package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-image-service.test.ts +113 -100
- package/src/__tests__/gemini-provider.test.ts +297 -220
- package/src/__tests__/get-weather.test.ts +188 -114
- package/src/__tests__/gmail-integration.test.ts +13 -5
- package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
- package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
- package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
- package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
- package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
- package/src/__tests__/guardian-action-store.test.ts +158 -109
- package/src/__tests__/guardian-action-sweep.test.ts +114 -100
- package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
- package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
- package/src/__tests__/guardian-dispatch.test.ts +316 -256
- package/src/__tests__/guardian-grant-minting.test.ts +247 -178
- package/src/__tests__/guardian-outbound-http.test.ts +5 -3
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
- package/src/__tests__/guardian-question-copy.test.ts +17 -17
- package/src/__tests__/guardian-question-mode.test.ts +134 -100
- package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
- package/src/__tests__/handle-user-message-secret-resume.test.ts +7 -2
- package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
- package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
- package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
- package/src/__tests__/handlers-slack-config.test.ts +63 -54
- package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
- package/src/__tests__/handlers-telegram-config.test.ts +662 -329
- package/src/__tests__/handlers-twitter-config.test.ts +525 -298
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +5 -2
- package/src/__tests__/headless-browser-interactions.test.ts +444 -280
- package/src/__tests__/headless-browser-navigate.test.ts +116 -79
- package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
- package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
- package/src/__tests__/heartbeat-service.test.ts +76 -58
- package/src/__tests__/history-repair-observability.test.ts +14 -14
- package/src/__tests__/history-repair.test.ts +171 -167
- package/src/__tests__/home-base-bootstrap.test.ts +30 -27
- package/src/__tests__/hooks-blocking.test.ts +86 -37
- package/src/__tests__/hooks-cli.test.ts +104 -68
- package/src/__tests__/hooks-config.test.ts +81 -43
- package/src/__tests__/hooks-discovery.test.ts +106 -96
- package/src/__tests__/hooks-integration.test.ts +78 -72
- package/src/__tests__/hooks-manager.test.ts +99 -61
- package/src/__tests__/hooks-runner.test.ts +94 -71
- package/src/__tests__/hooks-settings.test.ts +69 -64
- package/src/__tests__/hooks-templates.test.ts +85 -54
- package/src/__tests__/hooks-ts-runner.test.ts +82 -45
- package/src/__tests__/hooks-watch.test.ts +32 -22
- package/src/__tests__/host-file-edit-tool.test.ts +190 -148
- package/src/__tests__/host-file-read-tool.test.ts +86 -63
- package/src/__tests__/host-file-write-tool.test.ts +98 -64
- package/src/__tests__/host-shell-tool.test.ts +342 -233
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
- package/src/__tests__/ingress-member-store.test.ts +163 -159
- package/src/__tests__/ingress-reconcile.test.ts +13 -6
- package/src/__tests__/ingress-routes-http.test.ts +441 -356
- package/src/__tests__/ingress-url-consistency.test.ts +125 -64
- package/src/__tests__/integration-status.test.ts +93 -73
- package/src/__tests__/intent-routing.test.ts +148 -118
- package/src/__tests__/invite-redemption-service.test.ts +163 -121
- package/src/__tests__/ipc-blob-store.test.ts +104 -91
- package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
- package/src/__tests__/ipc-contract.test.ts +24 -23
- package/src/__tests__/ipc-protocol.test.ts +52 -46
- package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
- package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
- package/src/__tests__/ipc-validate.test.ts +240 -179
- package/src/__tests__/key-migration.test.ts +123 -90
- package/src/__tests__/keychain.test.ts +150 -123
- package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
- package/src/__tests__/llm-usage-store.test.ts +112 -87
- package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
- package/src/__tests__/managed-store.test.ts +411 -360
- package/src/__tests__/mcp-cli.test.ts +190 -124
- package/src/__tests__/mcp-health-check.test.ts +26 -21
- package/src/__tests__/media-generate-image.test.ts +122 -99
- package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
- package/src/__tests__/media-visibility-policy.test.ts +86 -38
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
- package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
- package/src/__tests__/memory-query-builder.test.ts +32 -33
- package/src/__tests__/memory-recall-quality.test.ts +761 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
- package/src/__tests__/memory-regressions.test.ts +3725 -2642
- package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
- package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
- package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
- package/src/__tests__/messaging-send-tool.test.ts +36 -29
- package/src/__tests__/migration-cli-flows.test.ts +69 -53
- package/src/__tests__/migration-ordering.test.ts +103 -86
- package/src/__tests__/mime-builder.test.ts +55 -32
- package/src/__tests__/mock-signup-server.test.ts +384 -246
- package/src/__tests__/model-intents.test.ts +61 -37
- package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
- package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
- package/src/__tests__/non-member-access-request.test.ts +3 -2
- package/src/__tests__/notification-broadcaster.test.ts +99 -81
- package/src/__tests__/notification-decision-fallback.test.ts +223 -178
- package/src/__tests__/notification-decision-strategy.test.ts +375 -337
- package/src/__tests__/notification-deep-link.test.ts +67 -61
- package/src/__tests__/notification-guardian-path.test.ts +248 -206
- package/src/__tests__/notification-routing-intent.test.ts +166 -93
- package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
- package/src/__tests__/notification-thread-candidates.test.ts +64 -61
- package/src/__tests__/oauth-callback-registry.test.ts +40 -30
- package/src/__tests__/oauth-connect-handler.test.ts +109 -89
- package/src/__tests__/oauth-scope-policy.test.ts +63 -55
- package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
- package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
- package/src/__tests__/onboarding-template-contract.test.ts +93 -94
- package/src/__tests__/openai-provider.test.ts +366 -274
- package/src/__tests__/pairing-concurrent.test.ts +18 -12
- package/src/__tests__/pairing-routes.test.ts +45 -41
- package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
- package/src/__tests__/parser.test.ts +316 -226
- package/src/__tests__/path-classifier.test.ts +24 -25
- package/src/__tests__/path-policy.test.ts +187 -147
- package/src/__tests__/phone.test.ts +36 -36
- package/src/__tests__/platform-move-helper.test.ts +48 -40
- package/src/__tests__/platform-socket-path.test.ts +23 -24
- package/src/__tests__/platform-workspace-migration.test.ts +464 -414
- package/src/__tests__/platform.test.ts +61 -53
- package/src/__tests__/playbook-execution.test.ts +397 -265
- package/src/__tests__/playbook-tools.test.ts +267 -196
- package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
- package/src/__tests__/pricing.test.ts +316 -136
- package/src/__tests__/profile-compiler.test.ts +206 -188
- package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
- package/src/__tests__/provider-error-scenarios.test.ts +212 -158
- package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
- package/src/__tests__/provider-registry-ollama.test.ts +13 -9
- package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
- package/src/__tests__/proxy-approval-callback.test.ts +180 -119
- package/src/__tests__/public-ingress-urls.test.ts +112 -94
- package/src/__tests__/qdrant-manager.test.ts +147 -98
- package/src/__tests__/ratelimit.test.ts +152 -82
- package/src/__tests__/recording-handler.test.ts +273 -151
- package/src/__tests__/recording-intent-fallback.test.ts +94 -75
- package/src/__tests__/recording-intent-handler.test.ts +9 -2
- package/src/__tests__/recording-intent.test.ts +578 -379
- package/src/__tests__/recording-state-machine.test.ts +530 -316
- package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
- package/src/__tests__/recurrence-engine.test.ts +81 -41
- package/src/__tests__/recurrence-types.test.ts +63 -44
- package/src/__tests__/relay-server.test.ts +2131 -1602
- package/src/__tests__/reminder-store.test.ts +158 -80
- package/src/__tests__/reminder.test.ts +113 -109
- package/src/__tests__/remote-skill-policy.test.ts +96 -72
- package/src/__tests__/request-file-tool.test.ts +74 -67
- package/src/__tests__/response-tier.test.ts +131 -74
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
- package/src/__tests__/runtime-events-sse.test.ts +0 -1
- package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
- package/src/__tests__/sandbox-host-parity.test.ts +377 -301
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
- package/src/__tests__/schedule-store.test.ts +268 -205
- package/src/__tests__/schedule-tools.test.ts +702 -524
- package/src/__tests__/scheduler-recurrence.test.ts +240 -130
- package/src/__tests__/scoped-approval-grants.test.ts +258 -168
- package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
- package/src/__tests__/script-proxy-certs.test.ts +38 -35
- package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
- package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
- package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
- package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
- package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
- package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
- package/src/__tests__/script-proxy-policy.test.ts +308 -153
- package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
- package/src/__tests__/script-proxy-router.test.ts +111 -77
- package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
- package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
- package/src/__tests__/secret-allowlist.test.ts +105 -90
- package/src/__tests__/secret-ingress-handler.test.ts +41 -30
- package/src/__tests__/secret-onetime-send.test.ts +67 -50
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
- package/src/__tests__/secret-response-routing.test.ts +50 -41
- package/src/__tests__/secret-scanner-executor.test.ts +152 -111
- package/src/__tests__/secret-scanner.test.ts +495 -413
- package/src/__tests__/secure-keys.test.ts +132 -121
- package/src/__tests__/send-endpoint-busy.test.ts +8 -3
- package/src/__tests__/send-notification-tool.test.ts +43 -42
- package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
- package/src/__tests__/sequence-store.test.ts +335 -167
- package/src/__tests__/server-history-render.test.ts +341 -202
- package/src/__tests__/session-abort-tool-results.test.ts +133 -70
- package/src/__tests__/session-confirmation-signals.test.ts +252 -160
- package/src/__tests__/session-conflict-gate.test.ts +775 -585
- package/src/__tests__/session-error.test.ts +222 -191
- package/src/__tests__/session-evictor.test.ts +79 -62
- package/src/__tests__/session-init.benchmark.test.ts +170 -108
- package/src/__tests__/session-load-history-repair.test.ts +273 -139
- package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
- package/src/__tests__/session-pre-run-repair.test.ts +106 -59
- package/src/__tests__/session-profile-injection.test.ts +198 -130
- package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
- package/src/__tests__/session-queue.test.ts +624 -321
- package/src/__tests__/session-runtime-assembly.test.ts +425 -329
- package/src/__tests__/session-runtime-workspace.test.ts +69 -61
- package/src/__tests__/session-skill-tools.test.ts +973 -678
- package/src/__tests__/session-slash-known.test.ts +185 -133
- package/src/__tests__/session-slash-queue.test.ts +147 -81
- package/src/__tests__/session-slash-unknown.test.ts +135 -90
- package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
- package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
- package/src/__tests__/session-undo.test.ts +43 -30
- package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
- package/src/__tests__/session-workspace-injection.test.ts +245 -117
- package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
- package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
- package/src/__tests__/shell-credential-ref.test.ts +126 -90
- package/src/__tests__/shell-identity.test.ts +134 -111
- package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
- package/src/__tests__/shell-parser-property.test.ts +435 -288
- package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
- package/src/__tests__/size-guard.test.ts +42 -44
- package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
- package/src/__tests__/skill-feature-flags.test.ts +75 -47
- package/src/__tests__/skill-include-graph.test.ts +143 -148
- package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
- package/src/__tests__/skill-load-tool.test.ts +371 -199
- package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
- package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
- package/src/__tests__/skill-script-runner-host.test.ts +460 -250
- package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
- package/src/__tests__/skill-script-runner.test.ts +115 -74
- package/src/__tests__/skill-tool-factory.test.ts +140 -96
- package/src/__tests__/skill-tool-manifest.test.ts +306 -210
- package/src/__tests__/skill-version-hash.test.ts +70 -56
- package/src/__tests__/skills.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +127 -84
- package/src/__tests__/slack-skill.test.ts +60 -47
- package/src/__tests__/slash-commands-catalog.test.ts +37 -31
- package/src/__tests__/slash-commands-parser.test.ts +71 -64
- package/src/__tests__/slash-commands-resolver.test.ts +143 -107
- package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
- package/src/__tests__/sms-messaging-provider.test.ts +4 -0
- package/src/__tests__/speaker-identification.test.ts +28 -25
- package/src/__tests__/starter-bundle.test.ts +27 -23
- package/src/__tests__/starter-task-flow.test.ts +67 -52
- package/src/__tests__/subagent-manager-notify.test.ts +154 -108
- package/src/__tests__/subagent-tools.test.ts +311 -270
- package/src/__tests__/subagent-types.test.ts +40 -40
- package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
- package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
- package/src/__tests__/swarm-orchestrator.test.ts +135 -101
- package/src/__tests__/swarm-plan-validator.test.ts +125 -73
- package/src/__tests__/swarm-recursion.test.ts +58 -46
- package/src/__tests__/swarm-router-planner.test.ts +99 -74
- package/src/__tests__/swarm-session-integration.test.ts +148 -91
- package/src/__tests__/swarm-tool.test.ts +65 -45
- package/src/__tests__/swarm-worker-backend.test.ts +59 -45
- package/src/__tests__/swarm-worker-runner.test.ts +133 -118
- package/src/__tests__/system-prompt.test.ts +311 -256
- package/src/__tests__/task-compiler.test.ts +176 -120
- package/src/__tests__/task-management-tools.test.ts +561 -456
- package/src/__tests__/task-memory-cleanup.test.ts +627 -362
- package/src/__tests__/task-runner.test.ts +117 -94
- package/src/__tests__/task-scheduler.test.ts +113 -84
- package/src/__tests__/task-tools.test.ts +349 -264
- package/src/__tests__/terminal-sandbox.test.ts +138 -108
- package/src/__tests__/terminal-tools.test.ts +350 -305
- package/src/__tests__/thread-seed-composer.test.ts +307 -180
- package/src/__tests__/tool-approval-handler.test.ts +238 -137
- package/src/__tests__/tool-audit-listener.test.ts +69 -69
- package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +155 -146
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
- package/src/__tests__/tool-executor-redaction.test.ts +112 -109
- package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
- package/src/__tests__/tool-executor.test.ts +1274 -674
- package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
- package/src/__tests__/tool-metrics-listener.test.ts +97 -85
- package/src/__tests__/tool-notification-listener.test.ts +42 -25
- package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
- package/src/__tests__/tool-policy.test.ts +44 -25
- package/src/__tests__/tool-profiling-listener.test.ts +99 -93
- package/src/__tests__/tool-result-truncation.test.ts +5 -4
- package/src/__tests__/tool-trace-listener.test.ts +131 -111
- package/src/__tests__/top-level-renderer.test.ts +62 -58
- package/src/__tests__/top-level-scanner.test.ts +68 -64
- package/src/__tests__/trace-emitter.test.ts +56 -56
- package/src/__tests__/trust-context-guards.test.ts +65 -65
- package/src/__tests__/trust-store.test.ts +1239 -806
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
- package/src/__tests__/trusted-contact-verification.test.ts +251 -231
- package/src/__tests__/turn-commit.test.ts +259 -200
- package/src/__tests__/twilio-provider.test.ts +140 -126
- package/src/__tests__/twilio-rest.test.ts +22 -18
- package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -1
- package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
- package/src/__tests__/twilio-routes.test.ts +0 -1
- package/src/__tests__/twitter-auth-handler.test.ts +184 -139
- package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
- package/src/__tests__/twitter-cli-routing.test.ts +146 -99
- package/src/__tests__/twitter-oauth-client.test.ts +82 -65
- package/src/__tests__/update-bulletin-format.test.ts +69 -66
- package/src/__tests__/update-bulletin-state.test.ts +66 -60
- package/src/__tests__/update-bulletin.test.ts +150 -114
- package/src/__tests__/update-template-contract.test.ts +15 -10
- package/src/__tests__/url-safety.test.ts +288 -265
- package/src/__tests__/user-reference.test.ts +32 -32
- package/src/__tests__/view-image-tool.test.ts +118 -96
- package/src/__tests__/voice-invite-redemption.test.ts +111 -106
- package/src/__tests__/voice-quality.test.ts +117 -102
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
- package/src/__tests__/voice-session-bridge.test.ts +351 -216
- package/src/__tests__/weather-skill-regression.test.ts +170 -120
- package/src/__tests__/web-fetch.test.ts +664 -526
- package/src/__tests__/web-search.test.ts +379 -213
- package/src/__tests__/work-item-output.test.ts +90 -53
- package/src/__tests__/workspace-git-service.test.ts +437 -356
- package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
- package/src/__tests__/workspace-lifecycle.test.ts +98 -64
- package/src/__tests__/workspace-policy.test.ts +139 -71
- package/src/cli/mcp.ts +81 -28
- package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +25 -10
- package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
- package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +6 -11
- package/src/config/bundled-skills/messaging/SKILL.md +4 -3
- package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
- package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -2
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
- package/src/config/bundled-skills/sms-setup/SKILL.md +8 -16
- package/src/config/bundled-skills/telegram-setup/SKILL.md +3 -3
- package/src/config/bundled-skills/trusted-contacts/SKILL.md +13 -25
- package/src/config/bundled-skills/twilio-setup/SKILL.md +13 -23
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/env.ts +3 -4
- package/src/config/system-prompt.ts +32 -0
- package/src/mcp/client.ts +2 -7
- package/src/memory/db-connection.ts +16 -10
- package/src/messaging/providers/gmail/adapter.ts +10 -3
- package/src/messaging/providers/gmail/client.ts +280 -72
- package/src/runtime/auth/__tests__/context.test.ts +75 -65
- package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
- package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
- package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
- package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
- package/src/runtime/auth/__tests__/policy.test.ts +9 -9
- package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
- package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
- package/src/runtime/auth/__tests__/subject.test.ts +54 -54
- package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
- package/src/runtime/auth/scopes.ts +3 -0
- package/src/runtime/auth/token-service.ts +4 -1
- package/src/runtime/auth/types.ts +2 -1
- package/src/runtime/http-server.ts +2 -1
- package/src/security/secure-keys.ts +120 -54
- package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
- package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
- package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
- package/src/tools/terminal/safe-env.ts +7 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { describe, expect,test } from
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type { AppDefinition } from
|
|
4
|
-
import type { AppStore, ProxyResolver } from
|
|
3
|
+
import type { AppDefinition } from "../memory/app-store.js";
|
|
4
|
+
import type { AppStore, ProxyResolver } from "../tools/apps/executors.js";
|
|
5
5
|
import {
|
|
6
6
|
executeAppCreate,
|
|
7
7
|
executeAppDelete,
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
executeAppList,
|
|
13
13
|
executeAppQuery,
|
|
14
14
|
executeAppUpdate,
|
|
15
|
-
} from
|
|
16
|
-
import type { EditEngineResult } from
|
|
15
|
+
} from "../tools/apps/executors.js";
|
|
16
|
+
import type { EditEngineResult } from "../tools/shared/filesystem/edit-engine.js";
|
|
17
17
|
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
// Mock factory
|
|
@@ -21,11 +21,11 @@ import type { EditEngineResult } from '../tools/shared/filesystem/edit-engine.js
|
|
|
21
21
|
|
|
22
22
|
function makeApp(overrides: Partial<AppDefinition> = {}): AppDefinition {
|
|
23
23
|
return {
|
|
24
|
-
id:
|
|
25
|
-
name:
|
|
26
|
-
description:
|
|
27
|
-
schemaJson:
|
|
28
|
-
htmlDefinition:
|
|
24
|
+
id: "app-1",
|
|
25
|
+
name: "Test App",
|
|
26
|
+
description: "A test app",
|
|
27
|
+
schemaJson: "{}",
|
|
28
|
+
htmlDefinition: "<h1>Hi</h1>",
|
|
29
29
|
createdAt: 1000,
|
|
30
30
|
updatedAt: 2000,
|
|
31
31
|
...overrides,
|
|
@@ -37,15 +37,23 @@ function makeMockStore(overrides: Partial<AppStore> = {}): AppStore {
|
|
|
37
37
|
getApp: () => makeApp(),
|
|
38
38
|
listApps: () => [makeApp()],
|
|
39
39
|
queryAppRecords: () => [],
|
|
40
|
-
listAppFiles: () => [
|
|
41
|
-
readAppFile: () =>
|
|
40
|
+
listAppFiles: () => ["index.html"],
|
|
41
|
+
readAppFile: () => "<h1>Hi</h1>",
|
|
42
42
|
createApp: (params) =>
|
|
43
43
|
makeApp({ name: params.name, description: params.description }),
|
|
44
44
|
updateApp: (id, updates) => makeApp({ id, ...updates }),
|
|
45
45
|
deleteApp: () => {},
|
|
46
46
|
writeAppFile: () => {},
|
|
47
47
|
editAppFile: () =>
|
|
48
|
-
({
|
|
48
|
+
({
|
|
49
|
+
ok: true,
|
|
50
|
+
updatedContent: "new",
|
|
51
|
+
matchCount: 1,
|
|
52
|
+
matchMethod: "exact",
|
|
53
|
+
similarity: 1,
|
|
54
|
+
actualOld: "old",
|
|
55
|
+
actualNew: "new",
|
|
56
|
+
}) as EditEngineResult,
|
|
49
57
|
...overrides,
|
|
50
58
|
};
|
|
51
59
|
}
|
|
@@ -54,16 +62,16 @@ function makeMockStore(overrides: Partial<AppStore> = {}): AppStore {
|
|
|
54
62
|
// app_create
|
|
55
63
|
// ---------------------------------------------------------------------------
|
|
56
64
|
|
|
57
|
-
describe(
|
|
58
|
-
test(
|
|
65
|
+
describe("executeAppCreate", () => {
|
|
66
|
+
test("creates an app and returns its definition", async () => {
|
|
59
67
|
const store = makeMockStore();
|
|
60
68
|
const result = await executeAppCreate(
|
|
61
|
-
{ name:
|
|
69
|
+
{ name: "My App", html: "<p>Hello</p>" },
|
|
62
70
|
store,
|
|
63
71
|
);
|
|
64
72
|
expect(result.isError).toBe(false);
|
|
65
73
|
const parsed = JSON.parse(result.content);
|
|
66
|
-
expect(parsed.name).toBe(
|
|
74
|
+
expect(parsed.name).toBe("My App");
|
|
67
75
|
});
|
|
68
76
|
|
|
69
77
|
test('defaults schema_json to "{}" when not provided', async () => {
|
|
@@ -74,11 +82,11 @@ describe('executeAppCreate', () => {
|
|
|
74
82
|
return makeApp({ name: params.name });
|
|
75
83
|
},
|
|
76
84
|
});
|
|
77
|
-
await executeAppCreate({ name:
|
|
78
|
-
expect(capturedSchema).toBe(
|
|
85
|
+
await executeAppCreate({ name: "App", html: "<p/>" }, store);
|
|
86
|
+
expect(capturedSchema).toBe("{}");
|
|
79
87
|
});
|
|
80
88
|
|
|
81
|
-
test(
|
|
89
|
+
test("passes schema_json through when provided", async () => {
|
|
82
90
|
let capturedSchema: string | undefined;
|
|
83
91
|
const store = makeMockStore({
|
|
84
92
|
createApp: (params) => {
|
|
@@ -87,36 +95,36 @@ describe('executeAppCreate', () => {
|
|
|
87
95
|
},
|
|
88
96
|
});
|
|
89
97
|
await executeAppCreate(
|
|
90
|
-
{ name:
|
|
98
|
+
{ name: "App", html: "<p/>", schema_json: '{"type":"object"}' },
|
|
91
99
|
store,
|
|
92
100
|
);
|
|
93
101
|
expect(capturedSchema).toBe('{"type":"object"}');
|
|
94
102
|
});
|
|
95
103
|
|
|
96
|
-
test(
|
|
104
|
+
test("auto-opens the app when proxyToolResolver is provided", async () => {
|
|
97
105
|
const store = makeMockStore();
|
|
98
106
|
const proxy: ProxyResolver = async () => ({
|
|
99
|
-
content:
|
|
107
|
+
content: "opened",
|
|
100
108
|
isError: false,
|
|
101
109
|
});
|
|
102
110
|
const result = await executeAppCreate(
|
|
103
|
-
{ name:
|
|
111
|
+
{ name: "Auto", html: "<p/>" },
|
|
104
112
|
store,
|
|
105
113
|
proxy,
|
|
106
114
|
);
|
|
107
115
|
expect(result.isError).toBe(false);
|
|
108
116
|
const parsed = JSON.parse(result.content);
|
|
109
117
|
expect(parsed.auto_opened).toBe(true);
|
|
110
|
-
expect(parsed.open_result).toBe(
|
|
118
|
+
expect(parsed.open_result).toBe("opened");
|
|
111
119
|
});
|
|
112
120
|
|
|
113
|
-
test(
|
|
121
|
+
test("returns auto_opened=false when proxy resolver throws", async () => {
|
|
114
122
|
const store = makeMockStore();
|
|
115
123
|
const proxy: ProxyResolver = async () => {
|
|
116
|
-
throw new Error(
|
|
124
|
+
throw new Error("no client");
|
|
117
125
|
};
|
|
118
126
|
const result = await executeAppCreate(
|
|
119
|
-
{ name:
|
|
127
|
+
{ name: "Fail Open", html: "<p/>" },
|
|
120
128
|
store,
|
|
121
129
|
proxy,
|
|
122
130
|
);
|
|
@@ -124,19 +132,19 @@ describe('executeAppCreate', () => {
|
|
|
124
132
|
const parsed = JSON.parse(result.content);
|
|
125
133
|
expect(parsed.auto_opened).toBe(false);
|
|
126
134
|
expect(parsed.auto_open_error).toBe(
|
|
127
|
-
|
|
135
|
+
"Failed to auto-open app. Use app_open to open it manually.",
|
|
128
136
|
);
|
|
129
137
|
});
|
|
130
138
|
|
|
131
|
-
test(
|
|
139
|
+
test("skips auto-open when auto_open is false", async () => {
|
|
132
140
|
let proxyCalled = false;
|
|
133
141
|
const store = makeMockStore();
|
|
134
142
|
const proxy: ProxyResolver = async () => {
|
|
135
143
|
proxyCalled = true;
|
|
136
|
-
return { content:
|
|
144
|
+
return { content: "opened", isError: false };
|
|
137
145
|
};
|
|
138
146
|
const result = await executeAppCreate(
|
|
139
|
-
{ name:
|
|
147
|
+
{ name: "No Open", html: "<p/>", auto_open: false },
|
|
140
148
|
store,
|
|
141
149
|
proxy,
|
|
142
150
|
);
|
|
@@ -146,10 +154,10 @@ describe('executeAppCreate', () => {
|
|
|
146
154
|
expect(parsed.auto_opened).toBeUndefined();
|
|
147
155
|
});
|
|
148
156
|
|
|
149
|
-
test(
|
|
157
|
+
test("skips auto-open when no proxyToolResolver", async () => {
|
|
150
158
|
const store = makeMockStore();
|
|
151
159
|
const result = await executeAppCreate(
|
|
152
|
-
{ name:
|
|
160
|
+
{ name: "No Proxy", html: "<p/>" },
|
|
153
161
|
store,
|
|
154
162
|
);
|
|
155
163
|
expect(result.isError).toBe(false);
|
|
@@ -157,7 +165,7 @@ describe('executeAppCreate', () => {
|
|
|
157
165
|
expect(parsed.auto_opened).toBeUndefined();
|
|
158
166
|
});
|
|
159
167
|
|
|
160
|
-
test(
|
|
168
|
+
test("passes pages through to store.createApp", async () => {
|
|
161
169
|
let capturedPages: Record<string, string> | undefined;
|
|
162
170
|
const store = makeMockStore({
|
|
163
171
|
createApp: (params) => {
|
|
@@ -166,37 +174,34 @@ describe('executeAppCreate', () => {
|
|
|
166
174
|
},
|
|
167
175
|
});
|
|
168
176
|
await executeAppCreate(
|
|
169
|
-
{ name:
|
|
177
|
+
{ name: "Multi", html: "<p/>", pages: { "settings.html": "<div/>" } },
|
|
170
178
|
store,
|
|
171
179
|
);
|
|
172
|
-
expect(capturedPages).toEqual({
|
|
180
|
+
expect(capturedPages).toEqual({ "settings.html": "<div/>" });
|
|
173
181
|
});
|
|
174
182
|
|
|
175
183
|
test('maps type "site" to appType "site"', async () => {
|
|
176
|
-
let capturedType:
|
|
184
|
+
let capturedType: "app" | "site" | undefined;
|
|
177
185
|
const store = makeMockStore({
|
|
178
186
|
createApp: (params) => {
|
|
179
187
|
capturedType = params.appType;
|
|
180
188
|
return makeApp({ name: params.name });
|
|
181
189
|
},
|
|
182
190
|
});
|
|
183
|
-
await executeAppCreate(
|
|
184
|
-
|
|
185
|
-
store,
|
|
186
|
-
);
|
|
187
|
-
expect(capturedType).toBe('site');
|
|
191
|
+
await executeAppCreate({ name: "Site", html: "<p/>", type: "site" }, store);
|
|
192
|
+
expect(capturedType).toBe("site");
|
|
188
193
|
});
|
|
189
194
|
|
|
190
195
|
test('defaults appType to "app" when type is not "site"', async () => {
|
|
191
|
-
let capturedType:
|
|
196
|
+
let capturedType: "app" | "site" | undefined;
|
|
192
197
|
const store = makeMockStore({
|
|
193
198
|
createApp: (params) => {
|
|
194
199
|
capturedType = params.appType;
|
|
195
200
|
return makeApp({ name: params.name });
|
|
196
201
|
},
|
|
197
202
|
});
|
|
198
|
-
await executeAppCreate({ name:
|
|
199
|
-
expect(capturedType).toBe(
|
|
203
|
+
await executeAppCreate({ name: "App", html: "<p/>" }, store);
|
|
204
|
+
expect(capturedType).toBe("app");
|
|
200
205
|
});
|
|
201
206
|
});
|
|
202
207
|
|
|
@@ -204,26 +209,36 @@ describe('executeAppCreate', () => {
|
|
|
204
209
|
// app_list
|
|
205
210
|
// ---------------------------------------------------------------------------
|
|
206
211
|
|
|
207
|
-
describe(
|
|
208
|
-
test(
|
|
212
|
+
describe("executeAppList", () => {
|
|
213
|
+
test("returns mapped list of apps", () => {
|
|
209
214
|
const store = makeMockStore({
|
|
210
215
|
listApps: () => [
|
|
211
|
-
makeApp({
|
|
212
|
-
|
|
216
|
+
makeApp({
|
|
217
|
+
id: "a1",
|
|
218
|
+
name: "First",
|
|
219
|
+
description: "desc1",
|
|
220
|
+
updatedAt: 100,
|
|
221
|
+
}),
|
|
222
|
+
makeApp({ id: "a2", name: "Second", updatedAt: 200 }),
|
|
213
223
|
],
|
|
214
224
|
});
|
|
215
225
|
const result = executeAppList(store);
|
|
216
226
|
expect(result.isError).toBe(false);
|
|
217
227
|
const parsed = JSON.parse(result.content);
|
|
218
228
|
expect(parsed).toHaveLength(2);
|
|
219
|
-
expect(parsed[0]).toEqual({
|
|
220
|
-
|
|
229
|
+
expect(parsed[0]).toEqual({
|
|
230
|
+
id: "a1",
|
|
231
|
+
name: "First",
|
|
232
|
+
description: "desc1",
|
|
233
|
+
updatedAt: 100,
|
|
234
|
+
});
|
|
235
|
+
expect(parsed[1].id).toBe("a2");
|
|
221
236
|
// Should not include htmlDefinition or schemaJson
|
|
222
237
|
expect(parsed[0].htmlDefinition).toBeUndefined();
|
|
223
238
|
expect(parsed[0].schemaJson).toBeUndefined();
|
|
224
239
|
});
|
|
225
240
|
|
|
226
|
-
test(
|
|
241
|
+
test("returns empty array when no apps exist", () => {
|
|
227
242
|
const store = makeMockStore({ listApps: () => [] });
|
|
228
243
|
const result = executeAppList(store);
|
|
229
244
|
expect(result.isError).toBe(false);
|
|
@@ -235,18 +250,18 @@ describe('executeAppList', () => {
|
|
|
235
250
|
// app_query
|
|
236
251
|
// ---------------------------------------------------------------------------
|
|
237
252
|
|
|
238
|
-
describe(
|
|
239
|
-
test(
|
|
240
|
-
const records = [{ id:
|
|
253
|
+
describe("executeAppQuery", () => {
|
|
254
|
+
test("returns records for a given app", () => {
|
|
255
|
+
const records = [{ id: "r1", appId: "app-1", data: { x: 1 } }];
|
|
241
256
|
const store = makeMockStore({ queryAppRecords: () => records });
|
|
242
|
-
const result = executeAppQuery({ app_id:
|
|
257
|
+
const result = executeAppQuery({ app_id: "app-1" }, store);
|
|
243
258
|
expect(result.isError).toBe(false);
|
|
244
259
|
expect(JSON.parse(result.content)).toEqual(records);
|
|
245
260
|
});
|
|
246
261
|
|
|
247
|
-
test(
|
|
262
|
+
test("returns empty array when no records", () => {
|
|
248
263
|
const store = makeMockStore({ queryAppRecords: () => [] });
|
|
249
|
-
const result = executeAppQuery({ app_id:
|
|
264
|
+
const result = executeAppQuery({ app_id: "app-1" }, store);
|
|
250
265
|
expect(result.isError).toBe(false);
|
|
251
266
|
expect(JSON.parse(result.content)).toEqual([]);
|
|
252
267
|
});
|
|
@@ -256,8 +271,8 @@ describe('executeAppQuery', () => {
|
|
|
256
271
|
// app_update
|
|
257
272
|
// ---------------------------------------------------------------------------
|
|
258
273
|
|
|
259
|
-
describe(
|
|
260
|
-
test(
|
|
274
|
+
describe("executeAppUpdate", () => {
|
|
275
|
+
test("passes update fields through to store", () => {
|
|
261
276
|
let capturedUpdates: Record<string, unknown> = {};
|
|
262
277
|
const store = makeMockStore({
|
|
263
278
|
updateApp: (_id, updates) => {
|
|
@@ -267,26 +282,26 @@ describe('executeAppUpdate', () => {
|
|
|
267
282
|
});
|
|
268
283
|
const result = executeAppUpdate(
|
|
269
284
|
{
|
|
270
|
-
app_id:
|
|
271
|
-
name:
|
|
272
|
-
description:
|
|
285
|
+
app_id: "app-1",
|
|
286
|
+
name: "New Name",
|
|
287
|
+
description: "New desc",
|
|
273
288
|
schema_json: '{"a":1}',
|
|
274
|
-
html:
|
|
275
|
-
pages: {
|
|
289
|
+
html: "<div/>",
|
|
290
|
+
pages: { "about.html": "<p/>" },
|
|
276
291
|
},
|
|
277
292
|
store,
|
|
278
293
|
);
|
|
279
294
|
expect(result.isError).toBe(false);
|
|
280
295
|
expect(capturedUpdates).toEqual({
|
|
281
|
-
name:
|
|
282
|
-
description:
|
|
296
|
+
name: "New Name",
|
|
297
|
+
description: "New desc",
|
|
283
298
|
schemaJson: '{"a":1}',
|
|
284
|
-
htmlDefinition:
|
|
285
|
-
pages: {
|
|
299
|
+
htmlDefinition: "<div/>",
|
|
300
|
+
pages: { "about.html": "<p/>" },
|
|
286
301
|
});
|
|
287
302
|
});
|
|
288
303
|
|
|
289
|
-
test(
|
|
304
|
+
test("only includes provided fields in updates", () => {
|
|
290
305
|
let capturedUpdates: Record<string, unknown> = {};
|
|
291
306
|
const store = makeMockStore({
|
|
292
307
|
updateApp: (_id, updates) => {
|
|
@@ -294,23 +309,23 @@ describe('executeAppUpdate', () => {
|
|
|
294
309
|
return makeApp({ id: _id, ...updates });
|
|
295
310
|
},
|
|
296
311
|
});
|
|
297
|
-
executeAppUpdate({ app_id:
|
|
298
|
-
expect(capturedUpdates).toEqual({ name:
|
|
312
|
+
executeAppUpdate({ app_id: "app-1", name: "Only Name" }, store);
|
|
313
|
+
expect(capturedUpdates).toEqual({ name: "Only Name" });
|
|
299
314
|
// html, description, schema_json, pages should NOT be in the updates
|
|
300
|
-
expect(
|
|
301
|
-
expect(
|
|
302
|
-
expect(
|
|
303
|
-
expect(
|
|
315
|
+
expect("htmlDefinition" in capturedUpdates).toBe(false);
|
|
316
|
+
expect("description" in capturedUpdates).toBe(false);
|
|
317
|
+
expect("schemaJson" in capturedUpdates).toBe(false);
|
|
318
|
+
expect("pages" in capturedUpdates).toBe(false);
|
|
304
319
|
});
|
|
305
320
|
|
|
306
|
-
test(
|
|
321
|
+
test("propagates store errors", () => {
|
|
307
322
|
const store = makeMockStore({
|
|
308
323
|
updateApp: () => {
|
|
309
|
-
throw new Error(
|
|
324
|
+
throw new Error("App not found: bad-id");
|
|
310
325
|
},
|
|
311
326
|
});
|
|
312
|
-
expect(() => executeAppUpdate({ app_id:
|
|
313
|
-
|
|
327
|
+
expect(() => executeAppUpdate({ app_id: "bad-id" }, store)).toThrow(
|
|
328
|
+
"App not found: bad-id",
|
|
314
329
|
);
|
|
315
330
|
});
|
|
316
331
|
});
|
|
@@ -319,18 +334,21 @@ describe('executeAppUpdate', () => {
|
|
|
319
334
|
// app_delete
|
|
320
335
|
// ---------------------------------------------------------------------------
|
|
321
336
|
|
|
322
|
-
describe(
|
|
323
|
-
test(
|
|
337
|
+
describe("executeAppDelete", () => {
|
|
338
|
+
test("deletes the app and returns confirmation", () => {
|
|
324
339
|
let deletedId: string | undefined;
|
|
325
340
|
const store = makeMockStore({
|
|
326
341
|
deleteApp: (id) => {
|
|
327
342
|
deletedId = id;
|
|
328
343
|
},
|
|
329
344
|
});
|
|
330
|
-
const result = executeAppDelete({ app_id:
|
|
345
|
+
const result = executeAppDelete({ app_id: "app-1" }, store);
|
|
331
346
|
expect(result.isError).toBe(false);
|
|
332
|
-
expect(JSON.parse(result.content)).toEqual({
|
|
333
|
-
|
|
347
|
+
expect(JSON.parse(result.content)).toEqual({
|
|
348
|
+
deleted: true,
|
|
349
|
+
appId: "app-1",
|
|
350
|
+
});
|
|
351
|
+
expect(deletedId).toBe("app-1");
|
|
334
352
|
});
|
|
335
353
|
});
|
|
336
354
|
|
|
@@ -338,23 +356,23 @@ describe('executeAppDelete', () => {
|
|
|
338
356
|
// app_file_list
|
|
339
357
|
// ---------------------------------------------------------------------------
|
|
340
358
|
|
|
341
|
-
describe(
|
|
342
|
-
test(
|
|
359
|
+
describe("executeAppFileList", () => {
|
|
360
|
+
test("returns list of files", () => {
|
|
343
361
|
const store = makeMockStore({
|
|
344
|
-
listAppFiles: () => [
|
|
362
|
+
listAppFiles: () => ["index.html", "styles.css", "js/app.js"],
|
|
345
363
|
});
|
|
346
|
-
const result = executeAppFileList({ app_id:
|
|
364
|
+
const result = executeAppFileList({ app_id: "app-1" }, store);
|
|
347
365
|
expect(result.isError).toBe(false);
|
|
348
366
|
expect(JSON.parse(result.content)).toEqual([
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
367
|
+
"index.html",
|
|
368
|
+
"styles.css",
|
|
369
|
+
"js/app.js",
|
|
352
370
|
]);
|
|
353
371
|
});
|
|
354
372
|
|
|
355
|
-
test(
|
|
373
|
+
test("returns empty array when app has no files", () => {
|
|
356
374
|
const store = makeMockStore({ listAppFiles: () => [] });
|
|
357
|
-
const result = executeAppFileList({ app_id:
|
|
375
|
+
const result = executeAppFileList({ app_id: "app-1" }, store);
|
|
358
376
|
expect(result.isError).toBe(false);
|
|
359
377
|
expect(JSON.parse(result.content)).toEqual([]);
|
|
360
378
|
});
|
|
@@ -364,80 +382,76 @@ describe('executeAppFileList', () => {
|
|
|
364
382
|
// app_file_read
|
|
365
383
|
// ---------------------------------------------------------------------------
|
|
366
384
|
|
|
367
|
-
describe(
|
|
368
|
-
test(
|
|
385
|
+
describe("executeAppFileRead", () => {
|
|
386
|
+
test("returns formatted content with line numbers", () => {
|
|
369
387
|
const store = makeMockStore({
|
|
370
|
-
readAppFile: () =>
|
|
388
|
+
readAppFile: () => "line1\nline2\nline3",
|
|
371
389
|
});
|
|
372
390
|
const result = executeAppFileRead(
|
|
373
|
-
{ app_id:
|
|
391
|
+
{ app_id: "app-1", path: "index.html" },
|
|
374
392
|
store,
|
|
375
393
|
);
|
|
376
394
|
expect(result.isError).toBe(false);
|
|
377
|
-
expect(result.content).toBe(
|
|
378
|
-
' 1\tline1\n 2\tline2\n 3\tline3',
|
|
379
|
-
);
|
|
395
|
+
expect(result.content).toBe(" 1\tline1\n 2\tline2\n 3\tline3");
|
|
380
396
|
});
|
|
381
397
|
|
|
382
|
-
test(
|
|
398
|
+
test("applies offset parameter (1-based)", () => {
|
|
383
399
|
const store = makeMockStore({
|
|
384
|
-
readAppFile: () =>
|
|
400
|
+
readAppFile: () => "a\nb\nc\nd\ne",
|
|
385
401
|
});
|
|
386
402
|
const result = executeAppFileRead(
|
|
387
|
-
{ app_id:
|
|
403
|
+
{ app_id: "app-1", path: "f.txt", offset: 3 },
|
|
388
404
|
store,
|
|
389
405
|
);
|
|
390
406
|
expect(result.isError).toBe(false);
|
|
391
407
|
// Lines 3, 4, 5
|
|
392
|
-
expect(result.content).toBe(
|
|
393
|
-
' 3\tc\n 4\td\n 5\te',
|
|
394
|
-
);
|
|
408
|
+
expect(result.content).toBe(" 3\tc\n 4\td\n 5\te");
|
|
395
409
|
});
|
|
396
410
|
|
|
397
|
-
test(
|
|
411
|
+
test("applies limit parameter", () => {
|
|
398
412
|
const store = makeMockStore({
|
|
399
|
-
readAppFile: () =>
|
|
413
|
+
readAppFile: () => "a\nb\nc\nd\ne",
|
|
400
414
|
});
|
|
401
415
|
const result = executeAppFileRead(
|
|
402
|
-
{ app_id:
|
|
416
|
+
{ app_id: "app-1", path: "f.txt", limit: 2 },
|
|
403
417
|
store,
|
|
404
418
|
);
|
|
405
419
|
expect(result.isError).toBe(false);
|
|
406
|
-
expect(result.content).toBe(
|
|
420
|
+
expect(result.content).toBe(" 1\ta\n 2\tb");
|
|
407
421
|
});
|
|
408
422
|
|
|
409
|
-
test(
|
|
423
|
+
test("applies both offset and limit", () => {
|
|
410
424
|
const store = makeMockStore({
|
|
411
|
-
readAppFile: () =>
|
|
425
|
+
readAppFile: () => "a\nb\nc\nd\ne",
|
|
412
426
|
});
|
|
413
427
|
const result = executeAppFileRead(
|
|
414
|
-
{ app_id:
|
|
428
|
+
{ app_id: "app-1", path: "f.txt", offset: 2, limit: 2 },
|
|
415
429
|
store,
|
|
416
430
|
);
|
|
417
431
|
expect(result.isError).toBe(false);
|
|
418
|
-
expect(result.content).toBe(
|
|
432
|
+
expect(result.content).toBe(" 2\tb\n 3\tc");
|
|
419
433
|
});
|
|
420
434
|
|
|
421
|
-
test(
|
|
435
|
+
test("defaults offset to 1 when not provided", () => {
|
|
422
436
|
const store = makeMockStore({
|
|
423
|
-
readAppFile: () =>
|
|
437
|
+
readAppFile: () => "only",
|
|
424
438
|
});
|
|
425
439
|
const result = executeAppFileRead(
|
|
426
|
-
{ app_id:
|
|
440
|
+
{ app_id: "app-1", path: "f.txt" },
|
|
427
441
|
store,
|
|
428
442
|
);
|
|
429
|
-
expect(result.content).toBe(
|
|
443
|
+
expect(result.content).toBe(" 1\tonly");
|
|
430
444
|
});
|
|
431
445
|
|
|
432
|
-
test(
|
|
446
|
+
test("propagates store errors (e.g. file not found)", () => {
|
|
433
447
|
const store = makeMockStore({
|
|
434
448
|
readAppFile: () => {
|
|
435
|
-
throw new Error(
|
|
449
|
+
throw new Error("File not found: missing.txt");
|
|
436
450
|
},
|
|
437
451
|
});
|
|
438
452
|
expect(() =>
|
|
439
|
-
executeAppFileRead({ app_id:
|
|
440
|
-
).toThrow(
|
|
453
|
+
executeAppFileRead({ app_id: "app-1", path: "missing.txt" }, store),
|
|
454
|
+
).toThrow("File not found: missing.txt");
|
|
441
455
|
});
|
|
442
456
|
});
|
|
443
457
|
|
|
@@ -445,24 +459,24 @@ describe('executeAppFileRead', () => {
|
|
|
445
459
|
// app_file_edit
|
|
446
460
|
// ---------------------------------------------------------------------------
|
|
447
461
|
|
|
448
|
-
describe(
|
|
449
|
-
test(
|
|
462
|
+
describe("executeAppFileEdit", () => {
|
|
463
|
+
test("returns edit result from store", () => {
|
|
450
464
|
const editResult: EditEngineResult = {
|
|
451
465
|
ok: true,
|
|
452
|
-
updatedContent:
|
|
466
|
+
updatedContent: "updated",
|
|
453
467
|
matchCount: 1,
|
|
454
|
-
matchMethod:
|
|
468
|
+
matchMethod: "exact" as const,
|
|
455
469
|
similarity: 1,
|
|
456
|
-
actualOld:
|
|
457
|
-
actualNew:
|
|
470
|
+
actualOld: "old",
|
|
471
|
+
actualNew: "new",
|
|
458
472
|
};
|
|
459
473
|
const store = makeMockStore({ editAppFile: () => editResult });
|
|
460
474
|
const result = executeAppFileEdit(
|
|
461
475
|
{
|
|
462
|
-
app_id:
|
|
463
|
-
path:
|
|
464
|
-
old_string:
|
|
465
|
-
new_string:
|
|
476
|
+
app_id: "app-1",
|
|
477
|
+
path: "index.html",
|
|
478
|
+
old_string: "old",
|
|
479
|
+
new_string: "new",
|
|
466
480
|
},
|
|
467
481
|
store,
|
|
468
482
|
);
|
|
@@ -470,37 +484,45 @@ describe('executeAppFileEdit', () => {
|
|
|
470
484
|
expect(JSON.parse(result.content)).toEqual(editResult);
|
|
471
485
|
});
|
|
472
486
|
|
|
473
|
-
test(
|
|
487
|
+
test("returns error when old_string is empty", () => {
|
|
474
488
|
const store = makeMockStore();
|
|
475
489
|
const result = executeAppFileEdit(
|
|
476
490
|
{
|
|
477
|
-
app_id:
|
|
478
|
-
path:
|
|
479
|
-
old_string:
|
|
480
|
-
new_string:
|
|
491
|
+
app_id: "app-1",
|
|
492
|
+
path: "index.html",
|
|
493
|
+
old_string: "",
|
|
494
|
+
new_string: "new",
|
|
481
495
|
},
|
|
482
496
|
store,
|
|
483
497
|
);
|
|
484
498
|
expect(result.isError).toBe(true);
|
|
485
499
|
expect(JSON.parse(result.content)).toEqual({
|
|
486
|
-
error:
|
|
500
|
+
error: "old_string must not be empty",
|
|
487
501
|
});
|
|
488
502
|
});
|
|
489
503
|
|
|
490
|
-
test(
|
|
504
|
+
test("passes replace_all through to store", () => {
|
|
491
505
|
let capturedReplaceAll: boolean | undefined;
|
|
492
506
|
const store = makeMockStore({
|
|
493
507
|
editAppFile: (_appId, _path, _old, _new, replaceAll) => {
|
|
494
508
|
capturedReplaceAll = replaceAll;
|
|
495
|
-
return {
|
|
509
|
+
return {
|
|
510
|
+
ok: true,
|
|
511
|
+
updatedContent: "",
|
|
512
|
+
matchCount: 1,
|
|
513
|
+
matchMethod: "exact" as const,
|
|
514
|
+
similarity: 1,
|
|
515
|
+
actualOld: "",
|
|
516
|
+
actualNew: "",
|
|
517
|
+
};
|
|
496
518
|
},
|
|
497
519
|
});
|
|
498
520
|
executeAppFileEdit(
|
|
499
521
|
{
|
|
500
|
-
app_id:
|
|
501
|
-
path:
|
|
502
|
-
old_string:
|
|
503
|
-
new_string:
|
|
522
|
+
app_id: "app-1",
|
|
523
|
+
path: "f.txt",
|
|
524
|
+
old_string: "x",
|
|
525
|
+
new_string: "y",
|
|
504
526
|
replace_all: true,
|
|
505
527
|
},
|
|
506
528
|
store,
|
|
@@ -508,39 +530,47 @@ describe('executeAppFileEdit', () => {
|
|
|
508
530
|
expect(capturedReplaceAll).toBe(true);
|
|
509
531
|
});
|
|
510
532
|
|
|
511
|
-
test(
|
|
533
|
+
test("defaults replace_all to false", () => {
|
|
512
534
|
let capturedReplaceAll: boolean | undefined;
|
|
513
535
|
const store = makeMockStore({
|
|
514
536
|
editAppFile: (_appId, _path, _old, _new, replaceAll) => {
|
|
515
537
|
capturedReplaceAll = replaceAll;
|
|
516
|
-
return {
|
|
538
|
+
return {
|
|
539
|
+
ok: true,
|
|
540
|
+
updatedContent: "",
|
|
541
|
+
matchCount: 1,
|
|
542
|
+
matchMethod: "exact" as const,
|
|
543
|
+
similarity: 1,
|
|
544
|
+
actualOld: "",
|
|
545
|
+
actualNew: "",
|
|
546
|
+
};
|
|
517
547
|
},
|
|
518
548
|
});
|
|
519
549
|
executeAppFileEdit(
|
|
520
550
|
{
|
|
521
|
-
app_id:
|
|
522
|
-
path:
|
|
523
|
-
old_string:
|
|
524
|
-
new_string:
|
|
551
|
+
app_id: "app-1",
|
|
552
|
+
path: "f.txt",
|
|
553
|
+
old_string: "x",
|
|
554
|
+
new_string: "y",
|
|
525
555
|
},
|
|
526
556
|
store,
|
|
527
557
|
);
|
|
528
558
|
expect(capturedReplaceAll).toBe(false);
|
|
529
559
|
});
|
|
530
560
|
|
|
531
|
-
test(
|
|
561
|
+
test("passes status through to result", () => {
|
|
532
562
|
const store = makeMockStore();
|
|
533
563
|
const result = executeAppFileEdit(
|
|
534
564
|
{
|
|
535
|
-
app_id:
|
|
536
|
-
path:
|
|
537
|
-
old_string:
|
|
538
|
-
new_string:
|
|
539
|
-
status:
|
|
565
|
+
app_id: "app-1",
|
|
566
|
+
path: "f.txt",
|
|
567
|
+
old_string: "x",
|
|
568
|
+
new_string: "y",
|
|
569
|
+
status: "updating styles",
|
|
540
570
|
},
|
|
541
571
|
store,
|
|
542
572
|
);
|
|
543
|
-
expect(result.status).toBe(
|
|
573
|
+
expect(result.status).toBe("updating styles");
|
|
544
574
|
});
|
|
545
575
|
});
|
|
546
576
|
|
|
@@ -548,8 +578,8 @@ describe('executeAppFileEdit', () => {
|
|
|
548
578
|
// app_file_write
|
|
549
579
|
// ---------------------------------------------------------------------------
|
|
550
580
|
|
|
551
|
-
describe(
|
|
552
|
-
test(
|
|
581
|
+
describe("executeAppFileWrite", () => {
|
|
582
|
+
test("writes file and returns confirmation", () => {
|
|
553
583
|
let writtenPath: string | undefined;
|
|
554
584
|
let writtenContent: string | undefined;
|
|
555
585
|
const store = makeMockStore({
|
|
@@ -559,22 +589,22 @@ describe('executeAppFileWrite', () => {
|
|
|
559
589
|
},
|
|
560
590
|
});
|
|
561
591
|
const result = executeAppFileWrite(
|
|
562
|
-
{ app_id:
|
|
592
|
+
{ app_id: "app-1", path: "new.html", content: "<div/>" },
|
|
563
593
|
store,
|
|
564
594
|
);
|
|
565
595
|
expect(result.isError).toBe(false);
|
|
566
596
|
expect(JSON.parse(result.content)).toEqual({
|
|
567
597
|
written: true,
|
|
568
|
-
path:
|
|
598
|
+
path: "new.html",
|
|
569
599
|
});
|
|
570
|
-
expect(writtenPath).toBe(
|
|
571
|
-
expect(writtenContent).toBe(
|
|
600
|
+
expect(writtenPath).toBe("new.html");
|
|
601
|
+
expect(writtenContent).toBe("<div/>");
|
|
572
602
|
});
|
|
573
603
|
|
|
574
|
-
test(
|
|
604
|
+
test("returns error when app is not found", () => {
|
|
575
605
|
const store = makeMockStore({ getApp: () => null });
|
|
576
606
|
const result = executeAppFileWrite(
|
|
577
|
-
{ app_id:
|
|
607
|
+
{ app_id: "missing", path: "f.txt", content: "hi" },
|
|
578
608
|
store,
|
|
579
609
|
);
|
|
580
610
|
expect(result.isError).toBe(true);
|
|
@@ -583,21 +613,21 @@ describe('executeAppFileWrite', () => {
|
|
|
583
613
|
});
|
|
584
614
|
});
|
|
585
615
|
|
|
586
|
-
test(
|
|
616
|
+
test("passes status through to result", () => {
|
|
587
617
|
const store = makeMockStore();
|
|
588
618
|
const result = executeAppFileWrite(
|
|
589
619
|
{
|
|
590
|
-
app_id:
|
|
591
|
-
path:
|
|
592
|
-
content:
|
|
593
|
-
status:
|
|
620
|
+
app_id: "app-1",
|
|
621
|
+
path: "f.txt",
|
|
622
|
+
content: "hi",
|
|
623
|
+
status: "adding dark mode styles",
|
|
594
624
|
},
|
|
595
625
|
store,
|
|
596
626
|
);
|
|
597
|
-
expect(result.status).toBe(
|
|
627
|
+
expect(result.status).toBe("adding dark mode styles");
|
|
598
628
|
});
|
|
599
629
|
|
|
600
|
-
test(
|
|
630
|
+
test("does not call writeAppFile when app not found", () => {
|
|
601
631
|
let writeCalled = false;
|
|
602
632
|
const store = makeMockStore({
|
|
603
633
|
getApp: () => null,
|
|
@@ -605,10 +635,7 @@ describe('executeAppFileWrite', () => {
|
|
|
605
635
|
writeCalled = true;
|
|
606
636
|
},
|
|
607
637
|
});
|
|
608
|
-
executeAppFileWrite(
|
|
609
|
-
{ app_id: 'bad', path: 'f.txt', content: 'x' },
|
|
610
|
-
store,
|
|
611
|
-
);
|
|
638
|
+
executeAppFileWrite({ app_id: "bad", path: "f.txt", content: "x" }, store);
|
|
612
639
|
expect(writeCalled).toBe(false);
|
|
613
640
|
});
|
|
614
641
|
});
|