@rowan-agent/agent 0.8.2 → 0.8.4
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/dist/index.d.ts +2 -1
- package/dist/index.js +98 -20
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1391,7 +1391,7 @@ declare class InMemoryStore implements DurableStore {
|
|
|
1391
1391
|
ownerId: string;
|
|
1392
1392
|
leaseMs: number;
|
|
1393
1393
|
}): Promise<OwnedStore>;
|
|
1394
|
-
assertOwner(lease: OwnerLease): void;
|
|
1394
|
+
assertOwner(lease: OwnerLease, requireLive?: boolean): void;
|
|
1395
1395
|
renewOwner(lease: OwnerLease, leaseMs: number): OwnerLease;
|
|
1396
1396
|
releaseOwner(lease: OwnerLease): void;
|
|
1397
1397
|
reserveAgent(lease: OwnerLease, input: {
|
|
@@ -1667,6 +1667,7 @@ declare class SqliteStore implements DurableStore {
|
|
|
1667
1667
|
private persistState;
|
|
1668
1668
|
private requireMatchingOwner;
|
|
1669
1669
|
private immediateTransaction;
|
|
1670
|
+
private readTransaction;
|
|
1670
1671
|
private assertOpen;
|
|
1671
1672
|
}
|
|
1672
1673
|
|
package/dist/index.js
CHANGED
|
@@ -767,6 +767,15 @@ var EmptyResponseError = class extends Error {
|
|
|
767
767
|
this.name = "EmptyResponseError";
|
|
768
768
|
}
|
|
769
769
|
};
|
|
770
|
+
var ModelOutputLimitError = class extends Error {
|
|
771
|
+
constructor(limit) {
|
|
772
|
+
super(`Model output exceeded the ${limit}-character safety limit.`);
|
|
773
|
+
this.limit = limit;
|
|
774
|
+
this.name = "ModelOutputLimitError";
|
|
775
|
+
}
|
|
776
|
+
limit;
|
|
777
|
+
code = "model_output_limit";
|
|
778
|
+
};
|
|
770
779
|
var LoopGuard = {
|
|
771
780
|
/** Returns abort result if signal is aborted */
|
|
772
781
|
checkAbort(signal) {
|
|
@@ -778,6 +787,7 @@ var LoopGuard = {
|
|
|
778
787
|
};
|
|
779
788
|
|
|
780
789
|
// src/loop/stream-collector.ts
|
|
790
|
+
var MAX_STREAMED_OUTPUT_CHARACTERS = 1024 * 1024;
|
|
781
791
|
async function invokeModel(input) {
|
|
782
792
|
const events = input.config.stream(input.request, { signal: input.config.signal });
|
|
783
793
|
const result = await collectStreamResult({
|
|
@@ -811,7 +821,22 @@ async function collectStreamResult(input) {
|
|
|
811
821
|
let lastPartial;
|
|
812
822
|
let stopReason;
|
|
813
823
|
let doneResponse;
|
|
824
|
+
let streamedOutputCharacters = 0;
|
|
825
|
+
const toolCallsWithDeltas = /* @__PURE__ */ new Set();
|
|
814
826
|
for await (const event of input.events) {
|
|
827
|
+
if (event.type === "text_delta") {
|
|
828
|
+
streamedOutputCharacters += event.text.length;
|
|
829
|
+
} else if (event.type === "thinking_delta") {
|
|
830
|
+
streamedOutputCharacters += event.thinking.length;
|
|
831
|
+
} else if (event.type === "tool_call_delta") {
|
|
832
|
+
streamedOutputCharacters += event.arguments.length;
|
|
833
|
+
toolCallsWithDeltas.add(event.id);
|
|
834
|
+
} else if (event.type === "tool_call_end" && !toolCallsWithDeltas.has(event.id)) {
|
|
835
|
+
streamedOutputCharacters += event.arguments.length;
|
|
836
|
+
}
|
|
837
|
+
if (streamedOutputCharacters > MAX_STREAMED_OUTPUT_CHARACTERS) {
|
|
838
|
+
throw new ModelOutputLimitError(MAX_STREAMED_OUTPUT_CHARACTERS);
|
|
839
|
+
}
|
|
815
840
|
const abortResult2 = LoopGuard.checkAbort(input.config.signal);
|
|
816
841
|
if (abortResult2.stopReason !== "none") {
|
|
817
842
|
if (activeMessageId) {
|
|
@@ -3816,6 +3841,7 @@ var TransientRunEventHub = class {
|
|
|
3816
3841
|
// src/runtime/durable-runtime.ts
|
|
3817
3842
|
var DEFAULT_CONCURRENCY = 10;
|
|
3818
3843
|
var DEFAULT_POLL_MS = 25;
|
|
3844
|
+
var MAX_CONSUMER_IDLE_POLL_MS = 250;
|
|
3819
3845
|
var OWNER_LEASE_MS = 3e4;
|
|
3820
3846
|
var OWNER_RENEWAL_MS = 1e4;
|
|
3821
3847
|
var AgentRuntime = class _AgentRuntime {
|
|
@@ -4218,6 +4244,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
4218
4244
|
let cursor = registration.cursor;
|
|
4219
4245
|
const waterline = cursorSequence(registration.waterline);
|
|
4220
4246
|
let caughtUp = false;
|
|
4247
|
+
let pollMs = DEFAULT_POLL_MS;
|
|
4221
4248
|
while (!subscription.controller.signal.aborted && !this.closed) {
|
|
4222
4249
|
const events = await this.owned.listEvents(cursor ? { after: cursor } : {});
|
|
4223
4250
|
for (const event of events) {
|
|
@@ -4243,7 +4270,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
4243
4270
|
caughtUp = true;
|
|
4244
4271
|
subscription.caughtUp.resolve();
|
|
4245
4272
|
}
|
|
4246
|
-
|
|
4273
|
+
pollMs = events.length === 0 ? Math.min(MAX_CONSUMER_IDLE_POLL_MS, pollMs * 2) : DEFAULT_POLL_MS;
|
|
4274
|
+
await delay(pollMs);
|
|
4247
4275
|
}
|
|
4248
4276
|
if (!caughtUp) subscription.caughtUp.resolve();
|
|
4249
4277
|
}
|
|
@@ -4492,17 +4520,17 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
4492
4520
|
};
|
|
4493
4521
|
return new MemoryOwnedStore(this, clone(this.owner));
|
|
4494
4522
|
}
|
|
4495
|
-
assertOwner(lease) {
|
|
4523
|
+
assertOwner(lease, requireLive = true) {
|
|
4496
4524
|
const actual = this.owner;
|
|
4497
4525
|
if (!actual || actual.token !== lease.token || actual.epoch !== lease.epoch || actual.ownerId !== lease.ownerId) {
|
|
4498
4526
|
throw ownershipLost(lease, actual, "epoch_advanced");
|
|
4499
4527
|
}
|
|
4500
|
-
if (Date.parse(actual.expiresAt) <= Date.now()) {
|
|
4528
|
+
if (requireLive && Date.parse(actual.expiresAt) <= Date.now()) {
|
|
4501
4529
|
throw ownershipLost(lease, actual, "expired");
|
|
4502
4530
|
}
|
|
4503
4531
|
}
|
|
4504
4532
|
renewOwner(lease, leaseMs) {
|
|
4505
|
-
this.assertOwner(lease);
|
|
4533
|
+
this.assertOwner(lease, false);
|
|
4506
4534
|
assertLeaseDuration(leaseMs);
|
|
4507
4535
|
this.owner.expiresAt = expiry(leaseMs);
|
|
4508
4536
|
return clone(this.owner);
|
|
@@ -4597,23 +4625,25 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
4597
4625
|
if ([...this.runs.values()].some((candidate) => candidate.agentId === run.agentId && candidate.id !== run.id && ["running", "input_required"].includes(candidate.state))) {
|
|
4598
4626
|
throw new RuntimeError("run_state_conflict", { runId: run.id, expected: ["queued"], actual: run.state });
|
|
4599
4627
|
}
|
|
4600
|
-
const messageId = input.messageId ?? createId("msg");
|
|
4601
4628
|
if (run.pinnedConfigToken && input.configToken && run.pinnedConfigToken !== input.configToken) {
|
|
4602
4629
|
throw new RuntimeError("run_state_conflict", { runId: run.id, expected: ["queued"], actual: run.state });
|
|
4603
4630
|
}
|
|
4604
4631
|
if (!run.pinnedConfigToken && input.configToken) run.pinnedConfigToken = input.configToken;
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4632
|
+
let message;
|
|
4633
|
+
if (!run.checkpoint) {
|
|
4634
|
+
const userInput = normalizeUserInput(run.input);
|
|
4635
|
+
message = {
|
|
4636
|
+
id: input.messageId ?? createId("msg"),
|
|
4637
|
+
agentId: run.agentId,
|
|
4638
|
+
runId: run.id,
|
|
4639
|
+
role: "user",
|
|
4640
|
+
content: userInputContent(userInput),
|
|
4641
|
+
...userInputMetadata(userInput) ? { metadata: clone(userInputMetadata(userInput)) } : {},
|
|
4642
|
+
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
4643
|
+
createdAt: createTimestamp()
|
|
4644
|
+
};
|
|
4645
|
+
this.messages.set(message.id, message);
|
|
4646
|
+
}
|
|
4617
4647
|
const execution = {
|
|
4618
4648
|
runId: run.id,
|
|
4619
4649
|
ownerEpoch: lease.epoch,
|
|
@@ -4623,7 +4653,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
4623
4653
|
run.execution = execution;
|
|
4624
4654
|
run.revision += 1;
|
|
4625
4655
|
run.updatedAt = createTimestamp();
|
|
4626
|
-
this.appendMessage(run, message);
|
|
4656
|
+
if (message) this.appendMessage(run, message);
|
|
4627
4657
|
this.appendTransition(run, "queued", "running");
|
|
4628
4658
|
const result = { run: clone(run), execution: clone(execution), history: this.history(run.agentId, run.agentSequence) };
|
|
4629
4659
|
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
@@ -5497,7 +5527,28 @@ var SqliteStore = class {
|
|
|
5497
5527
|
return this.invoke(lease, (store, current) => store.listRuns(current, input), false);
|
|
5498
5528
|
}
|
|
5499
5529
|
async listEvents(lease, input = {}) {
|
|
5500
|
-
|
|
5530
|
+
this.assertOpen();
|
|
5531
|
+
return this.readTransaction(() => {
|
|
5532
|
+
this.requireMatchingOwner(lease, true);
|
|
5533
|
+
const after = input.after ? parseEventCursor(lease, input.after) : 0;
|
|
5534
|
+
if (input.after) {
|
|
5535
|
+
const latest = this.database.query(
|
|
5536
|
+
"SELECT payload_json FROM run_events ORDER BY sequence DESC LIMIT 1"
|
|
5537
|
+
).get();
|
|
5538
|
+
const waterline = latest ? parseEventCursor(
|
|
5539
|
+
lease,
|
|
5540
|
+
JSON.parse(latest.payload_json).cursor
|
|
5541
|
+
) : 0;
|
|
5542
|
+
if (after > waterline) {
|
|
5543
|
+
throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "beyond_waterline" });
|
|
5544
|
+
}
|
|
5545
|
+
if (after === waterline) return [];
|
|
5546
|
+
}
|
|
5547
|
+
const rows = this.database.query(
|
|
5548
|
+
"SELECT payload_json FROM run_events ORDER BY sequence LIMIT -1 OFFSET ?"
|
|
5549
|
+
).all(after);
|
|
5550
|
+
return rows.map((row) => JSON.parse(row.payload_json));
|
|
5551
|
+
});
|
|
5501
5552
|
}
|
|
5502
5553
|
async openConsumer(lease, consumerId) {
|
|
5503
5554
|
return this.invoke(lease, (store, current) => store.openConsumer(current, consumerId), false);
|
|
@@ -5509,7 +5560,7 @@ var SqliteStore = class {
|
|
|
5509
5560
|
this.assertOpen();
|
|
5510
5561
|
assertOwnerInput(lease.ownerId, leaseMs);
|
|
5511
5562
|
return this.immediateTransaction(() => {
|
|
5512
|
-
const row = this.requireMatchingOwner(lease,
|
|
5563
|
+
const row = this.requireMatchingOwner(lease, false);
|
|
5513
5564
|
const expiresAt = Date.now() + leaseMs;
|
|
5514
5565
|
this.writeOwner({ ...row, expires_at: expiresAt });
|
|
5515
5566
|
return { ...lease, expiresAt: new Date(expiresAt).toISOString() };
|
|
@@ -5686,6 +5737,20 @@ var SqliteStore = class {
|
|
|
5686
5737
|
throw error;
|
|
5687
5738
|
}
|
|
5688
5739
|
}
|
|
5740
|
+
readTransaction(operation) {
|
|
5741
|
+
this.database.run("BEGIN");
|
|
5742
|
+
try {
|
|
5743
|
+
const result = operation();
|
|
5744
|
+
this.database.run("COMMIT");
|
|
5745
|
+
return result;
|
|
5746
|
+
} catch (error) {
|
|
5747
|
+
try {
|
|
5748
|
+
this.database.run("ROLLBACK");
|
|
5749
|
+
} catch {
|
|
5750
|
+
}
|
|
5751
|
+
throw error;
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5689
5754
|
assertOpen() {
|
|
5690
5755
|
if (this.closed) throw new RuntimeError("runtime_closed", null);
|
|
5691
5756
|
}
|
|
@@ -5774,6 +5839,19 @@ function ownerLease(row) {
|
|
|
5774
5839
|
expiresAt: new Date(row.expires_at).toISOString()
|
|
5775
5840
|
};
|
|
5776
5841
|
}
|
|
5842
|
+
function parseEventCursor(lease, cursor) {
|
|
5843
|
+
const value = String(cursor);
|
|
5844
|
+
const separator = value.lastIndexOf(":");
|
|
5845
|
+
const incarnation = separator < 0 ? "" : value.slice(0, separator);
|
|
5846
|
+
const sequence = separator < 0 ? "" : value.slice(separator + 1);
|
|
5847
|
+
const token = String(lease.token);
|
|
5848
|
+
const ownerSuffix = `:${lease.epoch}:${lease.ownerId}`;
|
|
5849
|
+
const expectedIncarnation = token.endsWith(ownerSuffix) ? token.slice(0, -ownerSuffix.length) : "";
|
|
5850
|
+
if (incarnation !== expectedIncarnation || !/^\d+$/.test(sequence)) {
|
|
5851
|
+
throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "wrong_store" });
|
|
5852
|
+
}
|
|
5853
|
+
return Number(sequence);
|
|
5854
|
+
}
|
|
5777
5855
|
function ownershipLost2(lease, row) {
|
|
5778
5856
|
return new RuntimeError("runtime_ownership_lost", {
|
|
5779
5857
|
reason: row.epoch > lease.epoch ? "epoch_advanced" : row.owner_id ? "released" : "released",
|