@e2edev/e2e 0.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/LICENSE +21 -0
- package/README.md +104 -0
- package/dist/agent/act-validation.d.ts +27 -0
- package/dist/agent/act-validation.d.ts.map +1 -0
- package/dist/agent/act-validation.js +121 -0
- package/dist/agent/act-validation.js.map +1 -0
- package/dist/agent/act.d.ts +27 -0
- package/dist/agent/act.d.ts.map +1 -0
- package/dist/agent/act.js +775 -0
- package/dist/agent/act.js.map +1 -0
- package/dist/agent/actions.d.ts +66 -0
- package/dist/agent/actions.d.ts.map +1 -0
- package/dist/agent/actions.js +82 -0
- package/dist/agent/actions.js.map +1 -0
- package/dist/agent/ai-sdk.d.ts +16 -0
- package/dist/agent/ai-sdk.d.ts.map +1 -0
- package/dist/agent/ai-sdk.js +59 -0
- package/dist/agent/ai-sdk.js.map +1 -0
- package/dist/agent/call-options.d.ts +10 -0
- package/dist/agent/call-options.d.ts.map +1 -0
- package/dist/agent/call-options.js +28 -0
- package/dist/agent/call-options.js.map +1 -0
- package/dist/agent/default-agent.d.ts +22 -0
- package/dist/agent/default-agent.d.ts.map +1 -0
- package/dist/agent/default-agent.js +354 -0
- package/dist/agent/default-agent.js.map +1 -0
- package/dist/agent/error.d.ts +53 -0
- package/dist/agent/error.d.ts.map +1 -0
- package/dist/agent/error.js +94 -0
- package/dist/agent/error.js.map +1 -0
- package/dist/agent/executor.d.ts +238 -0
- package/dist/agent/executor.d.ts.map +1 -0
- package/dist/agent/executor.js +56 -0
- package/dist/agent/executor.js.map +1 -0
- package/dist/agent/index.d.ts +15 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +304 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/invocation.d.ts +194 -0
- package/dist/agent/invocation.d.ts.map +1 -0
- package/dist/agent/invocation.js +389 -0
- package/dist/agent/invocation.js.map +1 -0
- package/dist/agent/ledger.d.ts +24 -0
- package/dist/agent/ledger.d.ts.map +1 -0
- package/dist/agent/ledger.js +48 -0
- package/dist/agent/ledger.js.map +1 -0
- package/dist/agent/loop-guards.d.ts +35 -0
- package/dist/agent/loop-guards.d.ts.map +1 -0
- package/dist/agent/loop-guards.js +110 -0
- package/dist/agent/loop-guards.js.map +1 -0
- package/dist/agent/model/adapter.d.ts +97 -0
- package/dist/agent/model/adapter.d.ts.map +1 -0
- package/dist/agent/model/adapter.js +40 -0
- package/dist/agent/model/adapter.js.map +1 -0
- package/dist/agent/model/router.d.ts +36 -0
- package/dist/agent/model/router.d.ts.map +1 -0
- package/dist/agent/model/router.js +45 -0
- package/dist/agent/model/router.js.map +1 -0
- package/dist/agent/model/schema.d.ts +16 -0
- package/dist/agent/model/schema.d.ts.map +1 -0
- package/dist/agent/model/schema.js +37 -0
- package/dist/agent/model/schema.js.map +1 -0
- package/dist/agent/model/sdk.d.ts +28 -0
- package/dist/agent/model/sdk.d.ts.map +1 -0
- package/dist/agent/model/sdk.js +258 -0
- package/dist/agent/model/sdk.js.map +1 -0
- package/dist/agent/observation.d.ts +70 -0
- package/dist/agent/observation.d.ts.map +1 -0
- package/dist/agent/observation.js +174 -0
- package/dist/agent/observation.js.map +1 -0
- package/dist/agent/phases.d.ts +71 -0
- package/dist/agent/phases.d.ts.map +1 -0
- package/dist/agent/phases.js +124 -0
- package/dist/agent/phases.js.map +1 -0
- package/dist/agent/prompts.d.ts +40 -0
- package/dist/agent/prompts.d.ts.map +1 -0
- package/dist/agent/prompts.js +104 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/protocol.d.ts +31 -0
- package/dist/agent/protocol.d.ts.map +1 -0
- package/dist/agent/protocol.js +67 -0
- package/dist/agent/protocol.js.map +1 -0
- package/dist/agent/public.d.ts +12 -0
- package/dist/agent/public.d.ts.map +1 -0
- package/dist/agent/public.js +12 -0
- package/dist/agent/public.js.map +1 -0
- package/dist/agent/replay.d.ts +61 -0
- package/dist/agent/replay.d.ts.map +1 -0
- package/dist/agent/replay.js +185 -0
- package/dist/agent/replay.js.map +1 -0
- package/dist/agent/secrets.d.ts +22 -0
- package/dist/agent/secrets.d.ts.map +1 -0
- package/dist/agent/secrets.js +63 -0
- package/dist/agent/secrets.js.map +1 -0
- package/dist/agent/step-cache.d.ts +156 -0
- package/dist/agent/step-cache.d.ts.map +1 -0
- package/dist/agent/step-cache.js +301 -0
- package/dist/agent/step-cache.js.map +1 -0
- package/dist/agent/tool-loop.d.ts +51 -0
- package/dist/agent/tool-loop.d.ts.map +1 -0
- package/dist/agent/tool-loop.js +331 -0
- package/dist/agent/tool-loop.js.map +1 -0
- package/dist/agent/tool.d.ts +39 -0
- package/dist/agent/tool.d.ts.map +1 -0
- package/dist/agent/tool.js +52 -0
- package/dist/agent/tool.js.map +1 -0
- package/dist/backend/contract.d.ts +186 -0
- package/dist/backend/contract.d.ts.map +1 -0
- package/dist/backend/contract.js +65 -0
- package/dist/backend/contract.js.map +1 -0
- package/dist/backend/index.d.ts +316 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +219 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/session.d.ts +23 -0
- package/dist/backend/session.d.ts.map +1 -0
- package/dist/backend/session.js +213 -0
- package/dist/backend/session.js.map +1 -0
- package/dist/backend/surface.d.ts +83 -0
- package/dist/backend/surface.d.ts.map +1 -0
- package/dist/backend/surface.js +11 -0
- package/dist/backend/surface.js.map +1 -0
- package/dist/cache/anchors.d.ts +37 -0
- package/dist/cache/anchors.d.ts.map +1 -0
- package/dist/cache/anchors.js +89 -0
- package/dist/cache/anchors.js.map +1 -0
- package/dist/cache/context.d.ts +74 -0
- package/dist/cache/context.d.ts.map +1 -0
- package/dist/cache/context.js +82 -0
- package/dist/cache/context.js.map +1 -0
- package/dist/cache/decide.d.ts +42 -0
- package/dist/cache/decide.d.ts.map +1 -0
- package/dist/cache/decide.js +47 -0
- package/dist/cache/decide.js.map +1 -0
- package/dist/cache/identity.d.ts +113 -0
- package/dist/cache/identity.d.ts.map +1 -0
- package/dist/cache/identity.js +109 -0
- package/dist/cache/identity.js.map +1 -0
- package/dist/cache/recorder.d.ts +76 -0
- package/dist/cache/recorder.d.ts.map +1 -0
- package/dist/cache/recorder.js +143 -0
- package/dist/cache/recorder.js.map +1 -0
- package/dist/cache/relocate.d.ts +69 -0
- package/dist/cache/relocate.d.ts.map +1 -0
- package/dist/cache/relocate.js +125 -0
- package/dist/cache/relocate.js.map +1 -0
- package/dist/cache/store.d.ts +68 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/store.js +106 -0
- package/dist/cache/store.js.map +1 -0
- package/dist/cache/trace.d.ts +146 -0
- package/dist/cache/trace.d.ts.map +1 -0
- package/dist/cache/trace.js +249 -0
- package/dist/cache/trace.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +108 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +6 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +101 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/collect/collect.d.ts +44 -0
- package/dist/collect/collect.d.ts.map +1 -0
- package/dist/collect/collect.js +89 -0
- package/dist/collect/collect.js.map +1 -0
- package/dist/collect/registry.d.ts +47 -0
- package/dist/collect/registry.d.ts.map +1 -0
- package/dist/collect/registry.js +262 -0
- package/dist/collect/registry.js.map +1 -0
- package/dist/collect/select.d.ts +54 -0
- package/dist/collect/select.d.ts.map +1 -0
- package/dist/collect/select.js +230 -0
- package/dist/collect/select.js.map +1 -0
- package/dist/config/agent.d.ts +91 -0
- package/dist/config/agent.d.ts.map +1 -0
- package/dist/config/agent.js +232 -0
- package/dist/config/agent.js.map +1 -0
- package/dist/config/load.d.ts +23 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +75 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/resolve.d.ts +94 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/resolve.js +500 -0
- package/dist/config/resolve.js.map +1 -0
- package/dist/config/validate.d.ts +6 -0
- package/dist/config/validate.d.ts.map +1 -0
- package/dist/config/validate.js +21 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/credentials.d.ts +7 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +42 -0
- package/dist/credentials.js.map +1 -0
- package/dist/expect/async.d.ts +5 -0
- package/dist/expect/async.d.ts.map +1 -0
- package/dist/expect/async.js +186 -0
- package/dist/expect/async.js.map +1 -0
- package/dist/expect/index.d.ts +7 -0
- package/dist/expect/index.d.ts.map +1 -0
- package/dist/expect/index.js +23 -0
- package/dist/expect/index.js.map +1 -0
- package/dist/expect/values.d.ts +4 -0
- package/dist/expect/values.d.ts.map +1 -0
- package/dist/expect/values.js +108 -0
- package/dist/expect/values.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/ai-trace.d.ts +151 -0
- package/dist/internal/ai-trace.d.ts.map +1 -0
- package/dist/internal/ai-trace.js +360 -0
- package/dist/internal/ai-trace.js.map +1 -0
- package/dist/internal/brands.d.ts +9 -0
- package/dist/internal/brands.d.ts.map +1 -0
- package/dist/internal/brands.js +9 -0
- package/dist/internal/brands.js.map +1 -0
- package/dist/internal/debug.d.ts +43 -0
- package/dist/internal/debug.d.ts.map +1 -0
- package/dist/internal/debug.js +102 -0
- package/dist/internal/debug.js.map +1 -0
- package/dist/internal/errors.d.ts +98 -0
- package/dist/internal/errors.d.ts.map +1 -0
- package/dist/internal/errors.js +212 -0
- package/dist/internal/errors.js.map +1 -0
- package/dist/internal/globs.d.ts +29 -0
- package/dist/internal/globs.d.ts.map +1 -0
- package/dist/internal/globs.js +126 -0
- package/dist/internal/globs.js.map +1 -0
- package/dist/internal/ids.d.ts +32 -0
- package/dist/internal/ids.d.ts.map +1 -0
- package/dist/internal/ids.js +124 -0
- package/dist/internal/ids.js.map +1 -0
- package/dist/internal/json-value.d.ts +15 -0
- package/dist/internal/json-value.d.ts.map +1 -0
- package/dist/internal/json-value.js +61 -0
- package/dist/internal/json-value.js.map +1 -0
- package/dist/internal/package-version.d.ts +6 -0
- package/dist/internal/package-version.d.ts.map +1 -0
- package/dist/internal/package-version.js +14 -0
- package/dist/internal/package-version.js.map +1 -0
- package/dist/internal/realm-slot.d.ts +13 -0
- package/dist/internal/realm-slot.d.ts.map +1 -0
- package/dist/internal/realm-slot.js +23 -0
- package/dist/internal/realm-slot.js.map +1 -0
- package/dist/internal/redact.d.ts +33 -0
- package/dist/internal/redact.d.ts.map +1 -0
- package/dist/internal/redact.js +56 -0
- package/dist/internal/redact.js.map +1 -0
- package/dist/internal/regexp.d.ts +10 -0
- package/dist/internal/regexp.d.ts.map +1 -0
- package/dist/internal/regexp.js +27 -0
- package/dist/internal/regexp.js.map +1 -0
- package/dist/internal/text.d.ts +39 -0
- package/dist/internal/text.d.ts.map +1 -0
- package/dist/internal/text.js +66 -0
- package/dist/internal/text.js.map +1 -0
- package/dist/internal/time.d.ts +37 -0
- package/dist/internal/time.d.ts.map +1 -0
- package/dist/internal/time.js +91 -0
- package/dist/internal/time.js.map +1 -0
- package/dist/internal/trace.d.ts +18 -0
- package/dist/internal/trace.d.ts.map +1 -0
- package/dist/internal/trace.js +46 -0
- package/dist/internal/trace.js.map +1 -0
- package/dist/internal/urls.d.ts +31 -0
- package/dist/internal/urls.d.ts.map +1 -0
- package/dist/internal/urls.js +95 -0
- package/dist/internal/urls.js.map +1 -0
- package/dist/locator/engine.d.ts +65 -0
- package/dist/locator/engine.d.ts.map +1 -0
- package/dist/locator/engine.js +164 -0
- package/dist/locator/engine.js.map +1 -0
- package/dist/locator/expression.d.ts +19 -0
- package/dist/locator/expression.d.ts.map +1 -0
- package/dist/locator/expression.js +85 -0
- package/dist/locator/expression.js.map +1 -0
- package/dist/locator/screen.d.ts +36 -0
- package/dist/locator/screen.d.ts.map +1 -0
- package/dist/locator/screen.js +281 -0
- package/dist/locator/screen.js.map +1 -0
- package/dist/report/build.d.ts +214 -0
- package/dist/report/build.d.ts.map +1 -0
- package/dist/report/build.js +346 -0
- package/dist/report/build.js.map +1 -0
- package/dist/report/code-frame.d.ts +20 -0
- package/dist/report/code-frame.d.ts.map +1 -0
- package/dist/report/code-frame.js +73 -0
- package/dist/report/code-frame.js.map +1 -0
- package/dist/report/debug-steps.d.ts +14 -0
- package/dist/report/debug-steps.d.ts.map +1 -0
- package/dist/report/debug-steps.js +85 -0
- package/dist/report/debug-steps.js.map +1 -0
- package/dist/report/list.d.ts +80 -0
- package/dist/report/list.d.ts.map +1 -0
- package/dist/report/list.js +372 -0
- package/dist/report/list.js.map +1 -0
- package/dist/report/live-status.d.ts +51 -0
- package/dist/report/live-status.d.ts.map +1 -0
- package/dist/report/live-status.js +162 -0
- package/dist/report/live-status.js.map +1 -0
- package/dist/report/write.d.ts +4 -0
- package/dist/report/write.d.ts.map +1 -0
- package/dist/report/write.js +13 -0
- package/dist/report/write.js.map +1 -0
- package/dist/run/app-process.d.ts +18 -0
- package/dist/run/app-process.d.ts.map +1 -0
- package/dist/run/app-process.js +112 -0
- package/dist/run/app-process.js.map +1 -0
- package/dist/run/artifacts.d.ts +51 -0
- package/dist/run/artifacts.d.ts.map +1 -0
- package/dist/run/artifacts.js +114 -0
- package/dist/run/artifacts.js.map +1 -0
- package/dist/run/events.d.ts +100 -0
- package/dist/run/events.d.ts.map +1 -0
- package/dist/run/events.js +59 -0
- package/dist/run/events.js.map +1 -0
- package/dist/run/execute.d.ts +119 -0
- package/dist/run/execute.d.ts.map +1 -0
- package/dist/run/execute.js +555 -0
- package/dist/run/execute.js.map +1 -0
- package/dist/run/fixtures.d.ts +40 -0
- package/dist/run/fixtures.d.ts.map +1 -0
- package/dist/run/fixtures.js +408 -0
- package/dist/run/fixtures.js.map +1 -0
- package/dist/run/in-process.d.ts +24 -0
- package/dist/run/in-process.d.ts.map +1 -0
- package/dist/run/in-process.js +120 -0
- package/dist/run/in-process.js.map +1 -0
- package/dist/run/public.d.ts +19 -0
- package/dist/run/public.d.ts.map +1 -0
- package/dist/run/public.js +11 -0
- package/dist/run/public.js.map +1 -0
- package/dist/run/realm.d.ts +52 -0
- package/dist/run/realm.d.ts.map +1 -0
- package/dist/run/realm.js +101 -0
- package/dist/run/realm.js.map +1 -0
- package/dist/run/records.d.ts +87 -0
- package/dist/run/records.d.ts.map +1 -0
- package/dist/run/records.js +3 -0
- package/dist/run/records.js.map +1 -0
- package/dist/run/retry.d.ts +18 -0
- package/dist/run/retry.d.ts.map +1 -0
- package/dist/run/retry.js +33 -0
- package/dist/run/retry.js.map +1 -0
- package/dist/run/runner.d.ts +49 -0
- package/dist/run/runner.d.ts.map +1 -0
- package/dist/run/runner.js +375 -0
- package/dist/run/runner.js.map +1 -0
- package/dist/run/scheduler.d.ts +45 -0
- package/dist/run/scheduler.d.ts.map +1 -0
- package/dist/run/scheduler.js +512 -0
- package/dist/run/scheduler.js.map +1 -0
- package/dist/run/serial.d.ts +52 -0
- package/dist/run/serial.d.ts.map +1 -0
- package/dist/run/serial.js +247 -0
- package/dist/run/serial.js.map +1 -0
- package/dist/run/sessions.d.ts +54 -0
- package/dist/run/sessions.d.ts.map +1 -0
- package/dist/run/sessions.js +221 -0
- package/dist/run/sessions.js.map +1 -0
- package/dist/run/steps.d.ts +196 -0
- package/dist/run/steps.d.ts.map +1 -0
- package/dist/run/steps.js +151 -0
- package/dist/run/steps.js.map +1 -0
- package/dist/run/unit-runner.d.ts +30 -0
- package/dist/run/unit-runner.d.ts.map +1 -0
- package/dist/run/unit-runner.js +11 -0
- package/dist/run/unit-runner.js.map +1 -0
- package/dist/run/units.d.ts +50 -0
- package/dist/run/units.d.ts.map +1 -0
- package/dist/run/units.js +103 -0
- package/dist/run/units.js.map +1 -0
- package/dist/run/worker/entry.d.ts +8 -0
- package/dist/run/worker/entry.d.ts.map +1 -0
- package/dist/run/worker/entry.js +137 -0
- package/dist/run/worker/entry.js.map +1 -0
- package/dist/run/worker/handle.d.ts +10 -0
- package/dist/run/worker/handle.d.ts.map +1 -0
- package/dist/run/worker/handle.js +74 -0
- package/dist/run/worker/handle.js.map +1 -0
- package/dist/run/worker/protocol.d.ts +129 -0
- package/dist/run/worker/protocol.d.ts.map +1 -0
- package/dist/run/worker/protocol.js +18 -0
- package/dist/run/worker/protocol.js.map +1 -0
- package/dist/run/worker/session.d.ts +69 -0
- package/dist/run/worker/session.d.ts.map +1 -0
- package/dist/run/worker/session.js +123 -0
- package/dist/run/worker/session.js.map +1 -0
- package/dist/types.d.ts +630 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backend contract vocabulary (RFC0002): the platform-neutral types every
|
|
3
|
+
* backend speaks and the harness consumes. A backend imports these from
|
|
4
|
+
* `@e2edev/e2e/backend`; core never imports anything from a backend.
|
|
5
|
+
*
|
|
6
|
+
* Everything here is capability vocabulary - semantic nodes, locator
|
|
7
|
+
* expressions, action kinds, the error contract - never a platform noun. A
|
|
8
|
+
* document platform, a simulator, and a desktop shell describe themselves with the same
|
|
9
|
+
* words, which is what lets `screen`, `expect`, and the agent work identically
|
|
10
|
+
* on all of them.
|
|
11
|
+
*/
|
|
12
|
+
/** The backend contract version this runner speaks. */
|
|
13
|
+
export const BACKEND_SPI_VERSION = 1;
|
|
14
|
+
/**
|
|
15
|
+
* Per-field bounds a backend applies to observation-tree nodes. A `name` or
|
|
16
|
+
* `text` whose length reaches its limit was cut at exactly that limit, so
|
|
17
|
+
* "length >= limit" is a precise truncation signal; every shorter value is
|
|
18
|
+
* complete. Single-node reads are unbounded and always carry the full value.
|
|
19
|
+
*/
|
|
20
|
+
export const OBSERVED_NAME_LIMIT = 256;
|
|
21
|
+
export const OBSERVED_TEXT_LIMIT = 512;
|
|
22
|
+
/** The closed backend error code set; the type is derived from it, so the two cannot drift. */
|
|
23
|
+
export const BACKEND_ERROR_CODES = [
|
|
24
|
+
'NODE_STALE',
|
|
25
|
+
'FRAME_NOT_FOUND',
|
|
26
|
+
'FRAME_AMBIGUOUS',
|
|
27
|
+
'NOT_ACTIONABLE',
|
|
28
|
+
'ACTION_MAY_HAVE_COMMITTED',
|
|
29
|
+
'OPERATION_TIMEOUT',
|
|
30
|
+
'CANCELLED',
|
|
31
|
+
'UNSUPPORTED_CAPABILITY',
|
|
32
|
+
'INVALID_STATE',
|
|
33
|
+
'BACKEND_FAILURE',
|
|
34
|
+
];
|
|
35
|
+
/**
|
|
36
|
+
* The only codes that may be retryable: both describe a repeatable read. Any
|
|
37
|
+
* other retryable claim, from this module's class or a foreign copy of it, is
|
|
38
|
+
* coerced to a non-retryable `BACKEND_FAILURE`.
|
|
39
|
+
*/
|
|
40
|
+
export const RETRYABLE_BACKEND_ERROR_CODES = new Set([
|
|
41
|
+
'NODE_STALE',
|
|
42
|
+
'FRAME_NOT_FOUND',
|
|
43
|
+
]);
|
|
44
|
+
/**
|
|
45
|
+
* The error contract a backend throws across the seam. Retryability is closed
|
|
46
|
+
* to `RETRYABLE_BACKEND_ERROR_CODES`; any other retryable claim is coerced to
|
|
47
|
+
* a non-retryable `BACKEND_FAILURE` so a backend can never talk the harness
|
|
48
|
+
* into repeating an action that may have committed.
|
|
49
|
+
*/
|
|
50
|
+
export class BackendError extends Error {
|
|
51
|
+
code;
|
|
52
|
+
retryable;
|
|
53
|
+
constructor(code, message, options) {
|
|
54
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
55
|
+
this.name = 'BackendError';
|
|
56
|
+
if (options.retryable && !RETRYABLE_BACKEND_ERROR_CODES.has(code)) {
|
|
57
|
+
this.code = 'BACKEND_FAILURE';
|
|
58
|
+
this.retryable = false;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.code = code;
|
|
62
|
+
this.retryable = options.retryable;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/backend/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,uDAAuD;AACvD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AA+DrC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAgGvC,+FAA+F;AAC/F,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,YAAY;IACZ,iBAAiB;IACjB,iBAAiB;IACjB,gBAAgB;IAChB,2BAA2B;IAC3B,mBAAmB;IACnB,WAAW;IACX,wBAAwB;IACxB,eAAe;IACf,iBAAiB;CACT,CAAC;AAIX;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAkC,IAAI,GAAG,CAAC;IAClF,YAAY;IACZ,iBAAiB;CAClB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAmB;IACvB,SAAS,CAAU;IAE5B,YACE,IAAsB,EACtB,OAAe,EACf,OAAgD;QAEhD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAClE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;YAC9B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backend contract (RFC0002): the typed, model-free body of one target.
|
|
3
|
+
*
|
|
4
|
+
* A backend never talks to a model. It declares capabilities - observation,
|
|
5
|
+
* actions, location, state, artifacts, contributed fixtures - and the harness
|
|
6
|
+
* grades what a target can do from what its backend declares: observation
|
|
7
|
+
* unlocks the judgment tier and prompt snapshots, `perform` unlocks the
|
|
8
|
+
* harness-routed node actions (the agent's grammar verbs and the `screen`
|
|
9
|
+
* tier's actions alike), location unlocks `screen`/`expect`. Every piece of
|
|
10
|
+
* model-facing vocabulary is an agent-side `defineTool`; a target with no
|
|
11
|
+
* backend at all is valid and simply runs everything opaque.
|
|
12
|
+
*
|
|
13
|
+
* Core knows this contract and never a backend's internals: no platform noun
|
|
14
|
+
* appears here. A document backend, a simulator backend, and a desktop backend
|
|
15
|
+
* fill in the same members with different bodies.
|
|
16
|
+
*
|
|
17
|
+
* `defineBackend` is the loud manifest: capability detection happens here,
|
|
18
|
+
* synchronously, at config load - a malformed backend fails the run instead
|
|
19
|
+
* of silently demoting itself to a lower tier.
|
|
20
|
+
*/
|
|
21
|
+
import { backendBrand } from '../internal/brands.ts';
|
|
22
|
+
export { ConfigurationError, InfrastructureError, TestError } from '../internal/errors.ts';
|
|
23
|
+
export { validateJsonValue, type JsonValueRules } from '../internal/json-value.ts';
|
|
24
|
+
export { describePattern, matchesText, toTextPattern } from '../internal/text.ts';
|
|
25
|
+
export type { TextMatch } from '../types.ts';
|
|
26
|
+
export { Deadline, pollCondition, type PollConditionOptions } from '../internal/time.ts';
|
|
27
|
+
export { urlMatches } from '../internal/urls.ts';
|
|
28
|
+
import type { Expectable, Locator, Momentum, Screen, ScrollDirection } from '../types.ts';
|
|
29
|
+
import { type BackendSpiVersion, type LocatorAction, type LocatorExpression, type NodeRef, type ObservationPixels, type OperationContext, type SemanticNode } from './contract.ts';
|
|
30
|
+
export type * from './contract.ts';
|
|
31
|
+
export { BACKEND_ERROR_CODES, BACKEND_SPI_VERSION, BackendError, OBSERVED_NAME_LIMIT, OBSERVED_TEXT_LIMIT, RETRYABLE_BACKEND_ERROR_CODES, } from './contract.ts';
|
|
32
|
+
export type { Expectable, JsonValue, Locator, Momentum, Platform, Screen, ScrollDirection, SelectOption, } from '../types.ts';
|
|
33
|
+
/**
|
|
34
|
+
* Capability names: the closed harness capabilities plus one name per
|
|
35
|
+
* contributed fixture. `actions` is `perform`; `location` is `locate`. Both
|
|
36
|
+
* require observation, because their refs live in the observation's id space.
|
|
37
|
+
*/
|
|
38
|
+
export type BackendCapability = 'observation' | 'actions' | 'location' | 'state' | 'artifacts' | (string & {});
|
|
39
|
+
/** The app under test as the harness resolved it, shared with every backend. */
|
|
40
|
+
export interface BackendAppInfo {
|
|
41
|
+
/**
|
|
42
|
+
* Normalized base URL; the target of `app.open()` with no path. Absent when
|
|
43
|
+
* the project configured no app URL: a surface that needs one then fails
|
|
44
|
+
* the call that needs it, and never navigates to a placeholder.
|
|
45
|
+
*/
|
|
46
|
+
readonly baseUrl?: string;
|
|
47
|
+
/** Origins navigation and cookie policy admit. */
|
|
48
|
+
readonly allowedOrigins: readonly string[];
|
|
49
|
+
}
|
|
50
|
+
/** Context handed to a contributed fixture factory, once per attempt. */
|
|
51
|
+
export interface BackendFixtureContext {
|
|
52
|
+
readonly targetName: string;
|
|
53
|
+
readonly app: BackendAppInfo & {
|
|
54
|
+
/**
|
|
55
|
+
* Resolves a navigation target against the base URL and the origin
|
|
56
|
+
* policy. Throws `APP_URL_REQUIRED` when no app URL is configured and
|
|
57
|
+
* `POLICY_DENIED` for a disallowed origin or scheme, so a fixture never
|
|
58
|
+
* re-implements the policy the harness owns.
|
|
59
|
+
*/
|
|
60
|
+
resolveUrl(url: string): string;
|
|
61
|
+
};
|
|
62
|
+
/** Harness budgets, for fixtures that poll or navigate. */
|
|
63
|
+
readonly timeouts: {
|
|
64
|
+
readonly test: number;
|
|
65
|
+
readonly action: number;
|
|
66
|
+
readonly assertion: number;
|
|
67
|
+
};
|
|
68
|
+
/** Aborts with the attempt. */
|
|
69
|
+
readonly signal: AbortSignal;
|
|
70
|
+
/** Per-call operation budget: the action timeout (or an explicit one) plus the attempt signal. */
|
|
71
|
+
operation(timeoutMs?: number): OperationContext;
|
|
72
|
+
/** Registers a file the current step produced under the attempt artifact directory. */
|
|
73
|
+
attachArtifact(kind: 'screenshot' | 'trace' | 'video' | 'download' | 'log', relativePath: string): void;
|
|
74
|
+
/** Records the viewport the current step established. */
|
|
75
|
+
attachViewport(viewport: {
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
scale: number;
|
|
79
|
+
}): void;
|
|
80
|
+
/** Mints a public locator from a raw expression (a platform selector, say). */
|
|
81
|
+
locator(expression: LocatorExpression): Locator;
|
|
82
|
+
/** Mints a screen scope whose every query is wrapped by `scope` (a nested document, say). */
|
|
83
|
+
screen(scope: (expression: LocatorExpression) => LocatorExpression): Screen;
|
|
84
|
+
/**
|
|
85
|
+
* Attaches an expectation surface to a fixture object so `expect(fixture)`
|
|
86
|
+
* returns it. The harness records every matcher call as an assertion step
|
|
87
|
+
* named `expect.<matcher>`; the factory only decides what the matchers mean.
|
|
88
|
+
*/
|
|
89
|
+
expectable<T extends object, E extends object>(target: T, factory: () => E): T & Expectable<E>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A contributed fixture: any record of async methods, sync accessors, and
|
|
93
|
+
* nested namespaces. The harness owns how every async method call runs - a
|
|
94
|
+
* recorded, timeout-bounded step named `<fixture>.<method>` - and never
|
|
95
|
+
* learns what the methods mean. A synchronous member is an accessor and is
|
|
96
|
+
* returned as is.
|
|
97
|
+
*/
|
|
98
|
+
export type BackendFixtureFactory = (context: BackendFixtureContext) => object;
|
|
99
|
+
/**
|
|
100
|
+
* An opaque, restorable snapshot of a backend's state. `data` is JSON the
|
|
101
|
+
* harness never inspects - a document platform's storage state, a device's app state, a
|
|
102
|
+
* desktop's window state all satisfy it identically. `format`/`version` let a
|
|
103
|
+
* backend reject a snapshot it can no longer read.
|
|
104
|
+
*/
|
|
105
|
+
export interface BackendState {
|
|
106
|
+
readonly format: string;
|
|
107
|
+
readonly version: number;
|
|
108
|
+
readonly data: unknown;
|
|
109
|
+
/** Earliest moment the state is known to be invalid, if the backend knows one. */
|
|
110
|
+
readonly expiresAt?: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Platform-neutral state capture and restore. A setup test captures a
|
|
114
|
+
* snapshot; an ordinary test restores it at launch.
|
|
115
|
+
*
|
|
116
|
+
* Snapshots are credentials: cookies, tokens, and storage that authenticate
|
|
117
|
+
* the app under test. The duties split at the seam. The harness owns the
|
|
118
|
+
* snapshot from the moment `capture` returns: it encrypts it at rest with a
|
|
119
|
+
* per-run AES-256-GCM key that never touches disk, stores it under the run's
|
|
120
|
+
* private session directory, binds it to the run, target, backend, and app
|
|
121
|
+
* identity, and deletes it when the run ends; it never logs it, reports it,
|
|
122
|
+
* digests it, or sends it to a model. A backend MUST NOT persist, cache, or
|
|
123
|
+
* log a snapshot on its own, MUST NOT echo snapshot contents in an error
|
|
124
|
+
* message, and MUST treat `restore` as a replacement of the surface's whole
|
|
125
|
+
* persisted state, never a merge, so a restored session cannot leak into the
|
|
126
|
+
* next attempt.
|
|
127
|
+
*/
|
|
128
|
+
export interface BackendStateCapability {
|
|
129
|
+
capture(context: OperationContext): Promise<BackendState>;
|
|
130
|
+
restore(state: BackendState, context: OperationContext): Promise<void>;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Evidence capture. Paths are relative to the attempt artifact directory the
|
|
134
|
+
* backend received in `startAttempt`.
|
|
135
|
+
*/
|
|
136
|
+
export interface BackendArtifacts {
|
|
137
|
+
/** Captures a redacted screenshot; secure fields are masked at the source. */
|
|
138
|
+
screenshot(label: string | undefined, context: OperationContext): Promise<string>;
|
|
139
|
+
/** Starts recording an execution trace for the attempt. */
|
|
140
|
+
startTrace?(context: OperationContext): Promise<void>;
|
|
141
|
+
/** Stops the trace and returns its relative path. */
|
|
142
|
+
stopTrace?(context: OperationContext): Promise<string>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* App-level hooks behind the universal `app` fixture and the agent's
|
|
146
|
+
* `navigate` verb. Node actions never live here; they are `perform`.
|
|
147
|
+
*/
|
|
148
|
+
export interface BackendApp {
|
|
149
|
+
/**
|
|
150
|
+
* Opens one URL the harness already resolved against the base URL and the
|
|
151
|
+
* origin policy. Absent on a surface without addressable locations.
|
|
152
|
+
*/
|
|
153
|
+
navigate?(url: string, context: OperationContext): Promise<void>;
|
|
154
|
+
/** Navigates back once in the surface's history. */
|
|
155
|
+
back?(context: OperationContext): Promise<void>;
|
|
156
|
+
/** Recreates the execution context, keeping persisted state, and relaunches. */
|
|
157
|
+
restart?(context: OperationContext): Promise<void>;
|
|
158
|
+
/** Clears persisted client state and relaunches. */
|
|
159
|
+
clearState?(context: OperationContext): Promise<void>;
|
|
160
|
+
}
|
|
161
|
+
/** Run identity and harness-resolved facts handed to `init`, once per worker before the first step. */
|
|
162
|
+
export interface BackendInitInfo {
|
|
163
|
+
readonly runId: string;
|
|
164
|
+
readonly targetName: string;
|
|
165
|
+
readonly app: BackendAppInfo;
|
|
166
|
+
/** Attribute the `testId` query resolves against. */
|
|
167
|
+
readonly testIdAttribute: string;
|
|
168
|
+
/** Whether the run asked for a visible surface (`--headed`). */
|
|
169
|
+
readonly headed: boolean;
|
|
170
|
+
/** Aborts on interrupt and when init exceeds the launch timeout; init must stop promptly. */
|
|
171
|
+
readonly signal: AbortSignal;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Per-attempt isolation context. A backend that must give each test a fresh
|
|
175
|
+
* surface (a fresh isolated context per test, a reset device) sets it up in
|
|
176
|
+
* `startAttempt` and tears it down in `endAttempt`.
|
|
177
|
+
*/
|
|
178
|
+
export interface BackendAttemptContext {
|
|
179
|
+
readonly attemptId: string;
|
|
180
|
+
/** Absolute directory every artifact of this attempt is written under. */
|
|
181
|
+
readonly artifactsDir: string;
|
|
182
|
+
/**
|
|
183
|
+
* Aborts with the attempt, and the moment `startAttempt` fails or exceeds
|
|
184
|
+
* the launch timeout: a hook still running then must stop, because the
|
|
185
|
+
* harness ends the attempt's isolation right behind it and may retry.
|
|
186
|
+
*/
|
|
187
|
+
readonly signal: AbortSignal;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Budget of one cleanup hook (`endAttempt`, `dispose`). `signal` aborts when
|
|
191
|
+
* the budget is exhausted, so a hook that cannot finish in time stops instead
|
|
192
|
+
* of running on into the next attempt's setup.
|
|
193
|
+
*/
|
|
194
|
+
export interface BackendCleanupContext {
|
|
195
|
+
readonly signal: AbortSignal;
|
|
196
|
+
/** Remaining cleanup budget when the call starts. */
|
|
197
|
+
readonly timeoutMs: number;
|
|
198
|
+
}
|
|
199
|
+
export interface BackendObserveOptions {
|
|
200
|
+
/** Requests masked viewport pixels for the same revision as the tree. */
|
|
201
|
+
readonly pixels?: boolean;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* One fresh semantic snapshot of the surface under test. The harness owns
|
|
205
|
+
* everything downstream: revision minting, secret redaction, and the
|
|
206
|
+
* observation byte budget apply to every backend equally.
|
|
207
|
+
*/
|
|
208
|
+
export interface BackendSnapshot {
|
|
209
|
+
readonly nodes: readonly SemanticNode[];
|
|
210
|
+
readonly viewport?: {
|
|
211
|
+
readonly width: number;
|
|
212
|
+
readonly height: number;
|
|
213
|
+
readonly scale: number;
|
|
214
|
+
};
|
|
215
|
+
/** Masked pixels, when requested and producible; omitted otherwise. */
|
|
216
|
+
readonly pixels?: ObservationPixels;
|
|
217
|
+
/** Regions masked in `pixels`; the harness checks it covers every secure node. */
|
|
218
|
+
readonly maskedRegionCount?: number;
|
|
219
|
+
}
|
|
220
|
+
/** The body of one target: typed, model-free, capability-graded. */
|
|
221
|
+
export interface Backend {
|
|
222
|
+
readonly name: string;
|
|
223
|
+
/**
|
|
224
|
+
* Implementation version, recorded as provenance and part of the trace
|
|
225
|
+
* cache identity: a backend that resolves nodes differently must not replay
|
|
226
|
+
* another version's traces, so an unversioned backend is not accepted.
|
|
227
|
+
*/
|
|
228
|
+
readonly version: string;
|
|
229
|
+
/**
|
|
230
|
+
* Contract version literal. Additive optional members never bump it;
|
|
231
|
+
* changed required semantics do.
|
|
232
|
+
*/
|
|
233
|
+
readonly spiVersion: BackendSpiVersion;
|
|
234
|
+
/** capability: observation. */
|
|
235
|
+
observe?(context: OperationContext, options?: BackendObserveOptions): Promise<BackendSnapshot>;
|
|
236
|
+
/**
|
|
237
|
+
* capability: actions - requires observation. Performs exactly one action
|
|
238
|
+
* on a ref this backend minted, from the newest observation or from
|
|
239
|
+
* `locate` (both live in one id space), with the platform's actionability
|
|
240
|
+
* checks. The agent's grammar verbs (tap, type, press, select, node scroll)
|
|
241
|
+
* and the `screen` tier's actions both bottom out here, so a surface
|
|
242
|
+
* implements each action once.
|
|
243
|
+
*
|
|
244
|
+
* Error contract (load-bearing for trace replay): throw a retryable
|
|
245
|
+
* `NODE_STALE`-coded error when a ref no longer binds, and an
|
|
246
|
+
* `ACTION_MAY_HAVE_COMMITTED`-coded error when input may have reached the
|
|
247
|
+
* app - the harness never blindly repeats an uncertain mutation.
|
|
248
|
+
*/
|
|
249
|
+
perform?(ref: NodeRef, action: LocatorAction, context: OperationContext): Promise<void>;
|
|
250
|
+
/**
|
|
251
|
+
* capability: location - requires observation. Deterministic locator
|
|
252
|
+
* resolution for the `screen`/`expect` tier: resolve one expression to the
|
|
253
|
+
* nodes it currently matches. The harness owns polling, strictness, and
|
|
254
|
+
* staleness; a backend resolves once, immediately.
|
|
255
|
+
*/
|
|
256
|
+
locate?(expression: LocatorExpression, context: OperationContext): Promise<readonly SemanticNode[]>;
|
|
257
|
+
/**
|
|
258
|
+
* Viewport-level swipe behind the agent's `scroll` verb, `screen.swipe`,
|
|
259
|
+
* and `scrollUntilVisible`; requires observation.
|
|
260
|
+
*/
|
|
261
|
+
swipe?(direction: ScrollDirection, momentum: Momentum | undefined, context: OperationContext): Promise<void>;
|
|
262
|
+
/**
|
|
263
|
+
* Named deterministic surfaces this backend contributes to TestFixtures
|
|
264
|
+
* (a device fixture, a document fixture - anything). Keys become fixture and
|
|
265
|
+
* capability names; `requires: ['<name>']` gates at selection.
|
|
266
|
+
*/
|
|
267
|
+
readonly fixtures?: Readonly<Record<string, BackendFixtureFactory>>;
|
|
268
|
+
/** capability: state - opaque snapshot capture/restore for session reuse. */
|
|
269
|
+
readonly state?: BackendStateCapability;
|
|
270
|
+
/** capability: artifacts - screenshots and traces under the attempt directory. */
|
|
271
|
+
readonly artifacts?: BackendArtifacts;
|
|
272
|
+
/** App-level hooks: navigate, back, restart, clearState. */
|
|
273
|
+
readonly app?: BackendApp;
|
|
274
|
+
/**
|
|
275
|
+
* Current top-level URL of the surface, when the platform has one. Enables
|
|
276
|
+
* trace start anchors and the secret-fill origin check.
|
|
277
|
+
*/
|
|
278
|
+
url?(context: OperationContext): Promise<string>;
|
|
279
|
+
/**
|
|
280
|
+
* Once per worker, before the first step; boot devices here, not in a step
|
|
281
|
+
* budget. The same handle can be booted again after `dispose`: a config-held
|
|
282
|
+
* handle outlives an in-process worker, so init MUST work on a disposed
|
|
283
|
+
* backend as it does on a fresh one.
|
|
284
|
+
*/
|
|
285
|
+
init?(info: BackendInitInfo): Promise<void>;
|
|
286
|
+
/** Before each attempt: set up per-test isolation. */
|
|
287
|
+
startAttempt?(context: BackendAttemptContext): Promise<void>;
|
|
288
|
+
/**
|
|
289
|
+
* After each attempt, within the cleanup budget: tear that isolation down.
|
|
290
|
+
* MUST be idempotent, and safe to call after a failed `startAttempt`.
|
|
291
|
+
*/
|
|
292
|
+
endAttempt?(context: BackendCleanupContext): Promise<void>;
|
|
293
|
+
/**
|
|
294
|
+
* Worker shutdown, within the cleanup budget; failure is a run error. Runs
|
|
295
|
+
* whether or not `init` ran, so it MUST tolerate a cold backend.
|
|
296
|
+
*/
|
|
297
|
+
dispose?(context: BackendCleanupContext): Promise<void>;
|
|
298
|
+
}
|
|
299
|
+
/** A validated backend: branded, frozen, capabilities computed. */
|
|
300
|
+
export interface BackendHandle extends Backend {
|
|
301
|
+
readonly [backendBrand]: true;
|
|
302
|
+
readonly capabilities: ReadonlySet<BackendCapability>;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Validates a backend and computes its capability set. Runs synchronously at
|
|
306
|
+
* config load and fails loud: a misspelled member or an undeclared dependency
|
|
307
|
+
* is `INVALID_CONFIG`, never a silent demotion to a lower tier.
|
|
308
|
+
*
|
|
309
|
+
* The handle is assembled member by member from the known keys, reading
|
|
310
|
+
* through the prototype chain and binding every function to the spec, so a
|
|
311
|
+
* class instance (own state fields included) is as valid a body as a literal.
|
|
312
|
+
*/
|
|
313
|
+
export declare function defineBackend(spec: Backend): BackendHandle;
|
|
314
|
+
/** True for a defineBackend-branded handle, across realms. */
|
|
315
|
+
export declare function isBackendHandle(value: unknown): value is BackendHandle;
|
|
316
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backend contract (RFC0002): the typed, model-free body of one target.
|
|
3
|
+
*
|
|
4
|
+
* A backend never talks to a model. It declares capabilities - observation,
|
|
5
|
+
* actions, location, state, artifacts, contributed fixtures - and the harness
|
|
6
|
+
* grades what a target can do from what its backend declares: observation
|
|
7
|
+
* unlocks the judgment tier and prompt snapshots, `perform` unlocks the
|
|
8
|
+
* harness-routed node actions (the agent's grammar verbs and the `screen`
|
|
9
|
+
* tier's actions alike), location unlocks `screen`/`expect`. Every piece of
|
|
10
|
+
* model-facing vocabulary is an agent-side `defineTool`; a target with no
|
|
11
|
+
* backend at all is valid and simply runs everything opaque.
|
|
12
|
+
*
|
|
13
|
+
* Core knows this contract and never a backend's internals: no platform noun
|
|
14
|
+
* appears here. A document backend, a simulator backend, and a desktop backend
|
|
15
|
+
* fill in the same members with different bodies.
|
|
16
|
+
*
|
|
17
|
+
* `defineBackend` is the loud manifest: capability detection happens here,
|
|
18
|
+
* synchronously, at config load - a malformed backend fails the run instead
|
|
19
|
+
* of silently demoting itself to a lower tier.
|
|
20
|
+
*/
|
|
21
|
+
import { backendBrand } from '../internal/brands.js';
|
|
22
|
+
import { ConfigurationError } from '../internal/errors.js';
|
|
23
|
+
// Semantics the spec requires every backend and contributed fixture to
|
|
24
|
+
// reproduce exactly, exported so a backend never carries its own copy: the
|
|
25
|
+
// runner error taxonomy (06-cli.md), text-pattern matching (04-locators.md),
|
|
26
|
+
// URL matching (03-assertions.md), assertion polling (03-assertions.md), and
|
|
27
|
+
// the JSON-value rules for data a fixture returns.
|
|
28
|
+
export { ConfigurationError, InfrastructureError, TestError } from '../internal/errors.js';
|
|
29
|
+
export { validateJsonValue } from '../internal/json-value.js';
|
|
30
|
+
export { describePattern, matchesText, toTextPattern } from '../internal/text.js';
|
|
31
|
+
export { Deadline, pollCondition } from '../internal/time.js';
|
|
32
|
+
export { urlMatches } from '../internal/urls.js';
|
|
33
|
+
import { BACKEND_SPI_VERSION, } from './contract.js';
|
|
34
|
+
export { BACKEND_ERROR_CODES, BACKEND_SPI_VERSION, BackendError, OBSERVED_NAME_LIMIT, OBSERVED_TEXT_LIMIT, RETRYABLE_BACKEND_ERROR_CODES, } from './contract.js';
|
|
35
|
+
/** Every key a backend may declare; anything else is rejected at config load. */
|
|
36
|
+
const KNOWN_KEYS = [
|
|
37
|
+
'name',
|
|
38
|
+
'version',
|
|
39
|
+
'spiVersion',
|
|
40
|
+
'observe',
|
|
41
|
+
'locate',
|
|
42
|
+
'perform',
|
|
43
|
+
'swipe',
|
|
44
|
+
'fixtures',
|
|
45
|
+
'state',
|
|
46
|
+
'artifacts',
|
|
47
|
+
'app',
|
|
48
|
+
'url',
|
|
49
|
+
'init',
|
|
50
|
+
'startAttempt',
|
|
51
|
+
'endAttempt',
|
|
52
|
+
'dispose',
|
|
53
|
+
];
|
|
54
|
+
/** Keys of the nested manifests, closed like the top level. */
|
|
55
|
+
const NESTED_KEYS = {
|
|
56
|
+
state: ['capture', 'restore'],
|
|
57
|
+
artifacts: ['screenshot', 'startTrace', 'stopTrace'],
|
|
58
|
+
app: ['navigate', 'back', 'restart', 'clearState'],
|
|
59
|
+
};
|
|
60
|
+
const FUNCTION_MEMBERS = [
|
|
61
|
+
'observe',
|
|
62
|
+
'locate',
|
|
63
|
+
'perform',
|
|
64
|
+
'swipe',
|
|
65
|
+
'url',
|
|
66
|
+
'init',
|
|
67
|
+
'startAttempt',
|
|
68
|
+
'endAttempt',
|
|
69
|
+
'dispose',
|
|
70
|
+
];
|
|
71
|
+
/** Universal fixture names a contribution may never shadow. */
|
|
72
|
+
const RESERVED_FIXTURES = new Set(['agent', 'app', 'screen', 'platform', 'session']);
|
|
73
|
+
const FIXTURE_NAME_PATTERN = /^[a-z][A-Za-z0-9]*$/;
|
|
74
|
+
function invalid(name, detail) {
|
|
75
|
+
return new ConfigurationError('INVALID_CONFIG', `backend "${name}": ${detail}`);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Validates one nested manifest (`state`, `artifacts`, `app`): a plain object
|
|
79
|
+
* whose keys are closed and whose declared members are functions. Returns a
|
|
80
|
+
* copy with every member bound to the manifest, so class-based bodies work.
|
|
81
|
+
*/
|
|
82
|
+
function nestedManifest(name, key, value, required = []) {
|
|
83
|
+
if (typeof value !== 'object' || value === null) {
|
|
84
|
+
throw invalid(name, `${key} must be an object`);
|
|
85
|
+
}
|
|
86
|
+
const allowed = NESTED_KEYS[key];
|
|
87
|
+
const source = value;
|
|
88
|
+
for (const member of Object.keys(source)) {
|
|
89
|
+
if (!allowed.includes(member)) {
|
|
90
|
+
throw invalid(name, `${key} has unknown key "${member}"; expected one of ${allowed.join(', ')}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const bound = {};
|
|
94
|
+
for (const member of allowed) {
|
|
95
|
+
const fn = source[member];
|
|
96
|
+
if (fn === undefined) {
|
|
97
|
+
if (required.includes(member))
|
|
98
|
+
throw invalid(name, `${key}.${member} must be a function`);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (typeof fn !== 'function')
|
|
102
|
+
throw invalid(name, `${key}.${member} must be a function`);
|
|
103
|
+
bound[member] = fn.bind(source);
|
|
104
|
+
}
|
|
105
|
+
return bound;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Validates a backend and computes its capability set. Runs synchronously at
|
|
109
|
+
* config load and fails loud: a misspelled member or an undeclared dependency
|
|
110
|
+
* is `INVALID_CONFIG`, never a silent demotion to a lower tier.
|
|
111
|
+
*
|
|
112
|
+
* The handle is assembled member by member from the known keys, reading
|
|
113
|
+
* through the prototype chain and binding every function to the spec, so a
|
|
114
|
+
* class instance (own state fields included) is as valid a body as a literal.
|
|
115
|
+
*/
|
|
116
|
+
export function defineBackend(spec) {
|
|
117
|
+
if (typeof spec !== 'object' || spec === null) {
|
|
118
|
+
throw new ConfigurationError('INVALID_CONFIG', 'defineBackend requires a backend object');
|
|
119
|
+
}
|
|
120
|
+
if (typeof spec.name !== 'string' || spec.name.trim() === '') {
|
|
121
|
+
throw new ConfigurationError('INVALID_CONFIG', 'backend.name must be a non-empty string');
|
|
122
|
+
}
|
|
123
|
+
const name = spec.name;
|
|
124
|
+
if (typeof spec.version !== 'string' || spec.version.trim() === '') {
|
|
125
|
+
throw invalid(name, 'version must be a non-empty string; it is provenance and keys the trace cache');
|
|
126
|
+
}
|
|
127
|
+
if (spec.spiVersion !== BACKEND_SPI_VERSION) {
|
|
128
|
+
throw invalid(name, `declares spiVersion ${String(spec.spiVersion)}; this runner supports ${BACKEND_SPI_VERSION}`);
|
|
129
|
+
}
|
|
130
|
+
// A literal's unknown key is a misspelling or a misplaced tool; a class
|
|
131
|
+
// instance's own fields are its state, so only literals are checked.
|
|
132
|
+
if (Object.getPrototypeOf(spec) === Object.prototype) {
|
|
133
|
+
const known = KNOWN_KEYS;
|
|
134
|
+
for (const key of Object.keys(spec)) {
|
|
135
|
+
if (!known.includes(key)) {
|
|
136
|
+
throw invalid(name, `unknown key "${key}" - tools belong on the agent, not the backend`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
for (const member of FUNCTION_MEMBERS) {
|
|
141
|
+
if (spec[member] !== undefined && typeof spec[member] !== 'function') {
|
|
142
|
+
throw invalid(name, `${member} must be a function`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const capabilities = new Set();
|
|
146
|
+
if (spec.observe !== undefined)
|
|
147
|
+
capabilities.add('observation');
|
|
148
|
+
if (spec.perform !== undefined) {
|
|
149
|
+
if (!capabilities.has('observation')) {
|
|
150
|
+
throw invalid(name, 'declares perform without observe: action targets are observation refs');
|
|
151
|
+
}
|
|
152
|
+
capabilities.add('actions');
|
|
153
|
+
}
|
|
154
|
+
if (spec.locate !== undefined) {
|
|
155
|
+
if (!capabilities.has('observation')) {
|
|
156
|
+
throw invalid(name, 'declares locate without observe: located nodes share the observation id space');
|
|
157
|
+
}
|
|
158
|
+
capabilities.add('location');
|
|
159
|
+
}
|
|
160
|
+
if (spec.swipe !== undefined && !capabilities.has('observation')) {
|
|
161
|
+
throw invalid(name, 'declares swipe without observe');
|
|
162
|
+
}
|
|
163
|
+
const handle = { name, version: spec.version, spiVersion: spec.spiVersion };
|
|
164
|
+
for (const member of FUNCTION_MEMBERS) {
|
|
165
|
+
const fn = spec[member];
|
|
166
|
+
if (fn !== undefined)
|
|
167
|
+
handle[member] = fn.bind(spec);
|
|
168
|
+
}
|
|
169
|
+
if (spec.fixtures !== undefined) {
|
|
170
|
+
if (typeof spec.fixtures !== 'object' || spec.fixtures === null) {
|
|
171
|
+
throw invalid(name, 'fixtures must be an object');
|
|
172
|
+
}
|
|
173
|
+
for (const [fixture, factory] of Object.entries(spec.fixtures)) {
|
|
174
|
+
if (!FIXTURE_NAME_PATTERN.test(fixture)) {
|
|
175
|
+
throw invalid(name, `fixture name "${fixture}" must be a lower-camel identifier`);
|
|
176
|
+
}
|
|
177
|
+
if (RESERVED_FIXTURES.has(fixture)) {
|
|
178
|
+
throw invalid(name, `fixture name "${fixture}" shadows a universal fixture`);
|
|
179
|
+
}
|
|
180
|
+
if (typeof factory !== 'function') {
|
|
181
|
+
throw invalid(name, `fixtures.${fixture} must be a factory function`);
|
|
182
|
+
}
|
|
183
|
+
capabilities.add(fixture);
|
|
184
|
+
}
|
|
185
|
+
// Bound like every other member, so a class-based backend keeps `this`
|
|
186
|
+
// in its fixture factories too.
|
|
187
|
+
handle['fixtures'] = Object.freeze(Object.fromEntries(Object.entries(spec.fixtures).map(([fixture, factory]) => [
|
|
188
|
+
fixture,
|
|
189
|
+
factory.bind(spec),
|
|
190
|
+
])));
|
|
191
|
+
}
|
|
192
|
+
if (spec.state !== undefined) {
|
|
193
|
+
handle['state'] = nestedManifest(name, 'state', spec.state, ['capture', 'restore']);
|
|
194
|
+
capabilities.add('state');
|
|
195
|
+
}
|
|
196
|
+
if (spec.artifacts !== undefined) {
|
|
197
|
+
const artifacts = nestedManifest(name, 'artifacts', spec.artifacts, ['screenshot']);
|
|
198
|
+
if ((artifacts['startTrace'] === undefined) !== (artifacts['stopTrace'] === undefined)) {
|
|
199
|
+
throw invalid(name, 'artifacts.startTrace and stopTrace must be declared together');
|
|
200
|
+
}
|
|
201
|
+
handle['artifacts'] = artifacts;
|
|
202
|
+
capabilities.add('artifacts');
|
|
203
|
+
}
|
|
204
|
+
if (spec.app !== undefined)
|
|
205
|
+
handle['app'] = nestedManifest(name, 'app', spec.app);
|
|
206
|
+
// Assembled key by key above, so the record is a Backend by construction.
|
|
207
|
+
return Object.freeze({
|
|
208
|
+
...handle,
|
|
209
|
+
[backendBrand]: true,
|
|
210
|
+
capabilities,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/** True for a defineBackend-branded handle, across realms. */
|
|
214
|
+
export function isBackendHandle(value) {
|
|
215
|
+
return (typeof value === 'object' &&
|
|
216
|
+
value !== null &&
|
|
217
|
+
value[backendBrand] === true);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,uEAAuE;AACvE,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,mDAAmD;AACnD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,iBAAiB,EAAuB,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAElF,OAAO,EAAE,QAAQ,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EACL,mBAAmB,GAQpB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,eAAe,CAAC;AAkTvB,iFAAiF;AACjF,MAAM,UAAU,GAAG;IACjB,MAAM;IACN,SAAS;IACT,YAAY;IACZ,SAAS;IACT,QAAQ;IACR,SAAS;IACT,OAAO;IACP,UAAU;IACV,OAAO;IACP,WAAW;IACX,KAAK;IACL,KAAK;IACL,MAAM;IACN,cAAc;IACd,YAAY;IACZ,SAAS;CACoC,CAAC;AAEhD,+DAA+D;AAC/D,MAAM,WAAW,GAAG;IAClB,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IAC7B,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC;IACpD,GAAG,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC;CAC1C,CAAC;AAEX,MAAM,gBAAgB,GAAG;IACvB,SAAS;IACT,QAAQ;IACR,SAAS;IACT,OAAO;IACP,KAAK;IACL,MAAM;IACN,cAAc;IACd,YAAY;IACZ,SAAS;CACD,CAAC;AAEX,+DAA+D;AAC/D,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;AAErF,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAEnD,SAAS,OAAO,CAAC,IAAY,EAAE,MAAc;IAC3C,OAAO,IAAI,kBAAkB,CAAC,gBAAgB,EAAE,YAAY,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CACrB,IAAY,EACZ,GAAM,EACN,KAAc,EACd,QAAQ,GAAsB,EAAE;IAEhC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,oBAAoB,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,OAAO,GAAsB,WAAW,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,MAAM,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,qBAAqB,MAAM,sBAAsB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAA4B,EAAE,CAAC;IAC1C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,MAAM,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,MAAM,qBAAqB,CAAC,CAAC;YAC1F,SAAS;QACX,CAAC;QACD,IAAI,OAAO,EAAE,KAAK,UAAU;YAAE,MAAM,OAAO,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,MAAM,qBAAqB,CAAC,CAAC;QACzF,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,kBAAkB,CAAC,gBAAgB,EAAE,yCAAyC,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7D,MAAM,IAAI,kBAAkB,CAAC,gBAAgB,EAAE,yCAAyC,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACvB,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACnE,MAAM,OAAO,CAAC,IAAI,EAAE,+EAA+E,CAAC,CAAC;IACvG,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,KAAK,mBAAmB,EAAE,CAAC;QAC5C,MAAM,OAAO,CACX,IAAI,EACJ,uBAAuB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,0BAA0B,mBAAmB,EAAE,CAC9F,CAAC;IACJ,CAAC;IACD,wEAAwE;IACxE,qEAAqE;IACrE,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;QACrD,MAAM,KAAK,GAAsB,UAAU,CAAC;QAC5C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,gDAAgD,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC;YACrE,MAAM,OAAO,CAAC,IAAI,EAAE,GAAG,MAAM,qBAAqB,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAqB,CAAC;IAClD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAChE,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YACrC,MAAM,OAAO,CAAC,IAAI,EAAE,uEAAuE,CAAC,CAAC;QAC/F,CAAC;QACD,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YACrC,MAAM,OAAO,CAAC,IAAI,EAAE,+EAA+E,CAAC,CAAC;QACvG,CAAC;QACD,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;QACjE,MAAM,OAAO,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACrG,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,IAAI,EAAE,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAChC,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAChE,MAAM,OAAO,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;QACpD,CAAC;QACD,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxC,MAAM,OAAO,CAAC,IAAI,EAAE,iBAAiB,OAAO,oCAAoC,CAAC,CAAC;YACpF,CAAC;YACD,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnC,MAAM,OAAO,CAAC,IAAI,EAAE,iBAAiB,OAAO,+BAA+B,CAAC,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;gBAClC,MAAM,OAAO,CAAC,IAAI,EAAE,YAAY,OAAO,6BAA6B,CAAC,CAAC;YACxE,CAAC;YACD,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QACD,uEAAuE;QACvE,gCAAgC;QAChC,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,CAChC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;YACxD,OAAO;YACN,OAA2C,CAAC,IAAI,CAAC,IAAI,CAAC;SACxD,CAAC,CACH,CACF,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QACpF,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;QACpF,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,SAAS,CAAC,EAAE,CAAC;YACvF,MAAM,OAAO,CAAC,IAAI,EAAE,8DAA8D,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;QAChC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAElF,0EAA0E;IAC1E,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,GAAG,MAAM;QACT,CAAC,YAAY,CAAC,EAAE,IAAa;QAC7B,YAAY;KACb,CAA6B,CAAC;AACjC,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACb,KAAsC,CAAC,YAAY,CAAC,KAAK,IAAI,CAC/D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backend-to-session adapter (RFC0002). One adapter per attempt satisfies
|
|
3
|
+
* the internal `TargetSession` surface over the backend contract, so the agent
|
|
4
|
+
* tier, the judgment tier, the trace cache, and the fixture graph program
|
|
5
|
+
* against one shape. It is the single seam every backend call crosses, which
|
|
6
|
+
* makes it the one place two rules are enforced: a capability the backend does
|
|
7
|
+
* not declare fails loud with `UNSUPPORTED_CAPABILITY` at the moment of use,
|
|
8
|
+
* and anything a backend throws that is not a `BackendError` is normalized to
|
|
9
|
+
* a non-retryable `BACKEND_FAILURE`, so a crashed backend is an infrastructure
|
|
10
|
+
* failure everywhere and never a retry-eligible test failure.
|
|
11
|
+
*/
|
|
12
|
+
import type { BackendHandle } from './index.ts';
|
|
13
|
+
import { type TargetSession } from './surface.ts';
|
|
14
|
+
export interface BackendSessionOptions {
|
|
15
|
+
readonly backend: BackendHandle | undefined;
|
|
16
|
+
readonly targetName: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Builds one session over a backend. One adapter per attempt; revisions are
|
|
20
|
+
* minted per adapter, so refs can never leak across attempts.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createBackendSession(options: BackendSessionOptions): TargetSession;
|
|
23
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/backend/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAOL,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAmED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,aAAa,CA2IlF"}
|