@laserdata/laser-sdk 0.5.2 → 0.6.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/README.md +105 -79
- package/dist/agent/agdx.d.ts +8 -3
- package/dist/agent/agdx.d.ts.map +1 -1
- package/dist/agent/agdx.js +39 -22
- package/dist/agent/agdx.js.map +1 -1
- package/dist/agent/builder.d.ts +25 -15
- package/dist/agent/builder.d.ts.map +1 -1
- package/dist/agent/builder.js +103 -59
- package/dist/agent/builder.js.map +1 -1
- package/dist/agent/context.d.ts +3 -6
- package/dist/agent/context.d.ts.map +1 -1
- package/dist/agent/context.js +17 -9
- package/dist/agent/context.js.map +1 -1
- package/dist/agent/contract.d.ts +2 -2
- package/dist/agent/contract.d.ts.map +1 -1
- package/dist/agent/contract.js +10 -6
- package/dist/agent/contract.js.map +1 -1
- package/dist/agent/memory-handler.d.ts +25 -0
- package/dist/agent/memory-handler.d.ts.map +1 -0
- package/dist/agent/memory-handler.js +43 -0
- package/dist/agent/memory-handler.js.map +1 -0
- package/dist/agent/registry.d.ts +3 -10
- package/dist/agent/registry.d.ts.map +1 -1
- package/dist/agent/registry.js +22 -19
- package/dist/agent/registry.js.map +1 -1
- package/dist/agent/reliable-consumer.d.ts +19 -9
- package/dist/agent/reliable-consumer.d.ts.map +1 -1
- package/dist/agent/reliable-consumer.js +193 -54
- package/dist/agent/reliable-consumer.js.map +1 -1
- package/dist/agent/replies.d.ts +6 -0
- package/dist/agent/replies.d.ts.map +1 -1
- package/dist/agent/replies.js +55 -4
- package/dist/agent/replies.js.map +1 -1
- package/dist/agent/router.d.ts +1 -1
- package/dist/agent/router.d.ts.map +1 -1
- package/dist/agent/router.js +5 -19
- package/dist/agent/router.js.map +1 -1
- package/dist/agent/scope.d.ts +7 -3
- package/dist/agent/scope.d.ts.map +1 -1
- package/dist/agent/scope.js +11 -1
- package/dist/agent/scope.js.map +1 -1
- package/dist/agent/timer.d.ts +6 -0
- package/dist/agent/timer.d.ts.map +1 -0
- package/dist/agent/timer.js +21 -0
- package/dist/agent/timer.js.map +1 -0
- package/dist/agent/workflow.d.ts +16 -19
- package/dist/agent/workflow.d.ts.map +1 -1
- package/dist/agent/workflow.js +17 -6
- package/dist/agent/workflow.js.map +1 -1
- package/dist/blob.d.ts +2 -3
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js.map +1 -1
- package/dist/bridges/a2a.d.ts +34 -23
- package/dist/bridges/a2a.d.ts.map +1 -1
- package/dist/bridges/a2a.js +29 -19
- package/dist/bridges/a2a.js.map +1 -1
- package/dist/bridges/hops.d.ts +1 -1
- package/dist/bridges/hops.d.ts.map +1 -1
- package/dist/bridges/hops.js +1 -1
- package/dist/bridges/hops.js.map +1 -1
- package/dist/bridges/mcp.d.ts +27 -7
- package/dist/bridges/mcp.d.ts.map +1 -1
- package/dist/bridges/mcp.js +24 -9
- package/dist/bridges/mcp.js.map +1 -1
- package/dist/client/bytes.d.ts +5 -0
- package/dist/client/bytes.d.ts.map +1 -1
- package/dist/client/bytes.js +15 -0
- package/dist/client/bytes.js.map +1 -1
- package/dist/client/capabilities.d.ts +25 -13
- package/dist/client/capabilities.d.ts.map +1 -1
- package/dist/client/capabilities.js +145 -123
- package/dist/client/capabilities.js.map +1 -1
- package/dist/client/error-classify.d.ts +57 -0
- package/dist/client/error-classify.d.ts.map +1 -0
- package/dist/client/error-classify.js +347 -0
- package/dist/client/error-classify.js.map +1 -0
- package/dist/client/errors.d.ts +113 -40
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +191 -53
- package/dist/client/errors.js.map +1 -1
- package/dist/client/internals.d.ts +1 -0
- package/dist/client/internals.d.ts.map +1 -1
- package/dist/client/internals.js +1 -0
- package/dist/client/internals.js.map +1 -1
- package/dist/client/laser.d.ts +62 -46
- package/dist/client/laser.d.ts.map +1 -1
- package/dist/client/laser.js +209 -120
- package/dist/client/laser.js.map +1 -1
- package/dist/client/managed.d.ts +3 -0
- package/dist/client/managed.d.ts.map +1 -1
- package/dist/client/managed.js +70 -3
- package/dist/client/managed.js.map +1 -1
- package/dist/context-scope.d.ts +25 -9
- package/dist/context-scope.d.ts.map +1 -1
- package/dist/context-scope.js +36 -9
- package/dist/context-scope.js.map +1 -1
- package/dist/context.d.ts +33 -16
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +174 -95
- package/dist/context.js.map +1 -1
- package/dist/conversation-state.d.ts +1 -1
- package/dist/conversation-state.d.ts.map +1 -1
- package/dist/conversation-state.js +35 -16
- package/dist/conversation-state.js.map +1 -1
- package/dist/govern.d.ts +24 -5
- package/dist/govern.d.ts.map +1 -1
- package/dist/govern.js +116 -28
- package/dist/govern.js.map +1 -1
- package/dist/iggy/apache-iggy.d.ts +59 -56
- package/dist/iggy/apache-iggy.d.ts.map +1 -1
- package/dist/iggy/apache-iggy.js +300 -137
- package/dist/iggy/apache-iggy.js.map +1 -1
- package/dist/index.d.ts +97 -65
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -30
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +16 -2
- package/dist/intent.d.ts.map +1 -1
- package/dist/intent.js +50 -18
- package/dist/intent.js.map +1 -1
- package/dist/managed/coordination.d.ts +82 -0
- package/dist/managed/coordination.d.ts.map +1 -0
- package/dist/managed/coordination.js +367 -0
- package/dist/managed/coordination.js.map +1 -0
- package/dist/managed/destinations.d.ts +4 -3
- package/dist/managed/destinations.d.ts.map +1 -1
- package/dist/managed/destinations.js +29 -13
- package/dist/managed/destinations.js.map +1 -1
- package/dist/managed/filters.d.ts +5 -5
- package/dist/managed/filters.d.ts.map +1 -1
- package/dist/managed/filters.js +39 -22
- package/dist/managed/filters.js.map +1 -1
- package/dist/managed/forks.d.ts +8 -11
- package/dist/managed/forks.d.ts.map +1 -1
- package/dist/managed/forks.js +33 -13
- package/dist/managed/forks.js.map +1 -1
- package/dist/managed/graph.d.ts +1 -4
- package/dist/managed/graph.d.ts.map +1 -1
- package/dist/managed/graph.js +5 -3
- package/dist/managed/graph.js.map +1 -1
- package/dist/managed/kv.d.ts +26 -14
- package/dist/managed/kv.d.ts.map +1 -1
- package/dist/managed/kv.js +88 -61
- package/dist/managed/kv.js.map +1 -1
- package/dist/managed/projections.d.ts +5 -8
- package/dist/managed/projections.d.ts.map +1 -1
- package/dist/managed/projections.js +22 -2
- package/dist/managed/projections.js.map +1 -1
- package/dist/managed/query.d.ts +20 -6
- package/dist/managed/query.d.ts.map +1 -1
- package/dist/managed/query.js +97 -24
- package/dist/managed/query.js.map +1 -1
- package/dist/managed/runs.d.ts +2 -4
- package/dist/managed/runs.d.ts.map +1 -1
- package/dist/managed/runs.js +9 -1
- package/dist/managed/runs.js.map +1 -1
- package/dist/managed/watch.d.ts +2 -4
- package/dist/managed/watch.d.ts.map +1 -1
- package/dist/managed/watch.js +9 -1
- package/dist/managed/watch.js.map +1 -1
- package/dist/memory/handle.d.ts +75 -22
- package/dist/memory/handle.d.ts.map +1 -1
- package/dist/memory/handle.js +232 -58
- package/dist/memory/handle.js.map +1 -1
- package/dist/memory/log-memory.d.ts +24 -12
- package/dist/memory/log-memory.d.ts.map +1 -1
- package/dist/memory/log-memory.js +214 -100
- package/dist/memory/log-memory.js.map +1 -1
- package/dist/memory/topic.d.ts +2 -2
- package/dist/memory/topic.d.ts.map +1 -1
- package/dist/memory/topic.js +7 -5
- package/dist/memory/topic.js.map +1 -1
- package/dist/memory/types.d.ts +41 -5
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +44 -18
- package/dist/memory/types.js.map +1 -1
- package/dist/memory/vector-memory.d.ts +8 -6
- package/dist/memory/vector-memory.d.ts.map +1 -1
- package/dist/memory/vector-memory.js +65 -34
- package/dist/memory/vector-memory.js.map +1 -1
- package/dist/memory.d.ts +6 -5
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +4 -4
- package/dist/memory.js.map +1 -1
- package/dist/provenance/agent-topic.d.ts +3 -1
- package/dist/provenance/agent-topic.d.ts.map +1 -1
- package/dist/provenance/agent-topic.js +3 -1
- package/dist/provenance/agent-topic.js.map +1 -1
- package/dist/provenance/provenance.d.ts +3 -3
- package/dist/provenance/provenance.d.ts.map +1 -1
- package/dist/provenance/provenance.js +30 -18
- package/dist/provenance/provenance.js.map +1 -1
- package/dist/runtime/clock.d.ts +3 -0
- package/dist/runtime/clock.d.ts.map +1 -1
- package/dist/runtime/clock.js +16 -3
- package/dist/runtime/clock.js.map +1 -1
- package/dist/schema-codecs.d.ts +7 -3
- package/dist/schema-codecs.d.ts.map +1 -1
- package/dist/schema-codecs.js +80 -12
- package/dist/schema-codecs.js.map +1 -1
- package/dist/session.d.ts +27 -18
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +95 -37
- package/dist/session.js.map +1 -1
- package/dist/signing.d.ts +11 -5
- package/dist/signing.d.ts.map +1 -1
- package/dist/signing.js +64 -21
- package/dist/signing.js.map +1 -1
- package/dist/snapshot.d.ts +10 -2
- package/dist/snapshot.d.ts.map +1 -1
- package/dist/snapshot.js +62 -28
- package/dist/snapshot.js.map +1 -1
- package/dist/state-store.d.ts +1 -1
- package/dist/state-store.d.ts.map +1 -1
- package/dist/state-store.js.map +1 -1
- package/dist/stream/batching.d.ts +81 -0
- package/dist/stream/batching.d.ts.map +1 -0
- package/dist/stream/batching.js +210 -0
- package/dist/stream/batching.js.map +1 -0
- package/dist/stream/bson.d.ts +3 -0
- package/dist/stream/bson.d.ts.map +1 -0
- package/dist/stream/bson.js +245 -0
- package/dist/stream/bson.js.map +1 -0
- package/dist/stream/codecs.d.ts +58 -6
- package/dist/stream/codecs.d.ts.map +1 -1
- package/dist/stream/codecs.js +143 -59
- package/dist/stream/codecs.js.map +1 -1
- package/dist/stream/consumer-group.d.ts +13 -10
- package/dist/stream/consumer-group.d.ts.map +1 -1
- package/dist/stream/consumer-group.js +91 -31
- package/dist/stream/consumer-group.js.map +1 -1
- package/dist/stream/consumer-start.d.ts +17 -0
- package/dist/stream/consumer-start.d.ts.map +1 -0
- package/dist/stream/consumer-start.js +2 -0
- package/dist/stream/consumer-start.js.map +1 -0
- package/dist/stream/consumer.d.ts +166 -24
- package/dist/stream/consumer.d.ts.map +1 -1
- package/dist/stream/consumer.js +451 -68
- package/dist/stream/consumer.js.map +1 -1
- package/dist/stream/cursor.d.ts +5 -12
- package/dist/stream/cursor.d.ts.map +1 -1
- package/dist/stream/cursor.js +34 -8
- package/dist/stream/cursor.js.map +1 -1
- package/dist/stream/header-value.d.ts +61 -15
- package/dist/stream/header-value.d.ts.map +1 -1
- package/dist/stream/header-value.js.map +1 -1
- package/dist/stream/message.d.ts +17 -0
- package/dist/stream/message.d.ts.map +1 -0
- package/dist/stream/message.js +9 -0
- package/dist/stream/message.js.map +1 -0
- package/dist/stream/producer.d.ts +127 -11
- package/dist/stream/producer.d.ts.map +1 -1
- package/dist/stream/producer.js +401 -36
- package/dist/stream/producer.js.map +1 -1
- package/dist/stream/publish.d.ts +6 -15
- package/dist/stream/publish.d.ts.map +1 -1
- package/dist/stream/publish.js +18 -28
- package/dist/stream/publish.js.map +1 -1
- package/dist/stream/record.d.ts +4 -6
- package/dist/stream/record.d.ts.map +1 -1
- package/dist/stream/record.js +4 -3
- package/dist/stream/record.js.map +1 -1
- package/dist/stream/routing.d.ts +12 -0
- package/dist/stream/routing.d.ts.map +1 -1
- package/dist/stream/routing.js +6 -1
- package/dist/stream/routing.js.map +1 -1
- package/dist/stream/stream.d.ts +1 -4
- package/dist/stream/stream.d.ts.map +1 -1
- package/dist/stream/stream.js +5 -1
- package/dist/stream/stream.js.map +1 -1
- package/dist/stream/topic.d.ts +22 -23
- package/dist/stream/topic.d.ts.map +1 -1
- package/dist/stream/topic.js +90 -30
- package/dist/stream/topic.js.map +1 -1
- package/dist/stream/typed-topic.d.ts +9 -13
- package/dist/stream/typed-topic.d.ts.map +1 -1
- package/dist/stream/typed-topic.js +25 -10
- package/dist/stream/typed-topic.js.map +1 -1
- package/dist/swarm.d.ts +0 -1
- package/dist/swarm.d.ts.map +1 -1
- package/dist/swarm.js +1 -0
- package/dist/swarm.js.map +1 -1
- package/dist/testing.d.ts +3 -3
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +3 -3
- package/dist/testing.js.map +1 -1
- package/dist/types/ids.d.ts +17 -2
- package/dist/types/ids.d.ts.map +1 -1
- package/dist/types/ids.js +34 -14
- package/dist/types/ids.js.map +1 -1
- package/dist/wire/agent.d.ts +22 -0
- package/dist/wire/agent.d.ts.map +1 -1
- package/dist/wire/agent.js +80 -25
- package/dist/wire/agent.js.map +1 -1
- package/dist/wire/authz.d.ts +35 -1
- package/dist/wire/authz.d.ts.map +1 -1
- package/dist/wire/authz.js +45 -15
- package/dist/wire/authz.js.map +1 -1
- package/dist/wire/cbor.d.ts.map +1 -1
- package/dist/wire/cbor.js +13 -2
- package/dist/wire/cbor.js.map +1 -1
- package/dist/wire/checkpoint.d.ts +17 -12
- package/dist/wire/checkpoint.d.ts.map +1 -1
- package/dist/wire/checkpoint.js +28 -3
- package/dist/wire/checkpoint.js.map +1 -1
- package/dist/wire/control.d.ts +82 -0
- package/dist/wire/control.d.ts.map +1 -1
- package/dist/wire/control.js +219 -0
- package/dist/wire/control.js.map +1 -1
- package/dist/wire/filter-eval.d.ts +41 -7
- package/dist/wire/filter-eval.d.ts.map +1 -1
- package/dist/wire/filter-eval.js +26 -28
- package/dist/wire/filter-eval.js.map +1 -1
- package/dist/wire/filter.d.ts +51 -17
- package/dist/wire/filter.d.ts.map +1 -1
- package/dist/wire/filter.js +99 -10
- package/dist/wire/filter.js.map +1 -1
- package/dist/wire/fork.d.ts +14 -1
- package/dist/wire/fork.d.ts.map +1 -1
- package/dist/wire/fork.js +19 -8
- package/dist/wire/fork.js.map +1 -1
- package/dist/wire/graph.d.ts +3 -0
- package/dist/wire/graph.d.ts.map +1 -1
- package/dist/wire/graph.js +18 -4
- package/dist/wire/graph.js.map +1 -1
- package/dist/wire/hello.d.ts +4 -1
- package/dist/wire/hello.d.ts.map +1 -1
- package/dist/wire/hello.js +13 -3
- package/dist/wire/hello.js.map +1 -1
- package/dist/wire/index.d.ts +4 -1
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +4 -1
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/kv.d.ts +37 -2
- package/dist/wire/kv.d.ts.map +1 -1
- package/dist/wire/kv.js +36 -18
- package/dist/wire/kv.js.map +1 -1
- package/dist/wire/query.d.ts +6 -0
- package/dist/wire/query.d.ts.map +1 -1
- package/dist/wire/query.js +38 -12
- package/dist/wire/query.js.map +1 -1
- package/dist/wire/schema.d.ts +29 -6
- package/dist/wire/schema.d.ts.map +1 -1
- package/dist/wire/schema.js +61 -26
- package/dist/wire/schema.js.map +1 -1
- package/dist/wire/snapshot.js +1 -1
- package/dist/wire/snapshot.js.map +1 -1
- package/dist/wire/value.d.ts +10 -2
- package/dist/wire/value.d.ts.map +1 -1
- package/dist/wire/value.js +29 -3
- package/dist/wire/value.js.map +1 -1
- package/package.json +2 -3
- package/dist/stream/polling-strategy.d.ts +0 -14
- package/dist/stream/polling-strategy.d.ts.map +0 -1
- package/dist/stream/polling-strategy.js +0 -2
- package/dist/stream/polling-strategy.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ This package provides the native TypeScript Laser SDK for Apache Iggy. [LaserDat
|
|
|
4
4
|
|
|
5
5
|
This prerelease targets Node 22.14 or later. Bun, Deno, and browsers are not supported because the Apache Iggy transport uses Node TCP and TLS APIs.
|
|
6
6
|
|
|
7
|
-
> The current release is `0.
|
|
7
|
+
> The current release is `0.6.0`. The wire contract and public API use semantic versioning. Before `1.0.0`, minor releases can contain breaking changes.
|
|
8
8
|
|
|
9
9
|
**Filter before the network.** Consumer filters select records on the server so each reader receives only its matching subset of a topic and its partitions. The shared CDC example delivers **4 of 240 records** and saves **98.5% of payload transfer**. It preserves original payloads and offsets, supports exact-width typed headers, and acknowledges only completed work. See the [Consumer Filters guide](https://docs.laserdata.cloud/laser-sdk/consumer-filters) and the [three-language examples](https://github.com/laserdata/laser-sdk/tree/main/examples).
|
|
10
10
|
|
|
@@ -24,20 +24,20 @@ import { Laser } from "@laserdata/laser-sdk"
|
|
|
24
24
|
await using laser = await Laser.connect(
|
|
25
25
|
process.env.LASER_CONNECTION_STRING ?? "iggy:iggy@127.0.0.1:8090"
|
|
26
26
|
)
|
|
27
|
-
const topic = laser.stream("
|
|
27
|
+
const topic = laser.stream("fleet").topic("readings")
|
|
28
28
|
await topic.ensure(4)
|
|
29
|
-
const committed = await topic.publish().json({
|
|
29
|
+
const committed = await topic.publish().json({ host: "node-7", cpu: 82 }).send()
|
|
30
30
|
console.log(committed.confirmations)
|
|
31
31
|
|
|
32
32
|
const records = await (await topic.replay()).poll()
|
|
33
|
-
console.log(`read ${records.length}
|
|
33
|
+
console.log(`read ${records.length} reading(s)`)
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Use a `user:password@host:port` connection string. The SDK supplies the Apache Iggy TCP scheme. Select a stream with `laser.stream(name)` and a topic with `.topic(name)`. `Laser.connectWithStream()` selects a default for the shorter `laser.topic(name)` form. It does not restrict stream access.
|
|
37
37
|
|
|
38
38
|
`Laser.connectEnv()` reads `LASER_CONNECTION_STRING` and optional `LASER_STREAM`. `Laser.local()` uses the default local server. `Laser.builder()` accepts a connection string, separate credentials, or an Apache Iggy client. For an injected client, select whether Laser SDK owns or borrows it.
|
|
39
39
|
|
|
40
|
-
For owned connections, the SDK retries
|
|
40
|
+
For owned connections, the SDK retries a failed dial and reconnects dropped sockets, by default without limit at one-second intervals. The 30-second connect budget stops the retries of the initial connection. Add `reconnection_retries` to the connection string with a non-negative integer to limit retries, and `reconnection_interval` with a duration such as `250ms`, `1s`, or `1m`, for example `iggy:iggy@127.0.0.1:8090?reconnection_retries=5&reconnection_interval=250ms`. The caller controls the lifecycle and reconnect policy of an injected client.
|
|
41
41
|
|
|
42
42
|
The TypeScript SDK uses Iggy's native VSR transport for owned and injected clients.
|
|
43
43
|
|
|
@@ -46,10 +46,11 @@ The TypeScript SDK uses Iggy's native VSR transport for owned and injected clien
|
|
|
46
46
|
`laser.stream(name).topic(name)` addresses any stream. `laser.topic(name)` is the default-stream shortcut. Topics support:
|
|
47
47
|
|
|
48
48
|
- raw, JSON, CBOR, MessagePack, Avro, Protobuf, and JSON Schema records
|
|
49
|
-
- exact headers,
|
|
50
|
-
- direct producers with bounded retry and
|
|
49
|
+
- exact headers, indexes, projection and schema IDs, inline payload, claim-check, routing keys, explicit partitions, and heterogeneous batches
|
|
50
|
+
- direct producers with bounded retry, explicit batching, and stream and topic creation on the first send (`createStream`, `createTopic`, `partitions`)
|
|
51
|
+
- a size-and-time batching publisher through `topic.batching()`
|
|
51
52
|
- standalone and consumer-group readers with first, last, next, offset, or timestamp starts
|
|
52
|
-
-
|
|
53
|
+
- the ten Rust commit policies through `commitPolicy`, such as `{ kind: "disabled" }` for manual commits, explicit `commit`, `storeOffset`, `deleteOffset`, and `lastStoredOffset`, replay, cancellation, and bounded `nextWithin()` waits that fail with `TimeoutError`
|
|
53
54
|
|
|
54
55
|
Delivery is at least once, so records can repeat. Ordering applies within each selected partition. Make external effects idempotent, which means safe to repeat. For operations that require a lease holder token, use fenced managed coordination.
|
|
55
56
|
|
|
@@ -57,31 +58,33 @@ Producers and publish builders return `SendMessagesResponse`. A confirmation ide
|
|
|
57
58
|
|
|
58
59
|
## Runtime-checked records
|
|
59
60
|
|
|
60
|
-
TypeScript types do not exist at runtime. A typed topic therefore takes a codec that checks decoded values. A generic type parameter alone cannot check incoming bytes.
|
|
61
|
+
TypeScript types do not exist at runtime. A typed topic therefore takes a codec that checks decoded values. A generic type parameter alone cannot check incoming bytes. The `Json`, `Cbor`, `Msgpack`, and `Bson` codec classes take an optional decode check, and a custom `Codec<T>` declares its `contentType` with `encode` and `decode`.
|
|
61
62
|
|
|
62
63
|
```ts
|
|
63
|
-
import {
|
|
64
|
+
import { Json } from "@laserdata/laser-sdk"
|
|
64
65
|
|
|
65
|
-
interface
|
|
66
|
-
readonly
|
|
67
|
-
readonly
|
|
66
|
+
interface Reading {
|
|
67
|
+
readonly host: string
|
|
68
|
+
readonly cpu: number
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
const
|
|
71
|
-
if (typeof value !== "object" || value === null)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
const readingCodec = new Json<Reading>((value) => {
|
|
72
|
+
if (typeof value !== "object" || value === null)
|
|
73
|
+
throw new TypeError("a reading must be an object")
|
|
74
|
+
const reading = value as Record<string, unknown>
|
|
75
|
+
if (typeof reading.host !== "string" || typeof reading.cpu !== "number") {
|
|
76
|
+
throw new TypeError("reading fields are invalid")
|
|
75
77
|
}
|
|
76
|
-
return {
|
|
78
|
+
return { host: reading.host, cpu: reading.cpu }
|
|
77
79
|
})
|
|
78
80
|
|
|
79
|
-
const
|
|
80
|
-
await
|
|
81
|
+
const readings = laser.stream("fleet").topic("readings").json(readingCodec)
|
|
82
|
+
await readings.publish({ host: "node-7", cpu: 82 })
|
|
81
83
|
|
|
82
|
-
const reader = await
|
|
83
|
-
const
|
|
84
|
-
console.log(record
|
|
84
|
+
const reader = await readings.records("readings-export")
|
|
85
|
+
for await (const item of reader.stream()) {
|
|
86
|
+
if (item.kind === "record") console.log(item.record.value)
|
|
87
|
+
}
|
|
85
88
|
```
|
|
86
89
|
|
|
87
90
|
Registered Avro, Protobuf, and JSON Schema topics compile their writer schema once. They reject invalid values before sending and attach the schema ID. Reads decode through the same schema.
|
|
@@ -95,29 +98,31 @@ The root client provides queries, projections, schemas, key-value state, forks,
|
|
|
95
98
|
```ts
|
|
96
99
|
import { graphNodeEntity, queryResultValue, typedValueDiagnosticText } from "@laserdata/laser-sdk"
|
|
97
100
|
|
|
98
|
-
const
|
|
99
|
-
for (const row of
|
|
100
|
-
const
|
|
101
|
-
console.log(
|
|
101
|
+
const degraded = await laser.query("readings_v1").whereEq("status", "degraded").limit(20).fetch()
|
|
102
|
+
for (const row of degraded.rows) {
|
|
103
|
+
const cpu = queryResultValue(degraded, row, "cpu")
|
|
104
|
+
console.log(cpu === undefined ? "missing" : typedValueDiagnosticText(cpu))
|
|
102
105
|
}
|
|
103
106
|
|
|
104
|
-
const key = new TextEncoder().encode("
|
|
105
|
-
|
|
106
|
-
await laser.kv("
|
|
107
|
-
const stored = await laser.kv("sessions").get(key)
|
|
107
|
+
const key = new TextEncoder().encode("service:auth")
|
|
108
|
+
await laser.kv("config").set(key).json({ log_level: "debug" }).ttl(300_000_000n).send()
|
|
109
|
+
const stored = await laser.kv("config").get(key)
|
|
108
110
|
|
|
109
|
-
const
|
|
110
|
-
const nearby = await laser.graph("ops").neighbors(
|
|
111
|
+
const auth = graphNodeEntity("Service", "auth")
|
|
112
|
+
const nearby = await laser.graph("ops").neighbors(auth.id, "out", undefined, 2)
|
|
111
113
|
```
|
|
112
114
|
|
|
113
115
|
`result.fields` defines the ordered result schema. Each `row.values` entry matches the field at the same position. Tagged values preserve numeric widths, decimal precision, timestamps, UUIDs, bytes, nested values, and nullability. Use `queryResultValue()` to select a field by name. Use `typedValueDiagnosticText()` for stable display text.
|
|
114
116
|
|
|
115
|
-
The first page can use an offset. Later pages use the `nextCursor` supplied by the server. `hasMore` is true exactly when that cursor is present. `fetchAll()` follows these cursors. Each page contains at most 1000 rows.
|
|
117
|
+
The first page can use an offset. Later pages use the `result.page.nextCursor` supplied by the server. `result.page.hasMore` is true exactly when that cursor is present. `fetchAll()` follows these cursors. Each page contains at most 1000 rows.
|
|
116
118
|
|
|
117
|
-
A query has a stable execution identity and absolute deadline
|
|
119
|
+
A query has a stable execution identity and an absolute deadline, 30 seconds after the request was built unless you set `deadlineMicros(epochMicros)` or the relative `deadline(milliseconds)`. `status()` and `cancel()` use dedicated managed commands and fail locally when the deployment does not advertise those capabilities. `laser.executeQuery(query)`, `queryPage(executionId, cursor, deadlineMicros)`, `queryStatus(executionId)`, and `cancelQuery(executionId)` are the lower-level forms:
|
|
118
120
|
|
|
119
121
|
```ts
|
|
120
|
-
const request = laser
|
|
122
|
+
const request = laser
|
|
123
|
+
.query("readings_v1")
|
|
124
|
+
.filterGte("cpu", { kind: "int", value: 90 })
|
|
125
|
+
.deadline(10_000)
|
|
121
126
|
const page = await request.fetch()
|
|
122
127
|
const status = await request.status()
|
|
123
128
|
if (status.state === "running") await request.cancel()
|
|
@@ -129,7 +134,7 @@ Lakehouse queries name one destination generation and can select a retained snap
|
|
|
129
134
|
const historical = await laser
|
|
130
135
|
.queryLakehouse(destinationId, destinationGeneration)
|
|
131
136
|
.atSnapshot(snapshotId)
|
|
132
|
-
.filterEq("
|
|
137
|
+
.filterEq("host_id", { kind: "string", value: "node-7" })
|
|
133
138
|
.limit(100)
|
|
134
139
|
.fetch()
|
|
135
140
|
|
|
@@ -143,7 +148,7 @@ Use `laser.destinations()` for destination declarations and explicit query route
|
|
|
143
148
|
```ts
|
|
144
149
|
const destinations = laser.destinations()
|
|
145
150
|
const page = await destinations.list("linearizable", {}, undefined, 50)
|
|
146
|
-
const routes = await destinations.queryRoutes("potentially_stale", "
|
|
151
|
+
const routes = await destinations.queryRoutes("potentially_stale", "readings", undefined, 50)
|
|
147
152
|
const current = await destinations.get(destinationId, "linearizable")
|
|
148
153
|
```
|
|
149
154
|
|
|
@@ -170,19 +175,21 @@ Accessors select operations without performing I/O. Methods such as `send()`, `f
|
|
|
170
175
|
|
|
171
176
|
A replay cursor saves offsets only after all partition reads succeed. A failed or canceled poll leaves them unchanged. Each request reads at most 10,000 messages. Further polls resume from the saved offsets. The TypeScript cursor stream continues waiting for new records until it is stopped.
|
|
172
177
|
|
|
173
|
-
Durable memory can use the default audit topic through `laser.memory(namespace)`, an existing isolated topic through `laser.memoryOnTopic(topic)`, or a configured topic:
|
|
178
|
+
Durable memory can use the default audit topic through `laser.memory(namespace)`, an existing isolated topic through `laser.memoryOnTopic(topic)`, or a configured topic. Each form needs a stream, from `Laser.connectWithStream()` or `withDefaultStream()`. `memoryTopic(topic).stream(name)` and `memoryOnTopic(topic, stream)` name one directly:
|
|
174
179
|
|
|
175
180
|
```ts
|
|
176
181
|
const incidents = await laser.memoryTopic("incidents").partitions(4).ttl(86_400_000).build()
|
|
177
182
|
|
|
178
|
-
await incidents.remember(new TextEncoder().encode("
|
|
183
|
+
await incidents.remember(new TextEncoder().encode("auth uses the read replica")).send()
|
|
179
184
|
```
|
|
180
185
|
|
|
181
|
-
|
|
186
|
+
Memory topic and consumer duration inputs use milliseconds. KV `ttl` and `expire` take a lifetime and `expireAt` takes an absolute time, all as microsecond `bigint` values. `noExpiry()` keeps the raw memory history until ordinary topic retention removes it.
|
|
182
187
|
|
|
183
|
-
|
|
188
|
+
Configure a consumer group's policy once. Its ordinary consumers and page readers then receive the selected records with their original payloads, headers and offsets. An unbound group receives all records without payload decoding.
|
|
184
189
|
|
|
185
190
|
```ts
|
|
191
|
+
import { ConsumerFilter, FilterExpr } from "@laserdata/laser-sdk"
|
|
192
|
+
|
|
186
193
|
const safeMode = ConsumerFilter.json(
|
|
187
194
|
FilterExpr.all([
|
|
188
195
|
FilterExpr.pred("table", "eq", "satellites"),
|
|
@@ -195,13 +202,11 @@ const group = topic.consumerGroup("anomaly-desk")
|
|
|
195
202
|
await group.create({ filter: safeMode }) // Run once during setup.
|
|
196
203
|
|
|
197
204
|
// Every consumer instance needs only the group name or the returned group ID.
|
|
198
|
-
const consumer = await group.consumer({ batchLength: 100,
|
|
205
|
+
const consumer = await group.consumer({ batchLength: 100, commitPolicy: { kind: "disabled" } })
|
|
199
206
|
try {
|
|
200
|
-
const record = await consumer.nextWithin(15_000)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
await consumer.commit(record)
|
|
204
|
-
}
|
|
207
|
+
const record = await consumer.nextWithin(15_000) // TimeoutError when nothing matched in time
|
|
208
|
+
console.log(record.position.partitionId, record.position.offset, record.json())
|
|
209
|
+
await consumer.commit(record)
|
|
205
210
|
} finally {
|
|
206
211
|
await consumer.shutdown()
|
|
207
212
|
}
|
|
@@ -213,7 +218,7 @@ For batch handling, build `await group.reader().count(100).maxExamined(1000).bui
|
|
|
213
218
|
|
|
214
219
|
`group.filter()` provides `configure`, `get`, `revisions`, `revise`, `setRevisionEnabled`, `release`, `delete`, `preview` and `test`. `delete()` removes the group's own filter with every revision and releases the group first. Use `configureAs(operationId, policy)` when setup must resume with the same operation ID after a lost reply. `topic.consumerGroupId(id)` addresses the same saved group by numeric ID. Catalog failures, denied reads and paused revisions never broaden into unfiltered delivery. Original Apache Iggy uses native group consumption, while an older managed server without group-aware reads returns an explicit upgrade error.
|
|
215
220
|
|
|
216
|
-
Filters support JSON, CBOR, Avro, Protobuf and typed headers. `CompiledFilter.compile(filter).evaluate(record)` checks records locally with exact integers. `ConsumerFilter.withFaultPolicy`, `withForeignPolicy` and `withMismatchPolicy` control invalid records. Passed invalid records and unfiltered records have `evaluated` false. Malformed headers set `headersMalformed` without discarding valid entries or the payload. Server refusals throw `FilterExecutionError`, and
|
|
221
|
+
Filters support JSON, CBOR, Avro, Protobuf and typed headers. `CompiledFilter.compile(filter).evaluate(record)` checks records locally with exact integers. `ConsumerFilter.withFaultPolicy`, `withForeignPolicy` and `withMismatchPolicy` control invalid records. Passed invalid records and unfiltered records have `evaluated` false. Malformed headers set `headersMalformed` without discarding valid entries or the payload. Server refusals throw `FilterExecutionError`. A fault stop throws `FilterFaultError` with its `reason`, and an oversized stop throws `FilterOversizedRecordError`. `filterReason(error)` reads the reason from any of them. See the [Consumer Filters guide](https://docs.laserdata.cloud/laser-sdk/consumer-filters) and the [three-language examples](https://github.com/laserdata/laser-sdk/tree/main/examples).
|
|
217
222
|
|
|
218
223
|
## Agents and coordination
|
|
219
224
|
|
|
@@ -221,7 +226,7 @@ The agent layer adds record origins, typed AGDX messages, routing, discovery, re
|
|
|
221
226
|
|
|
222
227
|
Sessions group one agent's conversation through `laser.sessions().create(id)`. `append(kind, data)` records a turn, and `context()` returns typed turns for a model. Turn kinds are `instruction`, `response`, `model.response`, `tool.call`, `tool.result`, and `human.input`. `memory().search(query)` searches memory scoped to the conversation.
|
|
223
228
|
|
|
224
|
-
A checkpoint records the next offset for each topic partition. `checkpoint()`, `turnsAt`, `turnsSince`, `stateAt`, and `replay` support reads and state reconstruction around those saved offsets. `Checkpoint.fromJSON(JSON.stringify(checkpoint))` restores a saved checkpoint. `laser.sessions(
|
|
229
|
+
A checkpoint records the next offset for each topic partition. `checkpoint()`, `turnsAt`, `turnsSince`, `stateAt`, and `replay` support reads and state reconstruction around those saved offsets. `Checkpoint.fromJSON(JSON.stringify(checkpoint))` restores a saved checkpoint. `laser.sessions(new SessionConfig().stream(name).topic(kind, topic).memoryNamespace(ns).contextTurns(n).contextTokens(n))` configures the stream, topics, memory namespace, and context limits. Each turn kind needs a distinct topic.
|
|
225
230
|
|
|
226
231
|
The root package provides context, snapshots, memory, governance, intent records, signing, delegation, A2A, MCP, AG-UI, and edge authorization. A configured verifier rejects unsigned or invalid replies for contracts, shared reply readers, and `requestInput`. It binds signatures to the observed headers and server timestamp. An agent with a signing key signs its `respond` and `respondInput` replies. `KvKeyRegistry` manages versioned keys through the platform. The SDK records model-call metadata but does not call a model.
|
|
227
232
|
|
|
@@ -233,10 +238,11 @@ await using handle = Agent.builder()
|
|
|
233
238
|
.listenOn(AgentTopic.Commands)
|
|
234
239
|
.respondOn(AgentTopic.Responses)
|
|
235
240
|
.handler({
|
|
236
|
-
handle(message,
|
|
237
|
-
return
|
|
241
|
+
handle(message, ctx) {
|
|
242
|
+
return ctx.respond(message.payload)
|
|
238
243
|
}
|
|
239
244
|
})
|
|
245
|
+
.build()
|
|
240
246
|
.spawn(laser)
|
|
241
247
|
|
|
242
248
|
await handle.ready()
|
|
@@ -249,50 +255,70 @@ Waiting operations accept `AbortSignal` or an explicit timeout where their contr
|
|
|
249
255
|
|
|
250
256
|
SDK failures extend `LaserError` and carry a stable `kind`. Separate subclasses identify configuration, timeout, cancellation, unknown mutation outcomes, unsupported operations, encoding, transport, policy, and signature failures. Catch a specific subclass when it needs different recovery. Otherwise, report the base error and its cause.
|
|
251
257
|
|
|
258
|
+
A failed publish throws `PublishFailedError` with the `stream`, `topic`, the `committed` confirmations, and the `unconfirmed` records. `publishCause()` reaches the original failure, so an `instanceof TransportError` check around a publish no longer matches. The classifiers mirror the Rust `LaserError` methods and answer through any publish wrapping: `isPermissionDenied`, `isUnsupported`, `isNotFound`, `isUnavailable`, `isNotLeader`, `isStale`, `isVersionSkew`, `isVersionConflict`, `isAmbiguousMutation`, `isStreamOrTopicNotFound`, `isNoCapableAgent`, `isLeaseLost`, `isFenceViolation`, `isBudgetExceeded`, `isQuarantined`, `isRetryable`, `filterReason`, `iggyErrorCode`, and `code`, which returns the unified result code. Routing failures throw `NoCapableAgentError`, `NoInboxError`, or `RoutePrincipalMismatchError`. Invalid identifiers throw `IdError` and malformed provenance headers throw `ProvenanceError`. Payloads are `Uint8Array`, so `TextEncoder` and `TextDecoder` convert text.
|
|
259
|
+
|
|
252
260
|
`Laser.connect*()` owns its Apache Iggy client. `Laser.builder()` can own or borrow an injected client. `Laser`, `Producer`, `Consumer`, and `AgentHandle` support `await using`. Their `close()` and `shutdown()` methods are safe to repeat. `close()` on any `Laser` view ends the shared connection for every view. Disposing a scoped view with `await using` leaves the root connection open.
|
|
253
261
|
|
|
254
|
-
##
|
|
262
|
+
## Connect timeout
|
|
255
263
|
|
|
256
|
-
|
|
257
|
-
- `@laserdata/laser-sdk/full` adds the complete native wire namespace
|
|
258
|
-
- `@laserdata/laser-sdk/testing` provides clocks, stores, fake transports, factories, observers, and bounded eventually checks
|
|
259
|
-
- `@laserdata/laser-sdk/opentelemetry` adapts the observer seam to OpenTelemetry
|
|
264
|
+
Connecting gives up after 30 seconds. Set another budget in milliseconds with `Laser.builder().connectTimeout()` or the `LASER_CONNECT_TIMEOUT_MS` environment variable. Explicit configuration overrides the variable. The budget covers the TCP dial, the TLS handshake, the login, and the capability probe. An expired budget rejects with a `TimeoutError` that says whether the server never accepted the connection or never answered the login. `laser.stream(name).delete()` removes a stream you no longer need, and `laser.close()` ends the shared connection. See [connect timeout and cleanup](../../docs/connect-timeout.md).
|
|
260
265
|
|
|
261
|
-
|
|
266
|
+
## Publish recovery
|
|
262
267
|
|
|
263
|
-
|
|
268
|
+
Publish attempts default to 60 seconds with three retries. Retry delays start at 250 milliseconds, double after each failure, and stop increasing at 30 seconds. Set them with `publishTimeout`, `publishMaxRetries`, and `publishRetryBackoff` on `Laser.builder()`, or with `LASER_PUBLISH_TIMEOUT_MS`, `LASER_PUBLISH_MAX_RETRIES`, and `LASER_PUBLISH_RETRY_BACKOFF_MS`. Explicit configuration overrides the variables. Exhausted retries reject with a `PublishFailedError`, so check `committed` before resending. A batching publisher from `topic.batching()` keeps a failed timer flush until `send()`, `flush()`, or `close()` reports it. See [publish recovery and outage handling](../../docs/publish-recovery.md).
|
|
264
269
|
|
|
265
|
-
|
|
270
|
+
## Consumer filter groups and offsets
|
|
266
271
|
|
|
267
|
-
|
|
268
|
-
npm ci
|
|
269
|
-
npm run verify
|
|
270
|
-
```
|
|
272
|
+
**Provision a filtered group once, then consume by its ID.** The filter API supports create-and-bind setup, numeric group selection, and revision pause/resume. Use separate groups for A/B revisions so their offsets remain independent. A fresh named consumer using `Next` starts at the first retained record. Ordinary consumers auto-commit each polled batch before delivery by default, so a later consumer can resume after records the application did not process. Disable auto-commit and commit after successful processing when that matters. Filtered readers use explicit acknowledgments, and keep at most 1024 unacknowledged record-bearing pages per partition by default, set with `maxUnackedPages`, so a reader that never acknowledges stops at that bound instead of growing without limit. Unnamed TypeScript consumers have isolated identities and default to no automatic commit. Use a stable name to resume durable progress. See the [Consumer Filters guide](https://docs.laserdata.cloud/laser-sdk/consumer-filters).
|
|
271
273
|
|
|
272
|
-
|
|
274
|
+
Avro and Protobuf filters use registered writer schemas, immutable schema IDs in the filter, and the `agdx.sid` header on each record. Headers-only filters work with any payload format. Filtering preserves original bytes and offsets.
|
|
273
275
|
|
|
274
|
-
|
|
276
|
+
For an application checkpoint inside a filtered page, call `reader.ackThrough(record)` after persisting the checkpoint and processing all preceding records on that partition. Later records in the same page stay pending. Use `ackPage` when the whole page is complete.
|
|
275
277
|
|
|
276
|
-
|
|
278
|
+
Consumer-filter patterns use the server's bounded Rust regex engine. TypeScript validates structure and lets the server decide regex syntax. A local `CompiledFilter` refuses regex predicates, because only the server's engine defines their meaning. A filter permits four compiled glob or regex predicates, with a 256 KiB program budget each. Enabling `localGuard(true)` on a reader whose filter has regex predicates throws a `ConfigError` instead of skipping verification. Guards verify unevaluated records under the server's reported decoder bounds and the applicable pass policy.
|
|
277
279
|
|
|
278
|
-
##
|
|
280
|
+
## 0.6.0 additions
|
|
279
281
|
|
|
280
|
-
|
|
282
|
+
These match the Rust and Python surfaces:
|
|
281
283
|
|
|
282
|
-
|
|
284
|
+
- Producer options `batchLength`, `lingerMs`, `maxTopicBytes`, `unlimitedTopicSize`, and `background`. In background mode a send returns once its records are buffered, and `shutdown()` drains the buffer, closes, and reports a background send failure.
|
|
285
|
+
- `QueryRequest.atSnapshot(id)`, `atTimestampMicros(ts)`, and `rowsTyped(codec)`.
|
|
286
|
+
- `MemoryHandle.backend`, `AgentScope.contract(router)`, and `SwappableGovernor.current()`.
|
|
287
|
+
- Capability helpers `isOpenOnly`, `servesConsistency`, `isReady`, `readinessReasons`, `enabledBackends`, and `unreadyBackends`.
|
|
288
|
+
- `AgdxSend.claimCheck(store, thresholdBytes)` moves a body at or over the threshold to the blob store before signing.
|
|
289
|
+
- `ConversationId.asU128()` returns the raw 128-bit ULID value.
|
|
290
|
+
- `MemoryHandle.consolidate` and `ScopedMemory.consolidate` take `{ summarizer, pruneSummarized }` to fold `message` items into one summary per conversation and to forget the folded items.
|
|
291
|
+
- `filterCapsEvaluates(filters, evaluatorVersion, codec)` tells whether the server evaluates a filter exactly as this build does.
|
|
292
|
+
- `KeyRecord.keyId()` returns the 8-byte identifier of the record's public key.
|
|
293
|
+
- `MemoryHandler` wraps an agent handler, and `autoRemember(kind)` remembers each handled message under its conversation.
|
|
294
|
+
- `cardIsFresh`, `cardServes`, and `cardAvailableFor` check the freshness, the skills, and the advertised health of a registered card.
|
|
295
|
+
- `new ProjectionBuilder(id)`, `new ProjectionBindingBuilder()`, and `new IndexSchemaBuilder()` build projection declarations with the Rust defaults.
|
|
296
|
+
- `laser.fork(id)` returns a `ForkHandle` whose `id` names the fork.
|
|
283
297
|
|
|
284
|
-
##
|
|
298
|
+
## 0.6.0 breaking changes
|
|
285
299
|
|
|
286
|
-
|
|
300
|
+
0.6.0 changes several TypeScript signatures. A publish that gives up throws `PublishFailedError` around the original error, `Consumer.nextWithin` throws `TimeoutError` instead of returning `null`, and `Kv.expire` takes a lifetime while `expireAt` takes an absolute time. `ConsolidationReport` reports `summarized`, `reweighted`, `pruned`, and `derived`, and `Consolidator.consolidate(scope, signal?)` no longer receives a memory argument. Fork row embeddings take numbers. The [client behavior guide](../../docs/client-behavior.md) lists every change with its replacement.
|
|
287
301
|
|
|
288
|
-
|
|
302
|
+
## Package exports
|
|
289
303
|
|
|
290
|
-
|
|
304
|
+
- `@laserdata/laser-sdk` is the ordinary application surface
|
|
305
|
+
- `@laserdata/laser-sdk/full` adds the native `wire` namespace
|
|
306
|
+
- `@laserdata/laser-sdk/testing` provides `TestClock`, `InMemoryStore`, and the `agentMessage` and `agentCtx` factories for handler tests
|
|
307
|
+
- `@laserdata/laser-sdk/opentelemetry` adapts the observer seam to OpenTelemetry
|
|
291
308
|
|
|
292
|
-
|
|
309
|
+
`laser.client` (a property) is the Apache Iggy escape hatch for native administrative or transport operations that Laser does not wrap.
|
|
310
|
+
|
|
311
|
+
## Examples and verification
|
|
293
312
|
|
|
294
|
-
|
|
313
|
+
The examples in [`examples/typescript`](../../examples/typescript/README.md) cover nine focused operations and nine larger applications. The shared scenarios under [`bdd/scenarios`](../../bdd/scenarios) describe behavior across clients.
|
|
295
314
|
|
|
296
|
-
|
|
315
|
+
```sh
|
|
316
|
+
npm ci
|
|
317
|
+
npm run verify
|
|
318
|
+
```
|
|
297
319
|
|
|
298
|
-
|
|
320
|
+
`verify` runs formatting, lint, dependency-boundary, type, build, API, unit, wire, coverage, license, and package tests. Integration and shared BDD tests run separately against the versioned native Iggy server.
|
|
321
|
+
|
|
322
|
+
## Security and license
|
|
323
|
+
|
|
324
|
+
Report security issues through the repository security policy. The package is Apache-2.0 licensed. Apache and Apache Iggy are trademarks of the Apache Software Foundation.
|
package/dist/agent/agdx.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { type BlobStore } from "../blob.js";
|
|
1
2
|
import { type BytesLike } from "../client/bytes.js";
|
|
2
3
|
import type { LaserTransport } from "../iggy/apache-iggy.js";
|
|
3
|
-
import {
|
|
4
|
+
import type { UlidSource } from "../runtime/ulid.js";
|
|
4
5
|
import { type KeyRegistry, type SigningKey } from "../signing.js";
|
|
5
6
|
import { type AgentId as SdkAgentId, type ConversationId as SdkConversationId } from "../types/ids.js";
|
|
6
7
|
import { type AgentEnvelope, type AgentErrorBody, type IdempotencyKey, type TaskState, type TokenUsage } from "../wire/agent.js";
|
|
@@ -10,9 +11,7 @@ import type { Value } from "../wire/value.js";
|
|
|
10
11
|
export declare const DEFAULT_CHUNK_FLUSH_BYTES = 512;
|
|
11
12
|
export declare const DEFAULT_CHUNK_LINGER_MS = 20;
|
|
12
13
|
export declare const MAX_CHUNK_BODY_BYTES: number;
|
|
13
|
-
export type AgdxLogPosition = LogPosition;
|
|
14
14
|
export interface Agdx {
|
|
15
|
-
readonly topicName: string;
|
|
16
15
|
command(correlation: CorrelationId, body: BytesLike): AgdxSend;
|
|
17
16
|
respond(correlation: CorrelationId, body: BytesLike): AgdxSend;
|
|
18
17
|
emit(body: BytesLike): AgdxSend;
|
|
@@ -39,6 +38,12 @@ export interface AgdxSend {
|
|
|
39
38
|
contentType(contentType: ContentType): this;
|
|
40
39
|
body(body: BytesLike): this;
|
|
41
40
|
signedBy(key: SigningKey): this;
|
|
41
|
+
/**
|
|
42
|
+
* Externalizes a body at or over `thresholdBytes` to `store` at send and
|
|
43
|
+
* replaces it with the body reference capsule (content type `ref`). Applied
|
|
44
|
+
* before signing, so a signature covers the capsule the log carries.
|
|
45
|
+
*/
|
|
46
|
+
claimCheck(store: BlobStore, thresholdBytes: number): this;
|
|
42
47
|
send(): Promise<RecordId | undefined>;
|
|
43
48
|
}
|
|
44
49
|
export interface AgdxStream {
|
package/dist/agent/agdx.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agdx.d.ts","sourceRoot":"","sources":["../../src/agent/agdx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,oBAAoB,CAAA;AAE/D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"agdx.d.ts","sourceRoot":"","sources":["../../src/agent/agdx.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/agdx.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { checkIn } from "../blob.js";
|
|
1
2
|
import { ownedBytes } from "../client/bytes.js";
|
|
2
3
|
import { CancelledError, InvalidError, RejectedError, TimeoutError } from "../client/errors.js";
|
|
3
|
-
import { mintUlidValue } from "../runtime/ulid.js";
|
|
4
4
|
import {} from "../signing.js";
|
|
5
5
|
import { decodeAgentMessage } from "./reliable-consumer.js";
|
|
6
|
-
import {} from "../types/ids.js";
|
|
7
|
-
import { AgentKind, chunkEnvelope, commandEnvelope, decodeAgentErrorBody, encodeAgentErrorBody, errorEnvelope, eventEnvelope, responseEnvelope,
|
|
6
|
+
import { MintUlid } from "../types/ids.js";
|
|
7
|
+
import { AgentKind, chunkEnvelope, commandEnvelope, decodeAgentErrorBody, encodeAgentErrorBody, errorEnvelope, eventEnvelope, responseEnvelope, statusEnvelope, validateAgentEnvelope, withCause, withCorrelation, withDeadlineMicros, withIdempotencyKey, withMetadata, withOperation, withTarget, withTaskState, withTool, withUsage } from "../wire/agent.js";
|
|
8
8
|
import { canonicalAgentRecord } from "../wire/agent-record.js";
|
|
9
9
|
import { decodeOne, encodeNamed, expectMap } from "../wire/cbor.js";
|
|
10
10
|
import { AGENT_OP_VERSION } from "../wire/codes.js";
|
|
@@ -33,9 +33,6 @@ function delay(ms, signal) {
|
|
|
33
33
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
-
function wireAgentId(agent) {
|
|
37
|
-
return parseAgentId(agent.asString());
|
|
38
|
-
}
|
|
39
36
|
function u32FromLittleEndian(header) {
|
|
40
37
|
if (header.bytes.byteLength !== 4)
|
|
41
38
|
throw new InvalidError("AGDX u32 header must be 4 bytes");
|
|
@@ -70,13 +67,13 @@ function assemble(envelope, contentType) {
|
|
|
70
67
|
};
|
|
71
68
|
}
|
|
72
69
|
function mintRecordId(source) {
|
|
73
|
-
return
|
|
70
|
+
return MintUlid.mint(RecordId, source);
|
|
74
71
|
}
|
|
75
72
|
function mintCorrelationId(source) {
|
|
76
|
-
return
|
|
73
|
+
return MintUlid.mint(CorrelationId, source);
|
|
77
74
|
}
|
|
78
75
|
function mintChannelId(source) {
|
|
79
|
-
return
|
|
76
|
+
return MintUlid.mint(ChannelId, source);
|
|
80
77
|
}
|
|
81
78
|
class AgdxReplyReader {
|
|
82
79
|
transport;
|
|
@@ -224,19 +221,31 @@ class AgdxClient {
|
|
|
224
221
|
await this.transport.sendMessagesWithHeaders(this.streamName, this.topicName, [message], this.conversationId.toString());
|
|
225
222
|
return envelope.record;
|
|
226
223
|
}
|
|
227
|
-
async prepare(envelope, contentType, signingKey) {
|
|
224
|
+
async prepare(envelope, contentType, signingKey, claimCheck) {
|
|
228
225
|
const body = this.govern === undefined
|
|
229
226
|
? envelope.body
|
|
230
227
|
: await this.govern(envelope, signingKey !== undefined);
|
|
231
|
-
|
|
228
|
+
let prepared = body === envelope.body ? envelope : { ...envelope, body };
|
|
229
|
+
let preparedType = contentType;
|
|
230
|
+
// Claim-check runs after governance and before signing, so the signature
|
|
231
|
+
// covers the capsule the log carries.
|
|
232
|
+
if (claimCheck !== undefined) {
|
|
233
|
+
const checked = await checkIn(claimCheck.store, claimCheck.thresholdBytes, prepared.body);
|
|
234
|
+
prepared = { ...prepared, body: checked.payload };
|
|
235
|
+
if (checked.contentType !== undefined)
|
|
236
|
+
preparedType = checked.contentType;
|
|
237
|
+
}
|
|
232
238
|
if (signingKey === undefined)
|
|
233
|
-
return
|
|
239
|
+
return { envelope: prepared, contentType: preparedType };
|
|
234
240
|
return {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
241
|
+
envelope: {
|
|
242
|
+
...prepared,
|
|
243
|
+
signature: signingKey.signWithContext(prepared, {
|
|
244
|
+
contentType: contentTypeCode(preparedType),
|
|
245
|
+
agentVersion: AGENT_OP_VERSION
|
|
246
|
+
})
|
|
247
|
+
},
|
|
248
|
+
contentType: preparedType
|
|
240
249
|
};
|
|
241
250
|
}
|
|
242
251
|
assemble(envelope, contentType) {
|
|
@@ -250,7 +259,7 @@ class AgdxClient {
|
|
|
250
259
|
}
|
|
251
260
|
}
|
|
252
261
|
export function createAgdx(transport, streamName, topicName, source, conversation, ulidSource, govern, verifier) {
|
|
253
|
-
return new AgdxClient(transport, streamName, topicName,
|
|
262
|
+
return new AgdxClient(transport, streamName, topicName, source.wireId(), ConversationId.parse(conversation.toString()), ulidSource, govern, verifier);
|
|
254
263
|
}
|
|
255
264
|
class AgdxSendBuilder {
|
|
256
265
|
agdx;
|
|
@@ -258,12 +267,13 @@ class AgdxSendBuilder {
|
|
|
258
267
|
contentTypeValue = ContentType.Raw;
|
|
259
268
|
sent = false;
|
|
260
269
|
signingKey;
|
|
270
|
+
claimCheckValue;
|
|
261
271
|
constructor(agdx, envelope) {
|
|
262
272
|
this.agdx = agdx;
|
|
263
273
|
this.envelope = envelope;
|
|
264
274
|
}
|
|
265
275
|
withTarget(target) {
|
|
266
|
-
this.envelope = withTarget(this.envelope,
|
|
276
|
+
this.envelope = withTarget(this.envelope, target.wireId());
|
|
267
277
|
return this;
|
|
268
278
|
}
|
|
269
279
|
withCause(cause, causeAt) {
|
|
@@ -318,12 +328,19 @@ class AgdxSendBuilder {
|
|
|
318
328
|
this.signingKey = key;
|
|
319
329
|
return this;
|
|
320
330
|
}
|
|
331
|
+
claimCheck(store, thresholdBytes) {
|
|
332
|
+
if (!Number.isSafeInteger(thresholdBytes) || thresholdBytes < 0) {
|
|
333
|
+
throw new InvalidError("claim-check threshold must be a non-negative safe integer");
|
|
334
|
+
}
|
|
335
|
+
this.claimCheckValue = { store, thresholdBytes };
|
|
336
|
+
return this;
|
|
337
|
+
}
|
|
321
338
|
async send() {
|
|
322
339
|
if (this.sent)
|
|
323
340
|
throw new InvalidError("an AGDX send can only be performed once");
|
|
324
341
|
this.sent = true;
|
|
325
|
-
const
|
|
326
|
-
return this.agdx.publish(envelope,
|
|
342
|
+
const prepared = await this.agdx.prepare(this.envelope, this.contentTypeValue, this.signingKey, this.claimCheckValue);
|
|
343
|
+
return this.agdx.publish(prepared.envelope, prepared.contentType);
|
|
327
344
|
}
|
|
328
345
|
}
|
|
329
346
|
class AgdxStreamWriter {
|
|
@@ -354,7 +371,7 @@ class AgdxStreamWriter {
|
|
|
354
371
|
return this;
|
|
355
372
|
}
|
|
356
373
|
withTarget(target) {
|
|
357
|
-
this.target =
|
|
374
|
+
this.target = target.wireId();
|
|
358
375
|
return this;
|
|
359
376
|
}
|
|
360
377
|
contentType(contentType) {
|