A version written into a manifest is written into every manifest that wants it,
which is how eslint came to exist in a hundred and four forms across this estate
and how a package came to resolve twice at run time. The catalog moves the number
out of the manifest: a manifest names the package, the workspace names the
version.
Four are held below their latest because the newer release cannot be used, and
the reason is recorded rather than the version alone: @noble/hashes 2 renamed
every subpath the web3 stack imports, @splinetool/runtime 2 depends on a package
that was never published, @dynamic-labs 5.4.1 the same, and react-resizable-panels
3 points its types condition at the bundle.
The cloud embedded engine links luxfi/zap v1.2.0 via MVS, whose NewBuilder stamps
wire version 2; the TS SDK only accepted version 1 -> 'unsupported version 2'
against cloud's gated :9999. The generic object encoding is byte-identical across
v1/v2 (only the platformvm TxKind schema differs, which this SDK never uses) and
v1.2.0's Parse accepts v1, so: keep emitting v1 (both engines accept it), accept
BOTH 1 and 2 on read. Verified live against cloud v1.786.102.
Also (drop-in compat, from the social migration):
- export TokenProvider from the package root.
- proxyActivities<A>: open the generic so proxyActivities<SomeActivityClass>()
type-checks; ProxyActivityOptions accepts cancellationType (no-op).
- engine.moreCurrentRun: a CONTINUED_AS_NEW run ranks below any other run of the
same workflowId, so the completed tail of a continue-as-new chain resolves over
its closed predecessor on a same-second StartTime (DescribeWorkflow by id).
The gated engine (cloud ServeGated :9999) requires an auth_token on every
JSON-body RPC; the TS SDK had no way to send one. Add a TokenProvider that
rides client lifecycle + worker Subscribe as auth_token (mirrors the Go SDK's
Options.Token), injected at the ZAP transport for JSON bodies only — worker
Respond/Heartbeat field-object frames are HMAC-authenticated and untouched.
Threaded through Connection/TasksClient/Worker options. Proven: unit test
(auth_token rides JSON RPCs, absent without a source) + gated e2e vs a real
RequireIdentity tasksd with a local RS256 JWKS (anonymous -> 401; IAM-bearer
client+worker run a durable workflow to COMPLETED with org-scoped namespace).
The social-orchestrator migration off upstream Temporal onto the embedded
Hanzo Tasks engine needs five workflow primitives its digest/sendEmail/post
workflows depend on. Implemented server-side (event-sourced, replay-safe) plus
the @hanzoai/tasks TS SDK (the worker social runs):
- Signal → running workflow: engine.signalWorkflow now re-dispatches a workflow
task after appending WORKFLOW_EXECUTION_SIGNALED, so the stateless worker
replays the extended history and fires the handler (digest/sendEmail are
entirely signal-driven). TS decider read the wrong history attr key
("signal" vs "signalName") — fixed.
- continueAsNew (kind=4): closes the run CONTINUED_AS_NEW + starts a successor
under the same workflowId carrying input/search-attrs/memo. TS continueAsNew
emits the command instead of throwing ContinueAsNewNotSupported.
- startChild (kind=5): detached (ABANDON) child, seq-keyed + idempotent; retires
the 0x006D 501 for the command path. TS startChild/executeChild added.
- Typed search attributes: carried on StartWorkflow/SignalWithStart wire, stored
on the execution, visibility-queryable (already read by fieldValue). TS adds
TypedSearchAttributes/defineSearchAttributeKey/SearchAttributeType.
- workflowIdConflictPolicy USE_EXISTING/TERMINATE_EXISTING/FAIL.
- ActivityFailure wraps ApplicationFailure (with .type) so workflow error
matching (err.cause.type === 'refresh_token') works.
Also fixes a pre-existing wire defect: the server registered
SignalWithStartWorkflow at 0x0069 while every client sends 0x0066 (schema +
Go/TS SDK) — signalWithStart 404'd against the real engine. Swapped with the
HTTP-only GetWorkflowHistory (no ZAP client).
DescribeWorkflow(workflowId, "") now resolves the OPEN run (Temporal's current
execution) so a continueAsNew successor is the one signalled/described.
Tests: engine unit (search attrs, conflict policy, continueAsNew, startChild)
+ TS e2e vs real tasksd (signals-across-continueAsNew, startChild, search attrs
run to COMPLETED). go test -race ./pkg/... green; TS vitest green.
Native TS client + worker over the Hanzo Tasks ZAP wire, byte-compatible with pkg/sdk (Go) and luxfi/zap v0.2.0. Drop-in for @temporalio/* + nestjs-temporal-core so the social-orchestrator migration is a dependency swap.
Includes: byte-exact ZAP message codec + TCP node (handshake, reqID correlation, Send-push dispatch); full client (start/signal/signalWithStart/query/describe/cancel/terminate/list, namespaces, health); activity worker (subscribe/dispatch/heartbeat/respond); event-sourced workflow replay decider (proxyActivities, durable activity-backed timers, condition, defineSignal/setHandler); temporal failure envelope serde; @temporalio compat (Connection/Client/NativeConnection/Worker/ApplicationFailure).
Tests: 25 vitest specs green (byte-layout golden, decider unit, full durable loop through a faithful ZAP mock) + a live integration suite that passes against a running tasksd. tsc --noEmit clean.
Co-authored-by: Hanzo Dev <[email protected]>