@codemation/core 1.0.0 → 2.0.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/CHANGELOG.md +312 -0
- package/dist/{EngineRuntimeRegistration.types-BP6tsaNP.d.ts → EngineRuntimeRegistration.types-D1fyApMI.d.ts} +2 -2
- package/dist/{EngineWorkflowRunnerService-DzOCa1BW.d.cts → EngineRuntimeRegistration.types-pB3FnzqR.d.cts} +17 -17
- package/dist/{InMemoryRunDataFactory-1iz7_SnO.d.cts → InMemoryRunDataFactory-Xw7v4-sj.d.cts} +31 -29
- package/dist/InMemoryRunEventBusRegistry-VM3OWnHo.cjs +47 -0
- package/dist/InMemoryRunEventBusRegistry-VM3OWnHo.cjs.map +1 -0
- package/dist/InMemoryRunEventBusRegistry-sM4z4n_i.js +41 -0
- package/dist/InMemoryRunEventBusRegistry-sM4z4n_i.js.map +1 -0
- package/dist/{RunIntentService-BqhmdoA1.d.ts → RunIntentService-BE9CAkbf.d.ts} +966 -471
- package/dist/{RunIntentService-S-1lW-gS.d.cts → RunIntentService-siBSjaaY.d.cts} +859 -493
- package/dist/bootstrap/index.cjs +5 -2
- package/dist/bootstrap/index.d.cts +212 -135
- package/dist/bootstrap/index.d.ts +4 -4
- package/dist/bootstrap/index.js +3 -3
- package/dist/{bootstrap-BfZE19lK.cjs → bootstrap-Cm5ruQxx.cjs} +253 -2
- package/dist/bootstrap-Cm5ruQxx.cjs.map +1 -0
- package/dist/{bootstrap-jqh1kCNI.js → bootstrap-D3r505ko.js} +236 -3
- package/dist/bootstrap-D3r505ko.js.map +1 -0
- package/dist/{index-CGs3Hnoz.d.ts → index-DeLl1Tne.d.ts} +599 -219
- package/dist/index.cjs +323 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +511 -80
- package/dist/index.d.ts +3 -3
- package/dist/index.js +299 -166
- package/dist/index.js.map +1 -1
- package/dist/{runtime-u6O644ST.js → runtime-BGNbRnqs.js} +933 -74
- package/dist/runtime-BGNbRnqs.js.map +1 -0
- package/dist/{runtime-DWKfb0BI.cjs → runtime-DKXJwTNv.cjs} +1027 -72
- package/dist/runtime-DKXJwTNv.cjs.map +1 -0
- package/dist/testing.cjs +4 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +3 -3
- package/package.json +7 -2
- package/src/ai/AiHost.ts +9 -0
- package/src/authoring/DefinedCollectionRegistry.ts +17 -0
- package/src/authoring/defineCollection.types.ts +181 -0
- package/src/authoring/definePollingTrigger.types.ts +396 -0
- package/src/authoring/definePollingTriggerInternals.ts +74 -0
- package/src/authoring/index.ts +19 -0
- package/src/bootstrap/index.ts +9 -0
- package/src/bootstrap/runtime/EngineRuntimeRegistrar.ts +8 -0
- package/src/browser.ts +1 -0
- package/src/contracts/CodemationTelemetryAttributeNames.ts +6 -0
- package/src/contracts/NoOpNodeExecutionTelemetry.ts +2 -11
- package/src/contracts/NoOpTelemetrySpanScope.ts +46 -10
- package/src/contracts/assertionTypes.ts +63 -0
- package/src/contracts/baseTypes.ts +12 -0
- package/src/contracts/collectionTypes.ts +44 -0
- package/src/contracts/credentialTypes.ts +23 -1
- package/src/contracts/executionPersistenceContracts.ts +30 -0
- package/src/contracts/index.ts +4 -0
- package/src/contracts/runTypes.ts +37 -1
- package/src/contracts/runtimeTypes.ts +42 -0
- package/src/contracts/telemetryTypes.ts +8 -0
- package/src/contracts/testTriggerTypes.ts +66 -0
- package/src/contracts/workflowTypes.ts +36 -7
- package/src/contracts.ts +59 -0
- package/src/events/ConnectionInvocationEventPublisher.ts +46 -0
- package/src/events/index.ts +1 -0
- package/src/events/runEvents.ts +74 -0
- package/src/execution/ChildExecutionScopeFactory.ts +55 -0
- package/src/execution/DefaultExecutionContextFactory.ts +6 -0
- package/src/execution/ExecutionTelemetryCostTrackingDecoratorFactory.ts +18 -0
- package/src/execution/NodeExecutor.ts +10 -2
- package/src/execution/NodeInstanceFactory.ts +13 -1
- package/src/execution/NodeInstantiationError.ts +16 -0
- package/src/execution/NodeRunStateWriter.ts +7 -0
- package/src/execution/NodeRunStateWriterFactory.ts +7 -0
- package/src/execution/WorkflowRunExecutionContextFactory.ts +3 -0
- package/src/execution/index.ts +2 -0
- package/src/index.ts +8 -0
- package/src/orchestration/AbortControllerFactory.ts +9 -0
- package/src/orchestration/NodeExecutionRequestHandlerService.ts +1 -0
- package/src/orchestration/RunContinuationService.ts +3 -0
- package/src/orchestration/RunStartService.ts +114 -2
- package/src/orchestration/TestSuiteOrchestrator.ts +350 -0
- package/src/orchestration/TestSuiteRunIdFactory.ts +11 -0
- package/src/orchestration/TriggerRuntimeService.ts +34 -7
- package/src/orchestration/index.ts +9 -0
- package/src/runtime/EngineFactory.ts +12 -0
- package/src/triggers/polling/PollingTriggerDedupWindow.ts +23 -0
- package/src/triggers/polling/PollingTriggerLogger.ts +18 -0
- package/src/triggers/polling/PollingTriggerRuntime.ts +122 -0
- package/src/triggers/polling/index.ts +5 -0
- package/src/types/index.ts +12 -9
- package/src/workflow/definition/NodeIterationIdFactory.ts +26 -0
- package/src/workflow/dsl/NodeIdSlugifier.ts +18 -0
- package/src/workflow/dsl/WorkflowBuilder.ts +71 -3
- package/src/workflow/dsl/WorkflowDefinitionError.ts +15 -0
- package/src/workflow/index.ts +3 -0
- package/dist/InMemoryRunEventBusRegistry-B0_C4OnP.cjs +0 -262
- package/dist/InMemoryRunEventBusRegistry-B0_C4OnP.cjs.map +0 -1
- package/dist/InMemoryRunEventBusRegistry-C2U83Hmv.js +0 -238
- package/dist/InMemoryRunEventBusRegistry-C2U83Hmv.js.map +0 -1
- package/dist/bootstrap-BfZE19lK.cjs.map +0 -1
- package/dist/bootstrap-jqh1kCNI.js.map +0 -1
- package/dist/runtime-DWKfb0BI.cjs.map +0 -1
- package/dist/runtime-u6O644ST.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,317 @@
|
|
|
1
1
|
# @codemation/core
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#102](https://github.com/MadeRelevant/codemation/pull/102) [`6566d55`](https://github.com/MadeRelevant/codemation/commit/6566d55c829f6631357ac95052b0852e86092ac5) Thanks [@cblokland90](https://github.com/cblokland90)! - **Breaking change:** Default node ids in `WorkflowBuilder` now derive from a slug of the node's label (`config.name`) instead of a sequential counter (`${tokenName}:${seq}`).
|
|
8
|
+
|
|
9
|
+
Previously, adding or reordering nodes changed their auto-assigned ids, silently orphaning credential bindings stored in the database (keyed by `workflowId + nodeId + slotKey`). The new scheme makes ids stable across reorders and inserts.
|
|
10
|
+
|
|
11
|
+
**Migration required:** Any existing credential bindings keyed by the old `${tokenName}:${seq}` format will appear unbound after this change. Users must re-bind credentials manually in the workflow editor. To avoid disruption, add an explicit `id:` field to node configs before upgrading — explicit ids are unaffected by this change and take priority over the label slug.
|
|
12
|
+
|
|
13
|
+
**Validation added:** `WorkflowBuilder.build()` now throws `WorkflowDefinitionError` if any node has an empty effective id (blank label + no explicit id) or if two nodes share the same effective id. Fix: provide a unique `id:` on the offending node configs.
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- [#111](https://github.com/MadeRelevant/codemation/pull/111) [`a77505f`](https://github.com/MadeRelevant/codemation/commit/a77505f331d7d3892f3c1c8f19dc37952b4d96bd) Thanks [@cblokland90](https://github.com/cblokland90)! - Add `definePollingTrigger` helper for declarative polling trigger authoring.
|
|
18
|
+
|
|
19
|
+
Plugin authors can now define polling triggers with a single `definePollingTrigger({...})` call instead of manually wiring `PollingTriggerRuntime` + `RunnableNodeConfig` + `@node` class pairs. The helper synthesises both the trigger config class and the runtime adapter, handles internal dedup-key bookkeeping, and exposes a `poll()` test seam for unit testing without spinning up the runtime.
|
|
20
|
+
|
|
21
|
+
- [#101](https://github.com/MadeRelevant/codemation/pull/101) [`2c0723f`](https://github.com/MadeRelevant/codemation/commit/2c0723fb1670e842c272939b5db73d4b95b25535) Thanks [@cblokland90](https://github.com/cblokland90)! - Add collections: declare typed Postgres/SQLite-backed data tables in the codemation config via `defineCollection({...})`. Schema sync runs at runtime startup behind an advisory lock (Postgres) or in-process mutex (SQLite).
|
|
22
|
+
|
|
23
|
+
Workflow access:
|
|
24
|
+
- `ctx.collections.<name>.crud(...)` from inside custom node code
|
|
25
|
+
- Six new canvas nodes: `CollectionInsert`, `CollectionGet`, `CollectionFindOne`, `CollectionList`, `CollectionUpdate`, `CollectionDelete`
|
|
26
|
+
|
|
27
|
+
Operator surfaces:
|
|
28
|
+
- HTTP API at `/collections/*`
|
|
29
|
+
- CLI: `codemation collections list|show|rows|get|insert|update|delete|sync`
|
|
30
|
+
- UI at `/collections`
|
|
31
|
+
|
|
32
|
+
Destructive schema changes (column drops, type changes) require `CODEMATION_COLLECTIONS_ALLOW_DESTRUCTIVE=1`.
|
|
33
|
+
|
|
34
|
+
Out of scope (separate PRs):
|
|
35
|
+
- Real leader election (advisory lock at boot is sufficient for sync; trigger double-firing during container swap is unaddressed)
|
|
36
|
+
- Admin-role gating on the UI
|
|
37
|
+
- Runtime user-defined schemas (Airtable-style)
|
|
38
|
+
- Joins, aggregates, query DSL beyond indexed-field equality
|
|
39
|
+
|
|
40
|
+
- [#109](https://github.com/MadeRelevant/codemation/pull/109) [`fb9f7fe`](https://github.com/MadeRelevant/codemation/commit/fb9f7fed9bf5a3d6b0c5f78a30027be3ab7bcaca) Thanks [@cblokland90](https://github.com/cblokland90)! - OAuth2 plugin authors can now declare `authorizeUrl` / `tokenUrl` (with `{publicFieldKey}` template substitution) directly on a credential type's `auth` definition — no core change required to add a new provider. Migrated `@codemation/core-nodes-msgraph` to use this for Microsoft tenant-templated URLs (fixes "Unsupported OAuth2 provider id: microsoft" on connect).
|
|
41
|
+
|
|
42
|
+
Removed dead `@codemation/core-nodes-gmail` devDep from `@codemation/host` and the matching `serverExternalPackages` entry from `@codemation/next-host` so plugin-author `pnpm dev` no longer rebuilds gmail when working on an unrelated plugin.
|
|
43
|
+
|
|
44
|
+
Softened the credentials UI's "Not set in host env: …" message: it's now an informational tip with neutral styling (was destructive/error styling), since the field works perfectly fine when filled in manually.
|
|
45
|
+
|
|
46
|
+
- [#101](https://github.com/MadeRelevant/codemation/pull/101) [`2c0723f`](https://github.com/MadeRelevant/codemation/commit/2c0723fb1670e842c272939b5db73d4b95b25535) Thanks [@cblokland90](https://github.com/cblokland90)! - Add collections authoring API: `defineCollection()` for declaring typed data tables, `DefinedCollectionRegistry` for registration, and `CollectionStore` contract for runtime access. Includes column DSL (`c.text()`, `c.int()`, etc.) with validation for field/index names and reserved fields.
|
|
47
|
+
|
|
48
|
+
- [#108](https://github.com/MadeRelevant/codemation/pull/108) [`781c146`](https://github.com/MadeRelevant/codemation/commit/781c146eb9d8bb8bdbc1963ea2a4b9abe4b7bfbf) Thanks [@cblokland90](https://github.com/cblokland90)! - Extract generic polling-trigger machinery from gmail into core and expose it via setup context.
|
|
49
|
+
|
|
50
|
+
**`@codemation/core`** — new polling-trigger API
|
|
51
|
+
- New `PollingTriggerRuntime` class: owns the set-interval loop, overlap guard, and state persistence via `TriggerSetupStateRepository`. Plugin authors no longer need to implement these themselves.
|
|
52
|
+
- New `PollingTriggerDedupWindow` class: merges processed-ID sets with a configurable cap (default 2000). Prevents unbounded memory growth across polling cycles.
|
|
53
|
+
- New `PollingTriggerHandle` interface exposed on `TriggerSetupContext.polling`: pre-binds trigger id, emit, and registerCleanup so plugin code only supplies `intervalMs` and `runCycle`. The handle also carries a `.dedup` reference for message-level deduplication.
|
|
54
|
+
- `EngineDeps.pollingTriggerLogger` optional field: hosts may wire a real logger; defaults to a no-op.
|
|
55
|
+
- `PollingTriggerRuntime`, `PollingTriggerDedupWindow`, and `NoOpPollingTriggerLogger` are exported from the main `@codemation/core` barrel.
|
|
56
|
+
- ESLint `allowedConstructorNames` extended to include `AbortController` (a global built-in, not a DI-managed class).
|
|
57
|
+
|
|
58
|
+
**`@codemation/core-nodes-gmail`** — internal refactor, no external API change
|
|
59
|
+
- `GmailPollingTriggerRuntime` deleted; loop/overlap-guard/persistence now come from the core runtime.
|
|
60
|
+
- `GmailPollingService.poll` renamed to `runCycle`; repo injection and `persist()` method removed; dedup delegated to `PollingTriggerDedupWindow`.
|
|
61
|
+
- `OnNewGmailTriggerNode.setup` now calls `ctx.polling.start(...)` instead of `gmailPollingTriggerRuntime.ensureStarted(...)`.
|
|
62
|
+
- `GmailNodeTokens.RuntimeLogger` token removed (no longer needed).
|
|
63
|
+
|
|
64
|
+
- [#100](https://github.com/MadeRelevant/codemation/pull/100) [`11616ae`](https://github.com/MadeRelevant/codemation/commit/11616aefb91d4b96b7eb9af4b935eec055a8a7bb) Thanks [@cblokland90](https://github.com/cblokland90)! - Foundation for first-class **workflow testing**: a TestTrigger node, an IsTestRun branching node, an Assertion node, a `TestSuiteOrchestrator` service that fans one workflow run per yielded fixture item, host-side persistence (Prisma `TestSuiteRun` + `TestAssertion` tables, repositories, `TestRunnerService`), and a per-suite event tracker that records assertions and node coverage. HTTP routes and the canvas Tests tab (next-host) ship in follow-up slices.
|
|
65
|
+
|
|
66
|
+
**What this slice adds**
|
|
67
|
+
- **`@codemation/core` — additive contract changes**
|
|
68
|
+
- `RunExecutionOptions.testContext?: { testSuiteRunId; testCaseIndex }` — set by the orchestrator on each test-case run; threaded through `ExecutionContext` so nodes can read it as `ctx.testContext`. Propagates to subworkflow runs via `ParentExecutionRef.testContext` + `EngineExecutionLimitsPolicy.mergeExecutionOptionsForNewRun`, so assertions emitted by subworkflows land under the correct parent test case.
|
|
69
|
+
- `TriggerNodeConfig.triggerKind?: "live" | "test"` — `"test"` triggers are skipped by `TriggerRuntimeService` (live activation, webhooks, polling) and are only invoked by the orchestrator.
|
|
70
|
+
- `NodeConfigBase.emitsAssertions?: true` — marker the host-side `TestAssertionPersister` (next slice) keys off when subscribing to `nodeCompleted`.
|
|
71
|
+
- New `AssertionResult` type (`pass | fail | error`, plus `score`, `expected`, `actual`, `message`, `details`) — the stable shape every assertion node emits on `main`.
|
|
72
|
+
- New `TestTriggerNodeConfig` + `TestTriggerSetupContext` — author callback signature returns `AsyncIterable<Item>` and exposes credential resolution + an `AbortSignal`.
|
|
73
|
+
- New `RunEvent` kinds: `testSuiteStarted`, `testCaseStarted`, `testCaseCompleted`, `testSuiteFinished` (with terminal status `succeeded | failed | partial | cancelled | errored`).
|
|
74
|
+
- New `TestSuiteOrchestrator` service in `orchestration/` — drives the iterator, applies a per-suite concurrency semaphore (default 4), dispatches one `engine.runWorkflow(...)` per item with `executionOptions.testContext` set, awaits terminal status, and publishes lifecycle events on the existing `RunEventBus`. No persistence, no HTTP — pure engine logic so tests can drive it via in-memory deps.
|
|
75
|
+
- `TestSuiteRunIdFactory`, `AbortControllerFactory` — DI-friendly minters used by the orchestrator.
|
|
76
|
+
- **`@codemation/core-nodes` — three new nodes**
|
|
77
|
+
- **`TestTrigger`** / `TestTriggerNode`: drop on the canvas alongside live triggers. `setup` is a no-op; `execute` is a passthrough. The author's `generateItems` is consumed by the orchestrator.
|
|
78
|
+
- **`IsTestRun`** / `IsTestRunNode`: per-item router with `true` / `false` ports. Routes to `true` iff `ctx.testContext` is set — lets workflows skip real side-effects in test runs (e.g. don't actually send the reply).
|
|
79
|
+
- **`Assertion`** / `AssertionNode`: generic callback-style assertion node. Author returns `Promise<AssertionResult[]>` per item; the node emits one workflow `Item` per result. Sets `emitsAssertions: true` so the host persister can identify it.
|
|
80
|
+
- Declarative shorthands (`StringEqualsAssertionNode`, `JudgeByAgentAssertionNode`) intentionally deferred — the generic callback node covers Phase 1 and the declarative variants compose on top.
|
|
81
|
+
- **`@codemation/host` — persistence + orchestration + HTTP**
|
|
82
|
+
- **Prisma schema**: new `TestSuiteRun` and `TestAssertion` tables in both Postgres and SQLite mirrors. Adds `Run.testSuiteRunId` (FK with `ON DELETE SET NULL`) and `Run.testCaseIndex` (indexed for join + ordering). Workflow definition itself is **not** FK'd — workflows live in code; `TestSuiteRun.triggerNodeName` is snapshotted at creation so historical viewing survives node renames/deletions.
|
|
83
|
+
- **`TestSuiteRunRepository`** + **`TestAssertionRepository`** domain interfaces with Prisma + in-memory adapters.
|
|
84
|
+
- **`TestRunnerService`** (host application layer) — single facade for "start a test suite": creates the persistence row, drives the orchestrator, awaits, finalizes counts + coverage. Subscribes to `RunEventBus.subscribeToWorkflow` only for the lifetime of one suite (no global subscriber, no shared mutable state across concurrent suites).
|
|
85
|
+
- **`TestSuiteRunTracker`** + **`TestSuiteRunTrackerFactory`** — per-suite event accumulator. Two-stage event buffering tolerates inline runners that emit `nodeCompleted` synchronously inside `runWorkflow` (before the orchestrator publishes `testCaseStarted`); without it, fast/in-memory engines drop assertions silently.
|
|
86
|
+
- **`AssertionResultGuard`** — type-guard the tracker uses to skip junk output if a misconfigured `emitsAssertions: true` node emits non-assertion items (defensive, not crash-on-bad-input).
|
|
87
|
+
- **HTTP routes** (Hono, all behind the existing session-verifier middleware):
|
|
88
|
+
- `POST /api/workflows/:workflowId/test-suite-runs` body `{ triggerNodeId, concurrency? }` → 201 with `{ testSuiteRunId, status, totalCases, passedCases, failedCases }`
|
|
89
|
+
- `GET /api/workflows/:workflowId/test-suite-runs` → list summaries
|
|
90
|
+
- `GET /api/test-suite-runs/:id` → detail (including `concurrency`, `nodeCoverage`, `errorMessage`)
|
|
91
|
+
- `GET /api/test-suite-runs/:id/assertions` → all assertions across the suite's child runs
|
|
92
|
+
- `GET /api/runs/:runId/assertions` → assertions for one child run
|
|
93
|
+
- Paths exposed through `ApiPaths.workflowTestSuiteRuns/testSuiteRun/testSuiteRunAssertions/runAssertions` so the next-host React Query layer can call them by helper instead of string literals.
|
|
94
|
+
- **DI bootstrap** in `AppContainerFactory`: registers all new singletons (factories, mappers, guard, repository selector, route handler + registrar) and wires Prisma vs in-memory `TestSuiteRunRepository` / `TestAssertionRepository` based on `appConfig.persistence.kind` (mirroring the existing `WorkflowRunRepository` selection). `TestSuiteOrchestrator` itself is registered via a tsyringe factory that injects `Engine` + the engine-side `RunEventBus` + a fresh `CredentialResolverFactory(CredentialSessionService)`.
|
|
95
|
+
- **DTOs** in `application/contracts/TestingContracts.ts`: `StartTestSuiteRunRequest/Response`, `TestSuiteRunSummaryDto`, `TestSuiteRunDetailDto`, `TestAssertionDto`. Mappers (`TestSuiteRunSummaryMapper`, `TestAssertionMapper`) translate persistence records → wire shape.
|
|
96
|
+
- **WebSocket / event narrowing** — `WorkflowWebsocketServer` and one integration test reader updated to type-narrow on the new test-suite event kinds (which carry `testSuiteRunId` rather than `runId`).
|
|
97
|
+
|
|
98
|
+
**Tests**
|
|
99
|
+
- `TestSuiteOrchestrator` unit suite (6 tests): per-item dispatch with `testContext`, partial-pass aggregation, lifecycle event emission, concurrency cap, `errored` status when `generateItems` throws, rejection of non-test triggers.
|
|
100
|
+
- Node unit suite (6 tests): TestTrigger passthrough + `triggerKind === "test"`, IsTestRun routing on both branches, AssertionNode emitting one item per result, `emitsAssertions === true`.
|
|
101
|
+
- `TestRunnerService` integration suite (2 tests): creates the persistence row, finalizes counts + coverage, persists 3 `TestAssertion` rows from a 2-case suite (one passing, one failing); rejects non-test triggers without leaving a phantom row.
|
|
102
|
+
- **`@codemation/next-host` — Tests tab UI**
|
|
103
|
+
- **Third canvas tab** ("Tests") next to Live workflow / Executions, mutually exclusive with both. Local React state for now (Phase 1) — promotion to the URL codec is a Phase 2 cleanup once the UX is settled.
|
|
104
|
+
- **`TestsPanel`** — top-level container with a trigger picker (shadcn `Select` populated from workflow nodes whose `triggerKind === "test"`), a "Run tests" CTA wired through `useStartTestSuiteRunMutation`, a left list of past suite runs, and a right detail panel.
|
|
105
|
+
- **`TestSuitePassRateChart`** — recharts line chart of pass rate over time across this workflow's suite runs. Carries an explicit `rolling-input` label so authors don't read trends as agent regressions when the underlying fixtures drift (Phase 2 ships snapshots).
|
|
106
|
+
- **`TestSuiteRunsList`** + **`TestSuiteRunStatusBadge`** — list rows + colored status badges (`running` / `succeeded` / `partial` / `failed` / `cancelled` / `errored`).
|
|
107
|
+
- **`TestSuiteRunDetailPanel`** — header with pass-rate + counts + concurrency + nodes-covered + (when set) an `errorMessage` callout; the body is a per-run grouped assertions list.
|
|
108
|
+
- **`TestAssertionsList`** + **`TestAssertionRow`** — each assertion shows status badge, optional score, optional `expected`/`actual` JSON viewers side-by-side.
|
|
109
|
+
- **React Query hooks** (`testSuiteHooks.ts`) cover all four GET endpoints plus the start mutation, with cache invalidation on `workflowTestSuiteRunsQueryKey` after a successful run.
|
|
110
|
+
- **WorkflowNodeDto** + **mapper additions** (host + next-host's `PersistedWorkflowSnapshotMapper`) propagate `triggerKind` to the wire shape so the Tests panel can identify test triggers without server round-trips. Both mappers default omitted values to `"live"` to keep the wire DTO consistent.
|
|
111
|
+
|
|
112
|
+
**Not in this slice (planned follow-ups)**
|
|
113
|
+
- Test-input snapshots (Phase 2 — Phase 1 inputs are always live; UI carries a "rolling-input" label so charts aren't read as agent regressions).
|
|
114
|
+
- Declarative assertion family (StringEquals, JsonPath, JudgeByAgent helpers — generic callback `Assertion` covers Phase 1).
|
|
115
|
+
- Cancellation endpoint (`POST /api/test-suite-runs/:id/cancel`) — orchestrator already supports `AbortSignal` cancellation; the HTTP surface for it is deferred until the UI surfaces it.
|
|
116
|
+
- Realtime updates on the Tests panel — currently the suite list refetches on mutation success; live `testSuite*` events arrive via the existing realtime bridge but the Tests panel doesn't subscribe yet.
|
|
117
|
+
- URL codec entry for `pane=tests` so suite drilldowns are deep-linkable (currently in-memory React state).
|
|
118
|
+
- Coverage heatmap overlay on the canvas itself.
|
|
119
|
+
|
|
120
|
+
The contract additions are **strictly additive**; no existing API surface changed shape.
|
|
121
|
+
|
|
122
|
+
### Patch Changes
|
|
123
|
+
|
|
124
|
+
- [#110](https://github.com/MadeRelevant/codemation/pull/110) [`4902978`](https://github.com/MadeRelevant/codemation/commit/49029782243ece59ab6aa5bb46396db445cad47c) Thanks [@cblokland90](https://github.com/cblokland90)! - Add per-package `test:unit` scripts so Turbo can address each package individually for affected-only filtering. No runtime changes — dev-tooling only.
|
|
125
|
+
|
|
126
|
+
- [#100](https://github.com/MadeRelevant/codemation/pull/100) [`11616ae`](https://github.com/MadeRelevant/codemation/commit/11616aefb91d4b96b7eb9af4b935eec055a8a7bb) Thanks [@cblokland90](https://github.com/cblokland90)! - Major dev-server startup-time and bundle-size improvements, plus dev-CLI hardening.
|
|
127
|
+
|
|
128
|
+
**Why this matters**
|
|
129
|
+
|
|
130
|
+
Before this work, opening the workflow detail page on a 4-cpu / 8-GB WSL box would
|
|
131
|
+
OOM-kill `next-server` mid-compile (~5 GB peak RSS). After: the page cold-compiles in
|
|
132
|
+
**5.5 s** with peak **1.8 GB** and the dev server stays comfortably alive. The dev CLI
|
|
133
|
+
also boots significantly faster and survives consumer-source errors without tearing
|
|
134
|
+
the whole session down.
|
|
135
|
+
|
|
136
|
+
**Hard numbers**
|
|
137
|
+
- Workflow page Turbopack RSS peak: **5.0 GB → 1.8 GB** (-64%)
|
|
138
|
+
- Workflow page cold compile time: **~14 s → ~5.5 s**
|
|
139
|
+
- Lucide-react files in workflow page bundle: **1,713 → 74** (-95.7%)
|
|
140
|
+
- Host package typecheck: **17.5 s / 4,093 files / 2.1 GB → 8.8 s / 2,806 files / 1.9 GB**
|
|
141
|
+
- Host source tree: **-112,492 lines** of generated Prisma `.d.ts`
|
|
142
|
+
- Host circular dep cycles: **92 → 21**
|
|
143
|
+
- Core circular dep cycles: **53 → 50**
|
|
144
|
+
|
|
145
|
+
**`@codemation/next-host`**
|
|
146
|
+
- New `WorkflowCanvasLucideIconRegistry` — curated 18-icon set used by core node plugins.
|
|
147
|
+
Replaces `lucide-react/dynamic` (which forced bundling of all 1,713 icons because it
|
|
148
|
+
loads them by string at runtime). Workflows using `icon: "lucide:<unknown>"` now fall
|
|
149
|
+
back to the `Boxes` icon and emit a one-time `console.warn`. **Plugin authors needing
|
|
150
|
+
custom icons must ship SVG via `builtin:` / `si:` / URL tokens.**
|
|
151
|
+
- New slim subpath exports on `@codemation/host`: **`@codemation/host/dto`**,
|
|
152
|
+
**`@codemation/host/mapping`**, plus extensions to **`@codemation/host/client`**.
|
|
153
|
+
All 65 deep `@codemation/host-src/*` imports replaced; `@codemation/host-src/*`
|
|
154
|
+
tsconfig path removed. Prevents the UI from dragging the heavy host runtime graph
|
|
155
|
+
through Turbopack on every UI route compile.
|
|
156
|
+
- 42 lucide-react named imports rewritten to per-icon deep imports
|
|
157
|
+
(`lucide-react/dist/esm/icons/<kebab>`).
|
|
158
|
+
- Workflow detail page lazy-loads `WorkflowDetailScreenTestsView` and the
|
|
159
|
+
Monaco-backed `WorkflowJsonEditorDialog`.
|
|
160
|
+
- Removed `@codemation/core` and `@codemation/host` from `transpilePackages` and
|
|
161
|
+
dropped the corresponding root-barrel tsconfig paths so Next loads them from
|
|
162
|
+
compiled `dist/` instead of TypeScript source.
|
|
163
|
+
- Dev: `EdgeSessionVerifier` resolves `/api/auth/session` via
|
|
164
|
+
`x-forwarded-host` (the dev gateway) instead of `request.nextUrl.origin` (Next's
|
|
165
|
+
loopback). Previously the auth-check fetch looped back into Next, forcing
|
|
166
|
+
Turbopack to compile the catch-all `/api/[[...path]]` route on every page load.
|
|
167
|
+
|
|
168
|
+
**`@codemation/host`**
|
|
169
|
+
- Generated Prisma clients (`prisma-client`, `prisma-postgresql-client`,
|
|
170
|
+
`prisma-sqlite-client`) moved out of `src/infrastructure/persistence/generated/`
|
|
171
|
+
to `prisma-generated/` (sibling of `src/`). They're still typechecked and bundled
|
|
172
|
+
by the host build, but no longer pollute the public source surface that downstream
|
|
173
|
+
packages walk.
|
|
174
|
+
- New **`@codemation/host/dto`**, **`@codemation/host/mapping`** subpath exports
|
|
175
|
+
re-exposing only the contract DTO types and presentation factories the UI needs.
|
|
176
|
+
The existing **`@codemation/host/client`** subpath gained `ApiPaths`,
|
|
177
|
+
`BrowserLoggerFactory`, `logLevelPolicyFactory`, `InAppCallbackUrlPolicy`, and
|
|
178
|
+
`Logger` so the UI no longer needs deep imports.
|
|
179
|
+
|
|
180
|
+
**`@codemation/core`**
|
|
181
|
+
- New **`@codemation/core/contracts`** subpath — re-exports only pure-type contracts
|
|
182
|
+
(`assertionTypes`, `runTypes`, `workflowTypes`, etc.) using `export type *`. Type-only
|
|
183
|
+
consumers can import from here to avoid dragging the workflow DSL runtime into their
|
|
184
|
+
compile graph. Existing `@codemation/core` (root barrel) is unchanged for backwards
|
|
185
|
+
compatibility.
|
|
186
|
+
- Extracted `core/src/contracts/baseTypes.ts` (six fundamental id types) to break a
|
|
187
|
+
long-standing `credentialTypes ↔ workflowTypes` cycle.
|
|
188
|
+
|
|
189
|
+
**`@codemation/cli` — dev-CLI hardening**
|
|
190
|
+
- **`DevHttpProbe`**: TCP-listener probe replaces the HTTP-response probe, so a slow
|
|
191
|
+
Next dev cold compile no longer SIGTERMs the dev tree.
|
|
192
|
+
- **Single-runtime swap** in `runQueuedRebuild`: stops the old in-process runtime
|
|
193
|
+
before creating the new one, freeing ~1.5 GB during dev source-changes. Consumer
|
|
194
|
+
errors are now non-fatal — the gateway returns 503 and the dev session stays up
|
|
195
|
+
until the next save fixes the build.
|
|
196
|
+
- **Workspace-plugin watch is now opt-in** via `CODEMATION_DEV_WATCH_PLUGINS=true`.
|
|
197
|
+
By default `pnpm dev` no longer spawns `tsdown --watch` for each workspace plugin
|
|
198
|
+
(saves ~500 MB baseline + the rebuild-loop pressure). Plugins still load from
|
|
199
|
+
their existing `dist/` output; opt in only when actively editing a plugin's source.
|
|
200
|
+
- **`DevSourceWatcher`**: 75 ms → 750 ms debounce so a single `tsdown` rebuild collapses
|
|
201
|
+
into one runtime swap. Defense-in-depth ignore re-check at the event handler (chokidar
|
|
202
|
+
doesn't always re-evaluate `ignored` for files created post-start). 20 s startup grace
|
|
203
|
+
period to drop initial-build noise.
|
|
204
|
+
- **Workspace plugin watch root** narrowed from `dist/` to the plugin's entry file —
|
|
205
|
+
tsdown rewrites the entry once per real build, so one watch event per build instead of
|
|
206
|
+
a dozen.
|
|
207
|
+
- Removed `--conditions=development` from the Next-host's `NODE_OPTIONS`. Previously
|
|
208
|
+
this resolved `@codemation/{core,host}` to TypeScript source; combined with
|
|
209
|
+
`transpilePackages` it forced Turbopack to walk the full source tree on every
|
|
210
|
+
UI route compile.
|
|
211
|
+
|
|
212
|
+
**Architectural guard rails (no behavior change, prevent regressions)**
|
|
213
|
+
- ESLint `no-restricted-imports` blocks `@codemation/host-src/*` and root
|
|
214
|
+
`@codemation/host` from `next-host` UI; blocks `prisma-generated/*` outside host's
|
|
215
|
+
persistence layer.
|
|
216
|
+
- New **`dependency-cruiser`** config + `pnpm depcruise` script.
|
|
217
|
+
- New **`knip`** config + `pnpm lint:knip` script.
|
|
218
|
+
- New `tooling/scripts/check-circular-deps.mjs` + `pnpm lint:circular` wired into
|
|
219
|
+
`pnpm lint` with frozen baselines (core: 50, host: 21, core-nodes: 73).
|
|
220
|
+
- **`@next/bundle-analyzer`** wired up; `pnpm analyze` available for on-demand
|
|
221
|
+
inspection (uses `next experimental-analyze` for Turbopack-mode introspection).
|
|
222
|
+
- New `AGENTS.md` "Cross-package imports" section documenting the slim-subpath
|
|
223
|
+
discipline and the rationale for it.
|
|
224
|
+
|
|
225
|
+
The contract additions are strictly additive; no existing API surface changed shape.
|
|
226
|
+
|
|
227
|
+
- [#112](https://github.com/MadeRelevant/codemation/pull/112) [`6fc7d3f`](https://github.com/MadeRelevant/codemation/commit/6fc7d3fe95f8d88386c16971fffa8dd3faa7704f) Thanks [@cblokland90](https://github.com/cblokland90)! - Surface workflow-planning errors in the node inspector instead of swallowing them as `[codemation-http] unhandled route error`. When `NodeInstanceFactory` fails to instantiate a node (e.g. tsyringe `TypeInfo not known` for a constructor param), the offending `nodeId` is preserved via a new `NodeInstantiationError`, and `RunStartService` now persists a failed run with the error attached to that node — same shape execution errors already use, so the UI shows `name`/`message`/`stack` in the node "output" panel.
|
|
228
|
+
|
|
229
|
+
- [#100](https://github.com/MadeRelevant/codemation/pull/100) [`11616ae`](https://github.com/MadeRelevant/codemation/commit/11616aefb91d4b96b7eb9af4b935eec055a8a7bb) Thanks [@cblokland90](https://github.com/cblokland90)! - Workflow Testing UI polish and end-to-end correctness fixes.
|
|
230
|
+
|
|
231
|
+
**`@codemation/next-host`** — Tests UI
|
|
232
|
+
- Fix `Maximum update depth exceeded` on the Tests panel. The trends chart was receiving a
|
|
233
|
+
fresh `[]` reference per render (`?? []` inline) which made recharts' internal effects loop;
|
|
234
|
+
every `?? EMPTY_*` fallback the chart consumes is now a module-scoped stable reference.
|
|
235
|
+
- Fix the same loop class on the canvas-play-dropdown → Tests path. The auto-start `useEffect`
|
|
236
|
+
had `startMutation` (a react-query mutation result, unstable per render) in its deps array,
|
|
237
|
+
which re-fired the mutation on every render. Now uses a ref keyed on `autoStartTriggerNodeId`
|
|
238
|
+
with explicit reset when the prop clears.
|
|
239
|
+
- Fix the canvas inspector showing `{ "json": {...} }` for historical / test-suite child runs.
|
|
240
|
+
`WorkflowDetailPresenter.jsonValueToMainItems` was wrapping every array entry as
|
|
241
|
+
`{ json: <entry> }`, but trigger outputs are persisted **already-Item-shaped**, producing
|
|
242
|
+
`{json: {json: {...}}}`. Detects already-Item entries and passes them through.
|
|
243
|
+
- Surface assertion-rollup-corrected status on the executions list. New `RunSummary.testCaseStatus`
|
|
244
|
+
is preferred over engine `status` so a test-case run whose assertions failed shows as
|
|
245
|
+
**failed** instead of "completed" (engine status is unchanged — only the UI display).
|
|
246
|
+
- Tabs no longer overlap the test-cases detail panel — moved from absolute positioning to a flow
|
|
247
|
+
header in the Tests view.
|
|
248
|
+
- Filter strip above the case tree-table: All / Passing / Failing / Errored / In flight, with
|
|
249
|
+
live counts. Empty buckets are disabled so users can't filter into a confusing empty state.
|
|
250
|
+
- Collapse all / Expand all controls on the case tree-table; expansion state lifted from
|
|
251
|
+
per-row `useState` to the table so broadcasts work. Auto-open-on-failure heuristic still fires
|
|
252
|
+
per-row but only the first time each run id appears, so a row the user explicitly collapsed
|
|
253
|
+
stays collapsed when realtime updates stream in.
|
|
254
|
+
- Trend chart x-axis is now numeric `idx` with subsampled ticks (~5 evenly-spaced labels) and
|
|
255
|
+
time-aware formatting (`HH:MM` when all runs share a day, `M/D HH:MM` across days).
|
|
256
|
+
- Status icon expanded to cover the full case-status union (`succeeded` / `failed` / `errored` /
|
|
257
|
+
`cancelled` / `running` / `queued`) with distinct icons and colors.
|
|
258
|
+
|
|
259
|
+
**`@codemation/host`** — Testing framework correctness
|
|
260
|
+
- Fix `TestSuiteRunTracker` race that left the last test case stuck on `testCaseStatus="running"`
|
|
261
|
+
and the suite counters off by one. The bus dispatched events fire-and-forget; `finalize` ran
|
|
262
|
+
before in-flight handlers wrote their `updateTestCaseStatus` calls. Tracker now serializes
|
|
263
|
+
events through a `processingTail` chain and `finalize` awaits it before reading
|
|
264
|
+
`listChildRuns`.
|
|
265
|
+
- Initialize `Run.testCaseStatus` to `"running"` at row creation when `executionOptions.testContext`
|
|
266
|
+
is present. Previously the tracker's `persistCaseStarted` raced the engine inserting the row
|
|
267
|
+
and silently swallowed P2025 — the suite-detail page never showed a "running" transition.
|
|
268
|
+
- `TestSuiteChildRunDto` exposes the new `testCaseStatus?: TestCaseRunStatus` field; mapper
|
|
269
|
+
narrows the persistence string through a known-statuses guard.
|
|
270
|
+
- `PrismaWorkflowRunRepository.listRuns` threads `testCaseStatus` into `RunSummary` so the
|
|
271
|
+
executions list can render the corrected outcome.
|
|
272
|
+
|
|
273
|
+
**`@codemation/core`**
|
|
274
|
+
- `RunSummary` gains an optional `testCaseStatus?: TestCaseRunStatus`. Additive, non-breaking.
|
|
275
|
+
|
|
276
|
+
**Dev experience**
|
|
277
|
+
- `pnpm dev` (root) now runs `tsdown --watch` for `@codemation/host` alongside `test-dev` under
|
|
278
|
+
`concurrently`, so host source edits rebuild `dist/` automatically. Without this, host changes
|
|
279
|
+
were invisible to the running Next dev server (which deliberately resolves host from `dist/`
|
|
280
|
+
to keep Turbopack memory bounded on 8 GB WSL boxes), forcing a manual
|
|
281
|
+
`pnpm --filter @codemation/host build` after every host edit.
|
|
282
|
+
|
|
283
|
+
**Documentation**
|
|
284
|
+
- Top-level `docs/workflow-testing.md` and the `codemation-workflow-dsl` skill reference
|
|
285
|
+
rewritten for the score-based assertion model (`score: 0..1` + `passThreshold?` + `errored?`),
|
|
286
|
+
with examples for boolean assertions, continuous metrics, and judge-by-agent assertions.
|
|
287
|
+
|
|
288
|
+
**Tests**
|
|
289
|
+
- New HTTP-driven e2e suite (`packages/host/test/e2e/testSuiteRunHttpFlow.e2e.test.ts`) drives
|
|
290
|
+
the full real-orchestrator + real-Prisma + real-engine lifecycle through `POST` →
|
|
291
|
+
`GET /api/test-suite-runs/:id` → child runs → assertions, asserting the partial-suite
|
|
292
|
+
outcome with assertion-rollup downgrade.
|
|
293
|
+
- New unit tests cover the case-status filter engine, the historical-run double-wrap regression,
|
|
294
|
+
and the chart prop-stability regression class.
|
|
295
|
+
|
|
296
|
+
## 1.0.1
|
|
297
|
+
|
|
298
|
+
### Patch Changes
|
|
299
|
+
|
|
300
|
+
- [`ed75183`](https://github.com/MadeRelevant/codemation/commit/ed75183f51ae71b06aa2e57ae4fc48ce9db2e4ce) - Establish "per Item per Call" identity end-to-end so the workflow run inspector reports, visualizes, and dashboards multi-item AI agents correctly.
|
|
301
|
+
|
|
302
|
+
Previously, an orchestrator agent that processed N items emitted one flat list of LLM rounds and tool calls — the bottom execution tree, the right-panel agent timeline, cost dashboards, and the realtime event stream all collapsed iterations into one bucket, making sub-agent fan-outs (and parallel item processing in general) unreadable.
|
|
303
|
+
|
|
304
|
+
**What changed**
|
|
305
|
+
- **Engine** (`@codemation/core`): `NodeExecutor` mints a `NodeIterationId` per item inside per-item runnable activations and stamps it (with `itemIndex`) onto `NodeExecutionContext`. Connection invocations, telemetry spans (`gen_ai.chat.completion`, `agent.tool.call`), metric points (`codemation.cost.estimated`, `codemation.agent.turns`, `codemation.agent.tool_calls`), and run events all carry the per-item identity. New `ChildExecutionScopeFactory` re-roots `NodeExecutionContext` for sub-agents so credentials and iteration ids resolve correctly across the orchestrator → tool → sub-agent boundary.
|
|
306
|
+
- **Sub-agent credentials** (`@codemation/core-nodes`): `NodeBackedToolRuntime.resolveNodeCtx` no longer re-wraps `args.ctx.nodeId` with `ConnectionNodeIdFactory.toolConnectionNodeId` — the caller already pre-wraps it. The previous double-nesting produced exponentially deep node ids (`AIAgentNode:2__conn__tool__conn__searchInMail__conn__tool__conn__searchInMail__conn__llm`) that didn't match user-bound credential slots. Sub-agent OpenAI / API-key slots resolve again.
|
|
307
|
+
- **Realtime events**: new `connectionInvocationStarted` / `connectionInvocationCompleted` / `connectionInvocationFailed` events carry the full `ConnectionInvocationRecord` (incl. `iterationId`, `itemIndex`, `parentInvocationId`) and surgical reducers update the run cache without waiting for a coarse `runSaved` snapshot. Run-query polling dropped from 250 ms → 5 s now that WebSocket events drive most updates.
|
|
308
|
+
- **Persistence** (`@codemation/host`): Prisma `ExecutionInstance` model gains `iteration_id`, `item_index`, `parent_invocation_id` columns + index (sqlite + postgres migrations); `PrismaWorkflowRunRepository` round-trips them on read/save and via `ExecutionInstanceDto`. Without this the cold reload of a finished run silently flattens the per-item tree because `runSaved` events stream through Prisma. Telemetry tables already carried these columns from Phase 4; both sides now agree.
|
|
309
|
+
- **Iteration projection / cost queries** (`@codemation/host`): new `RunIterationProjectionFactory` projects `RunIterationRecord`s from connection invocations + iteration cost metrics and `GetIterationCostQueryHandler` serves per-iteration cost rollups for dashboards.
|
|
310
|
+
- **Inspector view model** (`@codemation/next-host`): `NodeInspectorTelemetryPresenter` groups LLM and tool spans by `iterationId` into "Item N" accordion entries (single-item agents fall back to flat layout). New `FocusedInvocationModelFactory` powers item-level prev/next navigation when a specific invocation is selected — the breadcrumb shows "Item X of Y" and nav targets the first invocation of adjacent items. Tool spans now interleave chronologically with LLM rounds (request → tools → response) instead of LLM rounds first then orphan tools at the bottom.
|
|
311
|
+
- **Bottom execution tree** (`@codemation/next-host`): new `ExecutionTreeItemGroupInjector` injects synthetic "Item N" parent rows between an agent and its connection invocations when the agent processed 2+ items. Single-item activations are left untouched; sub-agent invocations whose `parentInvocationId` already points at a tool-call row stay nested under the orchestrator's specific tool call.
|
|
312
|
+
- **Sub-agent credential boundary**: `ChildExecutionScopeFactory.forSubAgent` ensures sub-agent `NodeExecutionContext` keeps the parent invocation id and span context intact so trace nesting and credential resolution agree on the connection-node id.
|
|
313
|
+
- **Tests**: new unit + UI suites for each layer (sub-agent scope, item-group injector, focused invocation model, agent timeline per-item grouping, chronological ordering, Prisma iterationId round trip, item-aware properties panel, connection-invocation event publisher) and a runnable `apps/test-dev` sample (`agentSubAgentToolFanout`) that exercises the orchestrator → sub-agent fan-out across 2 items end-to-end.
|
|
314
|
+
|
|
3
315
|
## 1.0.0
|
|
4
316
|
|
|
5
317
|
### Major Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Mr as WebhookTriggerMatcher, Pr as WebhookTriggerRoutingDiagnostics, Ta as DependencyContainer, Wa as EngineExecutionLimitsPolicyConfig, _r as TriggerRuntimeDiagnostics, vn as WorkflowPolicyRuntimeDefaults } from "./RunIntentService-BE9CAkbf.js";
|
|
2
2
|
|
|
3
3
|
//#region src/bootstrap/runtime/EngineRuntimeRegistration.types.d.ts
|
|
4
4
|
|
|
@@ -41,4 +41,4 @@ interface EngineRuntimeRegistrationOptions {
|
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
43
|
export { TriggerRuntimeDiagnosticsProvider as n, WebhookTriggerMatcherProvider as r, EngineRuntimeRegistrationOptions as t };
|
|
44
|
-
//# sourceMappingURL=EngineRuntimeRegistration.types-
|
|
44
|
+
//# sourceMappingURL=EngineRuntimeRegistration.types-D1fyApMI.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Br as PersistedWorkflowTokenRegistryLike, Fi as NodeId, G as WorkflowDefinition, Jr as RunResult, M as ParentExecutionRef, Q as WorkflowPolicyRuntimeDefaults, Ri as WorkflowId, Rr as PersistedWorkflowSnapshot, Zt as TriggerRuntimeDiagnostics, ai as DependencyContainer, d as Items, fn as WebhookTriggerMatcher, mn as WebhookTriggerRoutingDiagnostics, r as Engine, rn as WorkflowRepository, wi as EngineExecutionLimitsPolicyConfig, y as NodeConfigBase, zr as PersistedWorkflowSnapshotNode } from "./RunIntentService-siBSjaaY.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/workflowSnapshots/WorkflowSnapshotCodec.d.ts
|
|
4
4
|
declare class WorkflowSnapshotCodec {
|
|
@@ -18,6 +18,20 @@ declare class WorkflowSnapshotCodec {
|
|
|
18
18
|
private asRecord;
|
|
19
19
|
}
|
|
20
20
|
//#endregion
|
|
21
|
+
//#region src/runtime/EngineWorkflowRunnerService.d.ts
|
|
22
|
+
declare class EngineWorkflowRunnerService {
|
|
23
|
+
private readonly engine;
|
|
24
|
+
private readonly workflowRepository;
|
|
25
|
+
constructor(engine: Engine, workflowRepository: WorkflowRepository);
|
|
26
|
+
runById(args: {
|
|
27
|
+
workflowId: WorkflowId;
|
|
28
|
+
startAt?: NodeId;
|
|
29
|
+
items: Items;
|
|
30
|
+
parent?: ParentExecutionRef;
|
|
31
|
+
}): Promise<RunResult>;
|
|
32
|
+
private findDefaultStartNodeId;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
21
35
|
//#region src/bootstrap/runtime/EngineRuntimeRegistration.types.d.ts
|
|
22
36
|
/**
|
|
23
37
|
* Creates the webhook route matcher used by {@link import("../api/Engine").Engine}.
|
|
@@ -57,19 +71,5 @@ interface EngineRuntimeRegistrationOptions {
|
|
|
57
71
|
workflowPolicyRuntimeDefaults?: WorkflowPolicyRuntimeDefaults;
|
|
58
72
|
}
|
|
59
73
|
//#endregion
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
private readonly engine;
|
|
63
|
-
private readonly workflowRepository;
|
|
64
|
-
constructor(engine: Engine, workflowRepository: WorkflowRepository);
|
|
65
|
-
runById(args: {
|
|
66
|
-
workflowId: WorkflowId;
|
|
67
|
-
startAt?: NodeId;
|
|
68
|
-
items: Items;
|
|
69
|
-
parent?: ParentExecutionRef;
|
|
70
|
-
}): Promise<RunResult>;
|
|
71
|
-
private findDefaultStartNodeId;
|
|
72
|
-
}
|
|
73
|
-
//#endregion
|
|
74
|
-
export { WorkflowSnapshotCodec as a, WebhookTriggerMatcherProvider as i, EngineRuntimeRegistrationOptions as n, TriggerRuntimeDiagnosticsProvider as r, EngineWorkflowRunnerService as t };
|
|
75
|
-
//# sourceMappingURL=EngineWorkflowRunnerService-DzOCa1BW.d.cts.map
|
|
74
|
+
export { WorkflowSnapshotCodec as a, EngineWorkflowRunnerService as i, TriggerRuntimeDiagnosticsProvider as n, WebhookTriggerMatcherProvider as r, EngineRuntimeRegistrationOptions as t };
|
|
75
|
+
//# sourceMappingURL=EngineRuntimeRegistration.types-pB3FnzqR.d.cts.map
|
package/dist/{InMemoryRunDataFactory-1iz7_SnO.d.cts → InMemoryRunDataFactory-Xw7v4-sj.d.cts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $r as RunTestContext, Bt as NodeExecutionStatePublisher, Et as ExecutionContextFactory, F as RunDataSnapshot, Fi as NodeId, Ft as NodeBinaryAttachmentService, Hn as CostTrackingTelemetryFactory, I as RunId, It as NodeExecutionContext, Kn as CollectionsContext, M as ParentExecutionRef, N as PersistedRunPolicySnapshot, O as NodeOutputs, P as RunDataFactory, R as RunnableNodeConfig, Ri as WorkflowId, Tt as ExecutionContext, Wn as CostTrackingUsageRecord, _ as MutableRunData, _t as BinaryStorageReadResult, a as BinaryAttachment, bt as BinaryStorageWriteResult, dr as CredentialSessionService, gt as BinaryStorage, ht as BinaryBody, l as Item, pt as RetryPolicySpec, v as NodeActivationId, vn as ExecutionTelemetryFactory, vt as BinaryStorageStatResult, wt as ExecutionBinaryService } from "./RunIntentService-siBSjaaY.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/contracts/CostCatalogContract.d.ts
|
|
4
4
|
interface CostCatalogEntry {
|
|
@@ -22,6 +22,31 @@ declare class CredentialResolverFactory {
|
|
|
22
22
|
create(workflowId: WorkflowId, nodeId: NodeId, config?: NodeExecutionContext["config"]): NodeExecutionContext["getCredential"];
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
|
+
//#region src/binaries/UnavailableBinaryStorage.d.ts
|
|
26
|
+
declare class UnavailableBinaryStorage implements BinaryStorage {
|
|
27
|
+
readonly driverName = "unavailable";
|
|
28
|
+
write(): Promise<never>;
|
|
29
|
+
openReadStream(): Promise<undefined>;
|
|
30
|
+
stat(): Promise<{
|
|
31
|
+
exists: false;
|
|
32
|
+
}>;
|
|
33
|
+
delete(): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/binaries/DefaultExecutionBinaryServiceFactory.d.ts
|
|
37
|
+
declare class DefaultExecutionBinaryService implements ExecutionBinaryService {
|
|
38
|
+
private readonly storage;
|
|
39
|
+
private readonly workflowId;
|
|
40
|
+
private readonly runId;
|
|
41
|
+
private readonly now;
|
|
42
|
+
constructor(storage: BinaryStorage, workflowId: WorkflowId, runId: RunId, now: () => Date);
|
|
43
|
+
forNode(args: {
|
|
44
|
+
nodeId: NodeId;
|
|
45
|
+
activationId: NodeActivationId;
|
|
46
|
+
}): NodeBinaryAttachmentService;
|
|
47
|
+
openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
25
50
|
//#region src/execution/asyncSleeper.types.d.ts
|
|
26
51
|
interface AsyncSleeper {
|
|
27
52
|
sleep(ms: number): Promise<void>;
|
|
@@ -38,8 +63,9 @@ declare class DefaultExecutionContextFactory implements ExecutionContextFactory
|
|
|
38
63
|
private readonly telemetryFactory;
|
|
39
64
|
private readonly costTrackingFactory;
|
|
40
65
|
private readonly currentDate;
|
|
66
|
+
private readonly collections?;
|
|
41
67
|
private readonly telemetryDecoratorFactory;
|
|
42
|
-
constructor(binaryStorage?: BinaryStorage, telemetryFactory?: ExecutionTelemetryFactory, costTrackingFactory?: CostTrackingTelemetryFactory, currentDate?: () => Date);
|
|
68
|
+
constructor(binaryStorage?: BinaryStorage, telemetryFactory?: ExecutionTelemetryFactory, costTrackingFactory?: CostTrackingTelemetryFactory, currentDate?: () => Date, collections?: CollectionsContext | undefined);
|
|
43
69
|
create(args: {
|
|
44
70
|
runId: RunId;
|
|
45
71
|
workflowId: WorkflowId;
|
|
@@ -52,6 +78,7 @@ declare class DefaultExecutionContextFactory implements ExecutionContextFactory
|
|
|
52
78
|
nodeState?: NodeExecutionStatePublisher;
|
|
53
79
|
telemetry?: ExecutionContext["telemetry"];
|
|
54
80
|
getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
|
|
81
|
+
testContext?: RunTestContext;
|
|
55
82
|
}): ExecutionContext;
|
|
56
83
|
}
|
|
57
84
|
//#endregion
|
|
@@ -84,31 +111,6 @@ declare class RunnableOutputBehaviorResolver {
|
|
|
84
111
|
private isKeepBinariesEnabled;
|
|
85
112
|
}
|
|
86
113
|
//#endregion
|
|
87
|
-
//#region src/binaries/UnavailableBinaryStorage.d.ts
|
|
88
|
-
declare class UnavailableBinaryStorage implements BinaryStorage {
|
|
89
|
-
readonly driverName = "unavailable";
|
|
90
|
-
write(): Promise<never>;
|
|
91
|
-
openReadStream(): Promise<undefined>;
|
|
92
|
-
stat(): Promise<{
|
|
93
|
-
exists: false;
|
|
94
|
-
}>;
|
|
95
|
-
delete(): Promise<void>;
|
|
96
|
-
}
|
|
97
|
-
//#endregion
|
|
98
|
-
//#region src/binaries/DefaultExecutionBinaryServiceFactory.d.ts
|
|
99
|
-
declare class DefaultExecutionBinaryService implements ExecutionBinaryService {
|
|
100
|
-
private readonly storage;
|
|
101
|
-
private readonly workflowId;
|
|
102
|
-
private readonly runId;
|
|
103
|
-
private readonly now;
|
|
104
|
-
constructor(storage: BinaryStorage, workflowId: WorkflowId, runId: RunId, now: () => Date);
|
|
105
|
-
forNode(args: {
|
|
106
|
-
nodeId: NodeId;
|
|
107
|
-
activationId: NodeActivationId;
|
|
108
|
-
}): NodeBinaryAttachmentService;
|
|
109
|
-
openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
|
|
110
|
-
}
|
|
111
|
-
//#endregion
|
|
112
114
|
//#region src/runStorage/InMemoryBinaryStorageRegistry.d.ts
|
|
113
115
|
declare class InMemoryBinaryStorage implements BinaryStorage {
|
|
114
116
|
readonly driverName = "memory";
|
|
@@ -127,5 +129,5 @@ declare class InMemoryRunDataFactory implements RunDataFactory {
|
|
|
127
129
|
create(initial?: Record<NodeId, NodeOutputs>): MutableRunData;
|
|
128
130
|
}
|
|
129
131
|
//#endregion
|
|
130
|
-
export {
|
|
131
|
-
//# sourceMappingURL=InMemoryRunDataFactory-
|
|
132
|
+
export { ItemExprResolver as a, DefaultAsyncSleeper as c, UnavailableBinaryStorage as d, CredentialResolverFactory as f, RunnableOutputBehaviorResolver as i, AsyncSleeper as l, CostCatalogEntry as m, InMemoryBinaryStorage as n, InProcessRetryRunner as o, CostCatalog as p, RunnableOutputBehavior as r, DefaultExecutionContextFactory as s, InMemoryRunDataFactory as t, DefaultExecutionBinaryService as u };
|
|
133
|
+
//# sourceMappingURL=InMemoryRunDataFactory-Xw7v4-sj.d.cts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/events/InMemoryRunEventSubscription.ts
|
|
3
|
+
var InMemoryRunEventSubscription = class {
|
|
4
|
+
constructor(onClose) {
|
|
5
|
+
this.onClose = onClose;
|
|
6
|
+
}
|
|
7
|
+
async close() {
|
|
8
|
+
this.onClose();
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/events/InMemoryRunEventBusRegistry.ts
|
|
14
|
+
var InMemoryRunEventBus = class {
|
|
15
|
+
globalListeners = /* @__PURE__ */ new Set();
|
|
16
|
+
listenersByWorkflowId = /* @__PURE__ */ new Map();
|
|
17
|
+
async publish(event) {
|
|
18
|
+
for (const listener of this.globalListeners) listener(event);
|
|
19
|
+
for (const listener of this.listenersByWorkflowId.get(event.workflowId) ?? []) listener(event);
|
|
20
|
+
}
|
|
21
|
+
async subscribe(onEvent) {
|
|
22
|
+
this.globalListeners.add(onEvent);
|
|
23
|
+
return new InMemoryRunEventSubscription(() => {
|
|
24
|
+
this.globalListeners.delete(onEvent);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async subscribeToWorkflow(workflowId, onEvent) {
|
|
28
|
+
const existing = this.listenersByWorkflowId.get(workflowId) ?? /* @__PURE__ */ new Set();
|
|
29
|
+
existing.add(onEvent);
|
|
30
|
+
this.listenersByWorkflowId.set(workflowId, existing);
|
|
31
|
+
return new InMemoryRunEventSubscription(() => {
|
|
32
|
+
const listeners = this.listenersByWorkflowId.get(workflowId);
|
|
33
|
+
if (!listeners) return;
|
|
34
|
+
listeners.delete(onEvent);
|
|
35
|
+
if (listeners.size === 0) this.listenersByWorkflowId.delete(workflowId);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
Object.defineProperty(exports, 'InMemoryRunEventBus', {
|
|
42
|
+
enumerable: true,
|
|
43
|
+
get: function () {
|
|
44
|
+
return InMemoryRunEventBus;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=InMemoryRunEventBusRegistry-VM3OWnHo.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InMemoryRunEventBusRegistry-VM3OWnHo.cjs","names":["onClose: () => void"],"sources":["../src/events/InMemoryRunEventSubscription.ts","../src/events/InMemoryRunEventBusRegistry.ts"],"sourcesContent":["import type { RunEventSubscription } from \"./runEvents\";\n\nexport class InMemoryRunEventSubscription implements RunEventSubscription {\n constructor(private readonly onClose: () => void) {}\n\n async close(): Promise<void> {\n this.onClose();\n }\n}\n","import type { WorkflowId } from \"../types\";\n\nimport type { RunEvent, RunEventBus, RunEventSubscription } from \"./runEvents\";\n\nimport { InMemoryRunEventSubscription } from \"./InMemoryRunEventSubscription\";\n\nexport class InMemoryRunEventBus implements RunEventBus {\n private readonly globalListeners = new Set<(event: RunEvent) => void>();\n private readonly listenersByWorkflowId = new Map<WorkflowId, Set<(event: RunEvent) => void>>();\n\n async publish(event: RunEvent): Promise<void> {\n for (const listener of this.globalListeners) listener(event);\n for (const listener of this.listenersByWorkflowId.get(event.workflowId) ?? []) listener(event);\n }\n\n async subscribe(onEvent: (event: RunEvent) => void): Promise<RunEventSubscription> {\n this.globalListeners.add(onEvent);\n return new InMemoryRunEventSubscription(() => {\n this.globalListeners.delete(onEvent);\n });\n }\n\n async subscribeToWorkflow(workflowId: WorkflowId, onEvent: (event: RunEvent) => void): Promise<RunEventSubscription> {\n const existing = this.listenersByWorkflowId.get(workflowId) ?? new Set<(event: RunEvent) => void>();\n existing.add(onEvent);\n this.listenersByWorkflowId.set(workflowId, existing);\n\n return new InMemoryRunEventSubscription(() => {\n const listeners = this.listenersByWorkflowId.get(workflowId);\n if (!listeners) return;\n listeners.delete(onEvent);\n if (listeners.size === 0) this.listenersByWorkflowId.delete(workflowId);\n });\n }\n}\n\nexport { InMemoryRunEventSubscription } from \"./InMemoryRunEventSubscription\";\n"],"mappings":";;AAEA,IAAa,+BAAb,MAA0E;CACxE,YAAY,AAAiBA,SAAqB;EAArB;;CAE7B,MAAM,QAAuB;AAC3B,OAAK,SAAS;;;;;;ACAlB,IAAa,sBAAb,MAAwD;CACtD,AAAiB,kCAAkB,IAAI,KAAgC;CACvE,AAAiB,wCAAwB,IAAI,KAAiD;CAE9F,MAAM,QAAQ,OAAgC;AAC5C,OAAK,MAAM,YAAY,KAAK,gBAAiB,UAAS,MAAM;AAC5D,OAAK,MAAM,YAAY,KAAK,sBAAsB,IAAI,MAAM,WAAW,IAAI,EAAE,CAAE,UAAS,MAAM;;CAGhG,MAAM,UAAU,SAAmE;AACjF,OAAK,gBAAgB,IAAI,QAAQ;AACjC,SAAO,IAAI,mCAAmC;AAC5C,QAAK,gBAAgB,OAAO,QAAQ;IACpC;;CAGJ,MAAM,oBAAoB,YAAwB,SAAmE;EACnH,MAAM,WAAW,KAAK,sBAAsB,IAAI,WAAW,oBAAI,IAAI,KAAgC;AACnG,WAAS,IAAI,QAAQ;AACrB,OAAK,sBAAsB,IAAI,YAAY,SAAS;AAEpD,SAAO,IAAI,mCAAmC;GAC5C,MAAM,YAAY,KAAK,sBAAsB,IAAI,WAAW;AAC5D,OAAI,CAAC,UAAW;AAChB,aAAU,OAAO,QAAQ;AACzB,OAAI,UAAU,SAAS,EAAG,MAAK,sBAAsB,OAAO,WAAW;IACvE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/events/InMemoryRunEventSubscription.ts
|
|
2
|
+
var InMemoryRunEventSubscription = class {
|
|
3
|
+
constructor(onClose) {
|
|
4
|
+
this.onClose = onClose;
|
|
5
|
+
}
|
|
6
|
+
async close() {
|
|
7
|
+
this.onClose();
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/events/InMemoryRunEventBusRegistry.ts
|
|
13
|
+
var InMemoryRunEventBus = class {
|
|
14
|
+
globalListeners = /* @__PURE__ */ new Set();
|
|
15
|
+
listenersByWorkflowId = /* @__PURE__ */ new Map();
|
|
16
|
+
async publish(event) {
|
|
17
|
+
for (const listener of this.globalListeners) listener(event);
|
|
18
|
+
for (const listener of this.listenersByWorkflowId.get(event.workflowId) ?? []) listener(event);
|
|
19
|
+
}
|
|
20
|
+
async subscribe(onEvent) {
|
|
21
|
+
this.globalListeners.add(onEvent);
|
|
22
|
+
return new InMemoryRunEventSubscription(() => {
|
|
23
|
+
this.globalListeners.delete(onEvent);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async subscribeToWorkflow(workflowId, onEvent) {
|
|
27
|
+
const existing = this.listenersByWorkflowId.get(workflowId) ?? /* @__PURE__ */ new Set();
|
|
28
|
+
existing.add(onEvent);
|
|
29
|
+
this.listenersByWorkflowId.set(workflowId, existing);
|
|
30
|
+
return new InMemoryRunEventSubscription(() => {
|
|
31
|
+
const listeners = this.listenersByWorkflowId.get(workflowId);
|
|
32
|
+
if (!listeners) return;
|
|
33
|
+
listeners.delete(onEvent);
|
|
34
|
+
if (listeners.size === 0) this.listenersByWorkflowId.delete(workflowId);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
export { InMemoryRunEventBus as t };
|
|
41
|
+
//# sourceMappingURL=InMemoryRunEventBusRegistry-sM4z4n_i.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InMemoryRunEventBusRegistry-sM4z4n_i.js","names":["onClose: () => void"],"sources":["../src/events/InMemoryRunEventSubscription.ts","../src/events/InMemoryRunEventBusRegistry.ts"],"sourcesContent":["import type { RunEventSubscription } from \"./runEvents\";\n\nexport class InMemoryRunEventSubscription implements RunEventSubscription {\n constructor(private readonly onClose: () => void) {}\n\n async close(): Promise<void> {\n this.onClose();\n }\n}\n","import type { WorkflowId } from \"../types\";\n\nimport type { RunEvent, RunEventBus, RunEventSubscription } from \"./runEvents\";\n\nimport { InMemoryRunEventSubscription } from \"./InMemoryRunEventSubscription\";\n\nexport class InMemoryRunEventBus implements RunEventBus {\n private readonly globalListeners = new Set<(event: RunEvent) => void>();\n private readonly listenersByWorkflowId = new Map<WorkflowId, Set<(event: RunEvent) => void>>();\n\n async publish(event: RunEvent): Promise<void> {\n for (const listener of this.globalListeners) listener(event);\n for (const listener of this.listenersByWorkflowId.get(event.workflowId) ?? []) listener(event);\n }\n\n async subscribe(onEvent: (event: RunEvent) => void): Promise<RunEventSubscription> {\n this.globalListeners.add(onEvent);\n return new InMemoryRunEventSubscription(() => {\n this.globalListeners.delete(onEvent);\n });\n }\n\n async subscribeToWorkflow(workflowId: WorkflowId, onEvent: (event: RunEvent) => void): Promise<RunEventSubscription> {\n const existing = this.listenersByWorkflowId.get(workflowId) ?? new Set<(event: RunEvent) => void>();\n existing.add(onEvent);\n this.listenersByWorkflowId.set(workflowId, existing);\n\n return new InMemoryRunEventSubscription(() => {\n const listeners = this.listenersByWorkflowId.get(workflowId);\n if (!listeners) return;\n listeners.delete(onEvent);\n if (listeners.size === 0) this.listenersByWorkflowId.delete(workflowId);\n });\n }\n}\n\nexport { InMemoryRunEventSubscription } from \"./InMemoryRunEventSubscription\";\n"],"mappings":";AAEA,IAAa,+BAAb,MAA0E;CACxE,YAAY,AAAiBA,SAAqB;EAArB;;CAE7B,MAAM,QAAuB;AAC3B,OAAK,SAAS;;;;;;ACAlB,IAAa,sBAAb,MAAwD;CACtD,AAAiB,kCAAkB,IAAI,KAAgC;CACvE,AAAiB,wCAAwB,IAAI,KAAiD;CAE9F,MAAM,QAAQ,OAAgC;AAC5C,OAAK,MAAM,YAAY,KAAK,gBAAiB,UAAS,MAAM;AAC5D,OAAK,MAAM,YAAY,KAAK,sBAAsB,IAAI,MAAM,WAAW,IAAI,EAAE,CAAE,UAAS,MAAM;;CAGhG,MAAM,UAAU,SAAmE;AACjF,OAAK,gBAAgB,IAAI,QAAQ;AACjC,SAAO,IAAI,mCAAmC;AAC5C,QAAK,gBAAgB,OAAO,QAAQ;IACpC;;CAGJ,MAAM,oBAAoB,YAAwB,SAAmE;EACnH,MAAM,WAAW,KAAK,sBAAsB,IAAI,WAAW,oBAAI,IAAI,KAAgC;AACnG,WAAS,IAAI,QAAQ;AACrB,OAAK,sBAAsB,IAAI,YAAY,SAAS;AAEpD,SAAO,IAAI,mCAAmC;GAC5C,MAAM,YAAY,KAAK,sBAAsB,IAAI,WAAW;AAC5D,OAAI,CAAC,UAAW;AAChB,aAAU,OAAO,QAAQ;AACzB,OAAI,UAAU,SAAS,EAAG,MAAK,sBAAsB,OAAO,WAAW;IACvE"}
|