@rowan-agent/agent 0.9.12 → 0.9.14
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 +7 -1
- package/dist/index.js +74 -23
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1380,7 +1380,7 @@ type AgentConfiguration = Readonly<{
|
|
|
1380
1380
|
}>;
|
|
1381
1381
|
resourceView: ResourceView;
|
|
1382
1382
|
contexts?: readonly ContextCandidate[];
|
|
1383
|
-
/** Trusted Host-owned Contexts
|
|
1383
|
+
/** Trusted Host-owned Contexts rendered as durable user messages. */
|
|
1384
1384
|
additionalContexts?: readonly ContextCandidate[];
|
|
1385
1385
|
cwd?: string;
|
|
1386
1386
|
maxAttempts?: number;
|
|
@@ -1398,6 +1398,7 @@ type ConfigurationSnapshot = Readonly<{
|
|
|
1398
1398
|
refs: Readonly<Record<ResourceKind, readonly ResourceRef[]>>;
|
|
1399
1399
|
}>;
|
|
1400
1400
|
contexts: readonly ContextCandidate[];
|
|
1401
|
+
additionalContexts: readonly ContextCandidate[];
|
|
1401
1402
|
resourceView: ResourceView;
|
|
1402
1403
|
cwd?: string;
|
|
1403
1404
|
maxAttempts?: number;
|
|
@@ -1506,6 +1507,8 @@ type AgentConfig = Readonly<{
|
|
|
1506
1507
|
identity: string;
|
|
1507
1508
|
definition: AgentDefinition;
|
|
1508
1509
|
resources: AgentResources;
|
|
1510
|
+
/** Host-owned Contexts are rendered as durable user messages for a Run. */
|
|
1511
|
+
additionalContexts?: readonly ContextCandidate[];
|
|
1509
1512
|
cwd?: string;
|
|
1510
1513
|
maxAttempts?: number;
|
|
1511
1514
|
beforeToolCall?: BeforeToolCall;
|
|
@@ -1770,6 +1773,7 @@ interface OwnedStore {
|
|
|
1770
1773
|
executionId?: ExecutionId;
|
|
1771
1774
|
messageId?: MessageId;
|
|
1772
1775
|
configToken?: ConfigToken;
|
|
1776
|
+
inputContext?: UserInput;
|
|
1773
1777
|
}): Promise<RunClaim>;
|
|
1774
1778
|
failQueuedRun(input: {
|
|
1775
1779
|
runId: RunId;
|
|
@@ -2184,6 +2188,7 @@ declare class InMemoryStore implements DurableStore {
|
|
|
2184
2188
|
executionId?: ExecutionId;
|
|
2185
2189
|
messageId?: MessageId;
|
|
2186
2190
|
configToken?: ConfigToken;
|
|
2191
|
+
inputContext?: UserInput;
|
|
2187
2192
|
}): RunClaim;
|
|
2188
2193
|
failQueuedRun(lease: OwnerLease, input: {
|
|
2189
2194
|
runId: RunId;
|
|
@@ -2367,6 +2372,7 @@ declare class SqliteStore implements DurableStore {
|
|
|
2367
2372
|
executionId?: ExecutionId;
|
|
2368
2373
|
messageId?: MessageId;
|
|
2369
2374
|
configToken?: ConfigToken;
|
|
2375
|
+
inputContext?: UserInput;
|
|
2370
2376
|
}): Promise<RunClaim>;
|
|
2371
2377
|
failQueuedRun(lease: OwnerLease, input: {
|
|
2372
2378
|
runId: RunId;
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,9 @@ function buildContextDescription(contexts) {
|
|
|
46
46
|
lines.push("</agent_context>");
|
|
47
47
|
return lines.join("\n");
|
|
48
48
|
}
|
|
49
|
+
function buildAdditionalContextMessage(contexts) {
|
|
50
|
+
return buildContextDescription(contexts);
|
|
51
|
+
}
|
|
49
52
|
function formatResourceOutput(resource) {
|
|
50
53
|
const parts = [`<${resource.type} name="${escapeXml(resource.name)}" location="${escapeXml(resource.location)}">`];
|
|
51
54
|
if (resource.baseDir) {
|
|
@@ -2123,7 +2126,7 @@ function findLatestUserInputMessage(messages) {
|
|
|
2123
2126
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
2124
2127
|
const message = messages[index];
|
|
2125
2128
|
const kind = message.metadata?.kind;
|
|
2126
|
-
if (message.role === "user" && kind !== "phase_prompt" && kind !== "phase_input") {
|
|
2129
|
+
if (message.role === "user" && kind !== "phase_prompt" && kind !== "phase_input" && kind !== "host_context") {
|
|
2127
2130
|
return message;
|
|
2128
2131
|
}
|
|
2129
2132
|
}
|
|
@@ -3276,6 +3279,7 @@ function isContinuation(value) {
|
|
|
3276
3279
|
}
|
|
3277
3280
|
|
|
3278
3281
|
// src/runtime/contracts.ts
|
|
3282
|
+
var HOST_CONTEXT_MESSAGE_KIND = "host_context";
|
|
3279
3283
|
var THINKING_LEVELS = [
|
|
3280
3284
|
"off",
|
|
3281
3285
|
"minimal",
|
|
@@ -3298,7 +3302,7 @@ function thinkingLevelFromMessages(messages) {
|
|
|
3298
3302
|
if (message?.role !== "user") continue;
|
|
3299
3303
|
const metadata = message.metadata;
|
|
3300
3304
|
const kind = isRecord3(metadata) && typeof metadata.kind === "string" ? metadata.kind : void 0;
|
|
3301
|
-
if (kind === "phase_prompt" || kind === "phase_input") continue;
|
|
3305
|
+
if (kind === "phase_prompt" || kind === "phase_input" || kind === HOST_CONTEXT_MESSAGE_KIND) continue;
|
|
3302
3306
|
return thinkingLevelFromMetadata(metadata);
|
|
3303
3307
|
}
|
|
3304
3308
|
return void 0;
|
|
@@ -3352,6 +3356,9 @@ function normalizeUserInput(input) {
|
|
|
3352
3356
|
assertJsonValue(normalized, "input");
|
|
3353
3357
|
return normalized;
|
|
3354
3358
|
}
|
|
3359
|
+
function canonicalUserInput(input) {
|
|
3360
|
+
return canonicalJson(normalizeUserInput(input));
|
|
3361
|
+
}
|
|
3355
3362
|
function isAssistantMessage(value) {
|
|
3356
3363
|
return isRecord3(value) && hasOnlyKeys(value, ["id", "agentId", "runId", "messageRevision", "role", "content", "metadata", "sequenceWithinRun", "createdAt", "interrupted"]) && typeof value.id === "string" && typeof value.agentId === "string" && typeof value.runId === "string" && value.role === "assistant" && (value.messageRevision === void 0 || Number.isInteger(value.messageRevision) && value.messageRevision >= 0) && Number.isInteger(value.sequenceWithinRun) && value.sequenceWithinRun >= 0 && typeof value.createdAt === "string" && isAssistantContent(value.content) && (value.metadata === void 0 || isMetadata(value.metadata)) && (value.interrupted === void 0 || typeof value.interrupted === "boolean");
|
|
3357
3364
|
}
|
|
@@ -3378,6 +3385,12 @@ function assertAgentConfig(config) {
|
|
|
3378
3385
|
names.add(context.name);
|
|
3379
3386
|
assertJsonValue(context.value, `Context candidate "${context.name}" value`);
|
|
3380
3387
|
}
|
|
3388
|
+
for (const context of config.additionalContexts ?? []) {
|
|
3389
|
+
if (typeof context.name !== "string" || context.name.trim() === "") {
|
|
3390
|
+
throw new TypeError("Additional Context candidate name must be non-empty");
|
|
3391
|
+
}
|
|
3392
|
+
assertJsonValue(context.value, `Additional Context candidate "${context.name}" value`);
|
|
3393
|
+
}
|
|
3381
3394
|
}
|
|
3382
3395
|
function assertAgentConfigRequest(config) {
|
|
3383
3396
|
if (!isAgentConfiguration(config)) {
|
|
@@ -3545,7 +3558,17 @@ function snapshotConfig(config) {
|
|
|
3545
3558
|
})))
|
|
3546
3559
|
} : {}
|
|
3547
3560
|
});
|
|
3548
|
-
return Object.freeze({
|
|
3561
|
+
return Object.freeze({
|
|
3562
|
+
...config,
|
|
3563
|
+
definition,
|
|
3564
|
+
resources,
|
|
3565
|
+
...config.additionalContexts ? {
|
|
3566
|
+
additionalContexts: Object.freeze(config.additionalContexts.map((context) => Object.freeze({
|
|
3567
|
+
name: context.name,
|
|
3568
|
+
value: snapshotJsonValue(context.value)
|
|
3569
|
+
})))
|
|
3570
|
+
} : {}
|
|
3571
|
+
});
|
|
3549
3572
|
}
|
|
3550
3573
|
function snapshotPhaseRegistry(registry) {
|
|
3551
3574
|
const phases = /* @__PURE__ */ new Map();
|
|
@@ -5512,11 +5535,8 @@ function resolveConfigurationSnapshot(registry, input) {
|
|
|
5512
5535
|
}
|
|
5513
5536
|
const layer = input.definition.layer;
|
|
5514
5537
|
const selectedContexts = selectNamedResources(input.contexts ?? [], base.contexts, "Context");
|
|
5515
|
-
const
|
|
5516
|
-
const definition =
|
|
5517
|
-
applyDefinitionLayer(base, layer),
|
|
5518
|
-
contexts.slice(selectedContexts.length).map(({ name }) => name)
|
|
5519
|
-
);
|
|
5538
|
+
const additionalContexts = deduplicateContexts(input.additionalContexts ?? [], selectedContexts);
|
|
5539
|
+
const definition = applyDefinitionLayer(base, layer);
|
|
5520
5540
|
const tools = selectNamedResources(resolved.tools, definition.tools, "Tool");
|
|
5521
5541
|
const skills = mergeSkills(
|
|
5522
5542
|
selectNamedResources(resolved.skills, definition.skills, "Skill"),
|
|
@@ -5538,7 +5558,8 @@ function resolveConfigurationSnapshot(registry, input) {
|
|
|
5538
5558
|
phase: selectedRefs(resolved.refs.phase, [...phases?.phases.keys() ?? []])
|
|
5539
5559
|
}
|
|
5540
5560
|
},
|
|
5541
|
-
contexts,
|
|
5561
|
+
contexts: selectedContexts,
|
|
5562
|
+
additionalContexts,
|
|
5542
5563
|
resourceView: input.resourceView,
|
|
5543
5564
|
...input.cwd === void 0 ? {} : { cwd: input.cwd },
|
|
5544
5565
|
...input.maxAttempts === void 0 ? {} : { maxAttempts: input.maxAttempts },
|
|
@@ -5563,6 +5584,7 @@ function materializeConfigurationSnapshot(snapshot) {
|
|
|
5563
5584
|
],
|
|
5564
5585
|
resourceRevisions: snapshot.resources.revisions
|
|
5565
5586
|
},
|
|
5587
|
+
...snapshot.additionalContexts.length > 0 ? { additionalContexts: snapshot.additionalContexts } : {},
|
|
5566
5588
|
...snapshot.cwd === void 0 ? {} : { cwd: snapshot.cwd },
|
|
5567
5589
|
...snapshot.maxAttempts === void 0 ? {} : { maxAttempts: snapshot.maxAttempts },
|
|
5568
5590
|
..."stream" in snapshot && snapshot.stream ? { model: snapshot.model, stream: snapshot.stream } : { model: snapshot.model }
|
|
@@ -5580,9 +5602,9 @@ function applyDefinitionLayer(base, layer) {
|
|
|
5580
5602
|
...layer.phases === void 0 ? {} : { phases: intersectPhaseSelection(base.phases, layer.phases) }
|
|
5581
5603
|
};
|
|
5582
5604
|
}
|
|
5583
|
-
function
|
|
5584
|
-
const contexts = [
|
|
5585
|
-
const seen = new Set(
|
|
5605
|
+
function deduplicateContexts(additional, existing = []) {
|
|
5606
|
+
const contexts = [];
|
|
5607
|
+
const seen = new Set(existing.map(({ name }) => name));
|
|
5586
5608
|
for (const context of additional) {
|
|
5587
5609
|
if (seen.has(context.name)) continue;
|
|
5588
5610
|
seen.add(context.name);
|
|
@@ -5590,12 +5612,6 @@ function appendAdditionalContexts(selected, additional) {
|
|
|
5590
5612
|
}
|
|
5591
5613
|
return contexts;
|
|
5592
5614
|
}
|
|
5593
|
-
function addAdditionalContextNames(definition, names) {
|
|
5594
|
-
if (definition.contexts === void 0 || names.length === 0) return definition;
|
|
5595
|
-
const existing = new Set(definition.contexts);
|
|
5596
|
-
const additions = names.filter((name) => !existing.has(name));
|
|
5597
|
-
return additions.length === 0 ? definition : { ...definition, contexts: [...definition.contexts, ...additions] };
|
|
5598
|
-
}
|
|
5599
5615
|
function intersectNames(parent, layer, kind) {
|
|
5600
5616
|
if (parent === void 0) return [...layer];
|
|
5601
5617
|
const parentNames = new Set(parent);
|
|
@@ -6033,7 +6049,13 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6033
6049
|
}
|
|
6034
6050
|
}
|
|
6035
6051
|
const executionId = createId("exec");
|
|
6036
|
-
claim = await this.owned.claimRun({
|
|
6052
|
+
claim = await this.owned.claimRun({
|
|
6053
|
+
runId: run.id,
|
|
6054
|
+
expectedRevision: run.revision,
|
|
6055
|
+
executionId,
|
|
6056
|
+
configToken: token,
|
|
6057
|
+
...controlKind ? {} : { inputContext: additionalContextInput(config) }
|
|
6058
|
+
});
|
|
6037
6059
|
executionRevision = claim.run.revision;
|
|
6038
6060
|
const controller = new AbortController();
|
|
6039
6061
|
this.executions.set(run.id, { controller, executionId });
|
|
@@ -6502,6 +6524,12 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6502
6524
|
this.heartbeat.unref?.();
|
|
6503
6525
|
}
|
|
6504
6526
|
};
|
|
6527
|
+
function additionalContextInput(config) {
|
|
6528
|
+
const contexts = config.additionalContexts ?? [];
|
|
6529
|
+
if (contexts.length === 0) return void 0;
|
|
6530
|
+
const content = buildAdditionalContextMessage(contexts);
|
|
6531
|
+
return content.length === 0 ? void 0 : { content, metadata: { kind: HOST_CONTEXT_MESSAGE_KIND } };
|
|
6532
|
+
}
|
|
6505
6533
|
var DurableRun = class {
|
|
6506
6534
|
constructor(runtime, id) {
|
|
6507
6535
|
this.runtime = runtime;
|
|
@@ -7050,7 +7078,14 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7050
7078
|
this.assertOwner(lease);
|
|
7051
7079
|
const executionId = input.executionId ?? createId("exec");
|
|
7052
7080
|
const operationKey = `claim:${executionId}`;
|
|
7053
|
-
const
|
|
7081
|
+
const inputContext = input.inputContext === void 0 ? void 0 : normalizeUserInput(input.inputContext);
|
|
7082
|
+
const operationPayload = canonicalJson([
|
|
7083
|
+
input.runId,
|
|
7084
|
+
input.expectedRevision,
|
|
7085
|
+
input.messageId ?? null,
|
|
7086
|
+
input.configToken ?? null,
|
|
7087
|
+
inputContext ?? null
|
|
7088
|
+
]);
|
|
7054
7089
|
const replay = this.replayOperation(operationKey, operationPayload);
|
|
7055
7090
|
if (replay) return clone(replay);
|
|
7056
7091
|
const run = this.requireRun(input.runId);
|
|
@@ -7066,10 +7101,25 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7066
7101
|
throw new RuntimeError("run_state_conflict", { runId: run.id, expected: ["queued"], actual: run.state });
|
|
7067
7102
|
}
|
|
7068
7103
|
if (!run.pinnedConfigToken && input.configToken) run.pinnedConfigToken = input.configToken;
|
|
7069
|
-
|
|
7104
|
+
const committedMessages = [];
|
|
7105
|
+
const existingMessages = this.messagesForRun(run.id);
|
|
7106
|
+
if (inputContext && hasUserInput(inputContext) && !isControlRun(run) && !existingMessages.some((message) => message.role === "user" && message.metadata?.kind === HOST_CONTEXT_MESSAGE_KIND && canonicalUserInput({ content: message.content, metadata: message.metadata }) === canonicalUserInput(inputContext))) {
|
|
7107
|
+
const contextMessage = {
|
|
7108
|
+
id: createId("msg"),
|
|
7109
|
+
agentId: run.agentId,
|
|
7110
|
+
runId: run.id,
|
|
7111
|
+
role: "user",
|
|
7112
|
+
content: userInputContent(inputContext),
|
|
7113
|
+
...userInputMetadata(inputContext) ? { metadata: clone(userInputMetadata(inputContext)) } : {},
|
|
7114
|
+
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
7115
|
+
createdAt: createTimestamp()
|
|
7116
|
+
};
|
|
7117
|
+
this.messages.set(contextMessage.id, contextMessage);
|
|
7118
|
+
committedMessages.push(contextMessage);
|
|
7119
|
+
}
|
|
7070
7120
|
if (!run.checkpoint && !run.initialMessageId && (!isControlRun(run) || hasUserInput(run.input))) {
|
|
7071
7121
|
const userInput = normalizeUserInput(run.input);
|
|
7072
|
-
message = {
|
|
7122
|
+
const message = {
|
|
7073
7123
|
id: input.messageId ?? createId("msg"),
|
|
7074
7124
|
agentId: run.agentId,
|
|
7075
7125
|
runId: run.id,
|
|
@@ -7080,6 +7130,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7080
7130
|
createdAt: createTimestamp()
|
|
7081
7131
|
};
|
|
7082
7132
|
this.messages.set(message.id, message);
|
|
7133
|
+
committedMessages.push(message);
|
|
7083
7134
|
}
|
|
7084
7135
|
const execution = {
|
|
7085
7136
|
runId: run.id,
|
|
@@ -7090,7 +7141,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7090
7141
|
run.execution = execution;
|
|
7091
7142
|
run.revision += 1;
|
|
7092
7143
|
run.updatedAt = createTimestamp();
|
|
7093
|
-
|
|
7144
|
+
for (const message of committedMessages) this.appendMessage(run, message);
|
|
7094
7145
|
this.appendTransition(run, "queued", "running");
|
|
7095
7146
|
const result = { run: clone(run), execution: clone(execution), history: this.activeHistory(run.agentId, run.agentSequence) };
|
|
7096
7147
|
this.writeOperationReceipt(operationKey, operationPayload, result);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rowan-agent/agent",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.14",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"build": "tsup && bun scripts/check-public-interface.ts"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@rowan-agent/models": "0.6.
|
|
26
|
+
"@rowan-agent/models": "0.6.7",
|
|
27
27
|
"jiti": "2.7.0",
|
|
28
28
|
"typebox": "^1.0.0",
|
|
29
29
|
"yaml": "^2.7.0"
|