@rowan-agent/agent 0.20.1 → 0.21.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/dist/index.d.ts +30 -3
- package/dist/index.js +458 -121
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _rowan_agent_models from '@rowan-agent/models';
|
|
2
|
-
import { ContentBlock,
|
|
2
|
+
import { ContentBlock, ModelRef, LlmTokenUsage, LlmContentPart, ScopeRef, ToolCallStatus, JsonValue as JsonValue$1, ToolProgress, ToolCallContent, ToolCallLocation, JsonObject as JsonObject$1, ToolKind, ModelConfig, StreamFn, ToolAnnotations, ThinkingLevel, ToolCall as ToolCall$1, ToolCallUpdate } from '@rowan-agent/models';
|
|
3
3
|
export { ModelConfig, ModelRef, ProviderCallContext, ProviderConfig, ProviderModelConfig, ProviderStreamFn, ScopeRef, StreamFn, ThinkingLevel, ToolAnnotations, ToolCall, ToolCallContent, ToolCallLocation, ToolCallOptions, ToolCallOutcome, ToolCallStatus, ToolCallUpdate, ToolDefinitionSummary, ToolKind, ToolProgress } from '@rowan-agent/models';
|
|
4
4
|
import Type from 'typebox';
|
|
5
5
|
|
|
@@ -8,6 +8,8 @@ type ModelInvokeOutput = {
|
|
|
8
8
|
contentBlocks: ContentBlock[];
|
|
9
9
|
toolCalls: ToolCall[];
|
|
10
10
|
stopReason?: string;
|
|
11
|
+
model?: ModelRef;
|
|
12
|
+
usage?: LlmTokenUsage;
|
|
11
13
|
};
|
|
12
14
|
/** Snapshot of phase-level context for restore */
|
|
13
15
|
type PhaseContextSnapshot = {
|
|
@@ -27,7 +29,10 @@ type PhaseExecution = {
|
|
|
27
29
|
}): Promise<ModelInvokeOutput>;
|
|
28
30
|
reportStatus(status: PhaseStatus): Promise<void>;
|
|
29
31
|
executeTool(context: AgentContext, toolCall: ToolCall): Promise<ToolResult>;
|
|
30
|
-
executeTools(context: AgentContext, toolCalls: readonly ToolCall[], contentBlocks?: readonly ContentBlock[]
|
|
32
|
+
executeTools(context: AgentContext, toolCalls: readonly ToolCall[], contentBlocks?: readonly ContentBlock[], meta?: {
|
|
33
|
+
model?: ModelRef;
|
|
34
|
+
usage?: LlmTokenUsage;
|
|
35
|
+
}): Promise<readonly ToolResult[]>;
|
|
31
36
|
interaction: RunInteractionDriver;
|
|
32
37
|
/** Message lifecycle manager for streaming updates from programmatic phases */
|
|
33
38
|
messages: PhaseMessageManager;
|
|
@@ -45,7 +50,10 @@ type PhaseMessageManager = {
|
|
|
45
50
|
/** Replace the active message content with model-native content parts */
|
|
46
51
|
replaceContent(messageId: string, content: string | LlmContentPart[]): void;
|
|
47
52
|
/** End the message stream, appends to transcript */
|
|
48
|
-
end(messageId: string
|
|
53
|
+
end(messageId: string, meta?: {
|
|
54
|
+
model?: ModelRef;
|
|
55
|
+
usage?: LlmTokenUsage;
|
|
56
|
+
}): Promise<void>;
|
|
49
57
|
/** Drop an unstarted stream that produced no content. */
|
|
50
58
|
discard(messageId: string): void;
|
|
51
59
|
};
|
|
@@ -1078,6 +1086,8 @@ interface OwnedStore {
|
|
|
1078
1086
|
locations?: ToolCallLocation[];
|
|
1079
1087
|
content?: ToolCallContent[];
|
|
1080
1088
|
_meta?: JsonObject;
|
|
1089
|
+
model?: ModelRef;
|
|
1090
|
+
usage?: LlmTokenUsage;
|
|
1081
1091
|
}): Promise<ToolCommit>;
|
|
1082
1092
|
reserveToolCalls(input: {
|
|
1083
1093
|
runId: RunId;
|
|
@@ -1087,6 +1097,8 @@ interface OwnedStore {
|
|
|
1087
1097
|
calls: readonly ToolCallReservation[];
|
|
1088
1098
|
/** The model response's blocks, so the request message keeps what preceded the Tool Calls. */
|
|
1089
1099
|
contentBlocks?: readonly ContentBlock[];
|
|
1100
|
+
model?: ModelRef;
|
|
1101
|
+
usage?: LlmTokenUsage;
|
|
1090
1102
|
}): Promise<ToolBatchCommit>;
|
|
1091
1103
|
startToolCall(input: {
|
|
1092
1104
|
runId: RunId;
|
|
@@ -1163,6 +1175,9 @@ type AgentRuntimeOptions = Readonly<{
|
|
|
1163
1175
|
concurrency?: number;
|
|
1164
1176
|
bootstrap?: (registry: RuntimeBootstrapRegistry) => void | Promise<void>;
|
|
1165
1177
|
host?: ExtensionHost;
|
|
1178
|
+
sessionFiles?: Readonly<{
|
|
1179
|
+
dir: string;
|
|
1180
|
+
}>;
|
|
1166
1181
|
/** @internal Private / testing parameter to override retry delay */
|
|
1167
1182
|
retryDelayMs?: number;
|
|
1168
1183
|
}>;
|
|
@@ -2088,6 +2103,8 @@ type AssistantMessage = MessageBase & Readonly<{
|
|
|
2088
2103
|
role: "assistant";
|
|
2089
2104
|
content: AssistantContent;
|
|
2090
2105
|
interrupted?: boolean;
|
|
2106
|
+
model?: ModelRef;
|
|
2107
|
+
usage?: LlmTokenUsage;
|
|
2091
2108
|
}>;
|
|
2092
2109
|
type ToolMessage = MessageBase & Readonly<{
|
|
2093
2110
|
role: "tool";
|
|
@@ -2343,6 +2360,8 @@ type AgentMessage = {
|
|
|
2343
2360
|
phase?: string;
|
|
2344
2361
|
};
|
|
2345
2362
|
contexts?: readonly ContextCandidate[];
|
|
2363
|
+
model?: ModelRef;
|
|
2364
|
+
usage?: LlmTokenUsage;
|
|
2346
2365
|
};
|
|
2347
2366
|
type Skill = {
|
|
2348
2367
|
name: string;
|
|
@@ -2754,6 +2773,8 @@ declare class InMemoryStore implements DurableStore {
|
|
|
2754
2773
|
args: JsonValue;
|
|
2755
2774
|
toolCallId?: ToolCallId;
|
|
2756
2775
|
providerToolCallId?: string;
|
|
2776
|
+
model?: ModelRef;
|
|
2777
|
+
usage?: LlmTokenUsage;
|
|
2757
2778
|
}): ToolCommit;
|
|
2758
2779
|
reserveToolCalls(lease: OwnerLease, input: {
|
|
2759
2780
|
runId: RunId;
|
|
@@ -2763,6 +2784,8 @@ declare class InMemoryStore implements DurableStore {
|
|
|
2763
2784
|
calls: readonly ToolCallReservation[];
|
|
2764
2785
|
/** The model response's blocks, so the request message keeps what preceded the Tool Calls. */
|
|
2765
2786
|
contentBlocks?: readonly ContentBlock[];
|
|
2787
|
+
model?: ModelRef;
|
|
2788
|
+
usage?: LlmTokenUsage;
|
|
2766
2789
|
}): ToolBatchCommit;
|
|
2767
2790
|
startToolCall(lease: OwnerLease, input: {
|
|
2768
2791
|
runId: RunId;
|
|
@@ -3018,6 +3041,8 @@ declare class SqliteStore implements DurableStore {
|
|
|
3018
3041
|
locations?: ToolCallLocation[];
|
|
3019
3042
|
content?: ToolCallContent[];
|
|
3020
3043
|
_meta?: JsonObject;
|
|
3044
|
+
model?: _rowan_agent_models.ModelRef;
|
|
3045
|
+
usage?: _rowan_agent_models.LlmTokenUsage;
|
|
3021
3046
|
}): Promise<ToolCommit>;
|
|
3022
3047
|
reserveToolCalls(lease: OwnerLease, input: {
|
|
3023
3048
|
runId: RunId;
|
|
@@ -3026,6 +3051,8 @@ declare class SqliteStore implements DurableStore {
|
|
|
3026
3051
|
requestMessageId: MessageId;
|
|
3027
3052
|
calls: readonly ToolCallReservation[];
|
|
3028
3053
|
contentBlocks?: readonly ContentBlock[];
|
|
3054
|
+
model?: _rowan_agent_models.ModelRef;
|
|
3055
|
+
usage?: _rowan_agent_models.LlmTokenUsage;
|
|
3029
3056
|
}): Promise<ToolBatchCommit>;
|
|
3030
3057
|
startToolCall(lease: OwnerLease, input: {
|
|
3031
3058
|
runId: RunId;
|
package/dist/index.js
CHANGED
|
@@ -944,7 +944,7 @@ function createRuntimeCoreTools(input = {}) {
|
|
|
944
944
|
// src/runtime/durable-runtime.ts
|
|
945
945
|
import { mkdir as mkdir2, chmod as chmod2, writeFile as writeFile2 } from "fs/promises";
|
|
946
946
|
import { randomUUID } from "crypto";
|
|
947
|
-
import { join as
|
|
947
|
+
import { join as join6 } from "path";
|
|
948
948
|
import { createModelStream, isValidToolProgress } from "@rowan-agent/models";
|
|
949
949
|
|
|
950
950
|
// src/utils.ts
|
|
@@ -1378,46 +1378,11 @@ var LoopGuard = {
|
|
|
1378
1378
|
// src/loop/stream-collector.ts
|
|
1379
1379
|
var MAX_STREAMED_OUTPUT_CHARACTERS = 1024 * 1024;
|
|
1380
1380
|
async function invokeModel(input) {
|
|
1381
|
-
const baseContext = input.callContext ?? {
|
|
1382
|
-
signal: input.config.signal ?? new AbortController().signal,
|
|
1383
|
-
run: {
|
|
1384
|
-
id: input.config.execution.runId,
|
|
1385
|
-
agentId: input.config.execution.agentId,
|
|
1386
|
-
scope: input.config.execution.scope ?? [],
|
|
1387
|
-
cwd: input.config.execution.cwd ?? input.config.context.cwd ?? ""
|
|
1388
|
-
},
|
|
1389
|
-
interact: async (request) => {
|
|
1390
|
-
const handler = input.config.runtime?.interact ?? input.config.interact;
|
|
1391
|
-
if (!handler) {
|
|
1392
|
-
throw new Error("Run interactions are not supported in this runtime.");
|
|
1393
|
-
}
|
|
1394
|
-
return handler(request);
|
|
1395
|
-
},
|
|
1396
|
-
tools: {
|
|
1397
|
-
list: () => {
|
|
1398
|
-
return input.config.context.tools.map((t) => ({
|
|
1399
|
-
name: t.name,
|
|
1400
|
-
description: t.description,
|
|
1401
|
-
parameters: t.parameters,
|
|
1402
|
-
...t._meta !== void 0 ? { _meta: t._meta } : {}
|
|
1403
|
-
}));
|
|
1404
|
-
},
|
|
1405
|
-
call: async (_name, _args, _options) => {
|
|
1406
|
-
throw new Error("Tool calling is not available in standalone stream collector without callContext.");
|
|
1407
|
-
},
|
|
1408
|
-
report: (update) => {
|
|
1409
|
-
input.config.onToolReport?.({
|
|
1410
|
-
runId: input.config.execution.runId,
|
|
1411
|
-
update
|
|
1412
|
-
});
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
};
|
|
1416
1381
|
const position = { contentIndex: 0 };
|
|
1417
1382
|
const callContext = {
|
|
1418
|
-
...
|
|
1383
|
+
...input.callContext,
|
|
1419
1384
|
tools: {
|
|
1420
|
-
...
|
|
1385
|
+
...input.callContext.tools,
|
|
1421
1386
|
report: (update) => {
|
|
1422
1387
|
input.config.onToolReport?.({
|
|
1423
1388
|
runId: input.config.execution.runId,
|
|
@@ -1436,7 +1401,8 @@ async function invokeModel(input) {
|
|
|
1436
1401
|
metadataPhase: input.phaseId,
|
|
1437
1402
|
output: input.output,
|
|
1438
1403
|
onThinkingDelta: input.onThinkingDelta,
|
|
1439
|
-
onToolCallDelta: input.onToolCallDelta
|
|
1404
|
+
onToolCallDelta: input.onToolCallDelta,
|
|
1405
|
+
model: input.request.model
|
|
1440
1406
|
});
|
|
1441
1407
|
const response = result.doneResponse ?? {
|
|
1442
1408
|
content: result.text,
|
|
@@ -1452,6 +1418,8 @@ async function invokeModel(input) {
|
|
|
1452
1418
|
contentBlocks: result.contentBlocks,
|
|
1453
1419
|
toolCalls: result.toolCalls,
|
|
1454
1420
|
stopReason: result.stopReason,
|
|
1421
|
+
model: input.request.model,
|
|
1422
|
+
usage: response.usage,
|
|
1455
1423
|
transcript: {
|
|
1456
1424
|
request: input.request,
|
|
1457
1425
|
response
|
|
@@ -1575,7 +1543,7 @@ async function collectStreamResult(input) {
|
|
|
1575
1543
|
input.message.replaceContent(activeMessageId, contentBlocksToMessageContent(contentBlocks2));
|
|
1576
1544
|
}
|
|
1577
1545
|
if (persistAssistant && activeMessageId) {
|
|
1578
|
-
if (hasContent2) await input.message.end(activeMessageId);
|
|
1546
|
+
if (hasContent2) await input.message.end(activeMessageId, { model: input.model, usage: event.response?.usage });
|
|
1579
1547
|
else input.message.discard(activeMessageId);
|
|
1580
1548
|
activeMessageId = void 0;
|
|
1581
1549
|
}
|
|
@@ -1584,13 +1552,13 @@ async function collectStreamResult(input) {
|
|
|
1584
1552
|
const abortResult = LoopGuard.checkAbort(input.config.signal);
|
|
1585
1553
|
if (abortResult.stopReason !== "none") {
|
|
1586
1554
|
if (persistAssistant && activeMessageId) {
|
|
1587
|
-
await input.message.end(activeMessageId);
|
|
1555
|
+
await input.message.end(activeMessageId, { model: input.model });
|
|
1588
1556
|
activeMessageId = void 0;
|
|
1589
1557
|
}
|
|
1590
1558
|
return { text: abortResult.message, contentBlocks: [], toolCalls: [], stopReason: "aborted" };
|
|
1591
1559
|
}
|
|
1592
1560
|
if (persistAssistant && activeMessageId) {
|
|
1593
|
-
await input.message.end(activeMessageId);
|
|
1561
|
+
await input.message.end(activeMessageId, { model: input.model, usage: doneResponse?.usage });
|
|
1594
1562
|
}
|
|
1595
1563
|
const hasContent = (lastPartial?.contentBlocks?.length ?? 0) > 0 || (doneResponse?.content?.length ?? 0) > 0 || (doneResponse?.toolCalls?.length ?? 0) > 0;
|
|
1596
1564
|
if (!hasContent && stopReason !== "error" && stopReason !== "aborted") {
|
|
@@ -2741,6 +2709,7 @@ function buildModelRequest(input, options) {
|
|
|
2741
2709
|
model: options?.model ?? { provider: "", id: "" },
|
|
2742
2710
|
...options?.thinkingLevel === void 0 ? {} : { thinkingLevel: options.thinkingLevel },
|
|
2743
2711
|
...options?.providerOptions === void 0 ? {} : { providerOptions: options.providerOptions },
|
|
2712
|
+
...options?.sessionId === void 0 ? {} : { sessionId: options.sessionId },
|
|
2744
2713
|
system: systemText,
|
|
2745
2714
|
messages,
|
|
2746
2715
|
tools: modelTools.length > 0 ? modelTools : void 0
|
|
@@ -3006,9 +2975,15 @@ function createMessageManager(context, onMessage, onMessageDelta) {
|
|
|
3006
2975
|
if (!active) return;
|
|
3007
2976
|
active.message.content = content;
|
|
3008
2977
|
},
|
|
3009
|
-
async end(messageId) {
|
|
2978
|
+
async end(messageId, meta) {
|
|
3010
2979
|
const active = activeMessages.get(messageId);
|
|
3011
2980
|
if (!active) return;
|
|
2981
|
+
if (meta?.model) {
|
|
2982
|
+
active.message.model = meta.model;
|
|
2983
|
+
}
|
|
2984
|
+
if (meta?.usage) {
|
|
2985
|
+
active.message.usage = meta.usage;
|
|
2986
|
+
}
|
|
3012
2987
|
if (!active.emitted && (active.message.content === "" || active.message.content.length === 0)) {
|
|
3013
2988
|
activeMessages.delete(messageId);
|
|
3014
2989
|
return;
|
|
@@ -3077,6 +3052,7 @@ async function executePhaseWithModel(ctx) {
|
|
|
3077
3052
|
};
|
|
3078
3053
|
let executableToolCalls;
|
|
3079
3054
|
let roundContentBlocks;
|
|
3055
|
+
let collected;
|
|
3080
3056
|
const checkpoint = ctx.execution.interaction.checkpoint();
|
|
3081
3057
|
if (checkpoint && typeof checkpoint === "object" && checkpoint.kind === "tool_call_suspension") {
|
|
3082
3058
|
const toolSuspension = checkpoint;
|
|
@@ -3089,7 +3065,7 @@ async function executePhaseWithModel(ctx) {
|
|
|
3089
3065
|
toolCalls: [...toolSuspension.toolCalls]
|
|
3090
3066
|
};
|
|
3091
3067
|
} else {
|
|
3092
|
-
|
|
3068
|
+
collected = await ctx.execution.invokeModel(roundContext);
|
|
3093
3069
|
output = {
|
|
3094
3070
|
message: collected.text,
|
|
3095
3071
|
phase: ctx.phase.name,
|
|
@@ -3122,7 +3098,13 @@ async function executePhaseWithModel(ctx) {
|
|
|
3122
3098
|
return output;
|
|
3123
3099
|
}
|
|
3124
3100
|
}
|
|
3125
|
-
const
|
|
3101
|
+
const currentModel = ctx.phase.model ?? ctx.config.model;
|
|
3102
|
+
const results = await ctx.execution.executeTools(
|
|
3103
|
+
roundContext,
|
|
3104
|
+
executableToolCalls,
|
|
3105
|
+
roundContentBlocks,
|
|
3106
|
+
{ model: currentModel, usage: collected?.usage }
|
|
3107
|
+
);
|
|
3126
3108
|
for (const result of results) {
|
|
3127
3109
|
const messageId = ctx.messageManager.start("tool", createToolResultContent(result), {
|
|
3128
3110
|
phase: ctx.phase.name
|
|
@@ -3676,7 +3658,9 @@ async function executeToolCalls(input) {
|
|
|
3676
3658
|
config: input.config,
|
|
3677
3659
|
toolCalls: input.toolCalls,
|
|
3678
3660
|
contentBlocks: input.contentBlocks,
|
|
3679
|
-
driver: input.driver
|
|
3661
|
+
driver: input.driver,
|
|
3662
|
+
model: input.model,
|
|
3663
|
+
usage: input.usage
|
|
3680
3664
|
});
|
|
3681
3665
|
if (results2.length !== input.toolCalls.length) throw new Error("Runtime returned an invalid Tool batch result");
|
|
3682
3666
|
return results2.map((result, index) => ({
|
|
@@ -3748,6 +3732,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3748
3732
|
appendSystemPrompt: phaseContext.appendSystemPrompt
|
|
3749
3733
|
}, {
|
|
3750
3734
|
model: phase.model ?? config.model,
|
|
3735
|
+
sessionId: config.execution.agentId,
|
|
3751
3736
|
...config.thinkingLevel === void 0 ? {} : { thinkingLevel: config.thinkingLevel },
|
|
3752
3737
|
...config.providerOptions === void 0 ? {} : { providerOptions: config.providerOptions }
|
|
3753
3738
|
});
|
|
@@ -3796,12 +3781,6 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3796
3781
|
};
|
|
3797
3782
|
const res = await executePhaseTool(phaseContext, toolCall, options2, true);
|
|
3798
3783
|
return res.ok ? { ok: true, content: res.content } : { ok: false, error: res.error ?? "Tool execution failed", ...res.content !== void 0 ? { content: res.content } : {} };
|
|
3799
|
-
},
|
|
3800
|
-
report: (update) => {
|
|
3801
|
-
config.onToolReport?.({
|
|
3802
|
-
runId: config.execution.runId,
|
|
3803
|
-
update
|
|
3804
|
-
});
|
|
3805
3784
|
}
|
|
3806
3785
|
}
|
|
3807
3786
|
};
|
|
@@ -3839,7 +3818,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3839
3818
|
await config.onPhaseStatus?.(phase.name, status);
|
|
3840
3819
|
},
|
|
3841
3820
|
executeTool: executePhaseTool,
|
|
3842
|
-
async executeTools(phaseContext, toolCalls, contentBlocks) {
|
|
3821
|
+
async executeTools(phaseContext, toolCalls, contentBlocks, meta) {
|
|
3843
3822
|
return runTurn(async () => {
|
|
3844
3823
|
const tools = phaseContext.tools.filter((tool) => tool.name !== PhaseRouteTool);
|
|
3845
3824
|
for (const toolCall of toolCalls) {
|
|
@@ -3857,7 +3836,9 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3857
3836
|
tools,
|
|
3858
3837
|
toolCalls,
|
|
3859
3838
|
contentBlocks,
|
|
3860
|
-
driver: interaction
|
|
3839
|
+
driver: interaction,
|
|
3840
|
+
model: meta?.model,
|
|
3841
|
+
usage: meta?.usage
|
|
3861
3842
|
});
|
|
3862
3843
|
for (const result of results) {
|
|
3863
3844
|
await toolExecutionManager.end(result.toolCallId, result.toolName, result, !result.ok);
|
|
@@ -4324,7 +4305,7 @@ function normalizeUserInput(input) {
|
|
|
4324
4305
|
return normalized;
|
|
4325
4306
|
}
|
|
4326
4307
|
function isAssistantMessage(value) {
|
|
4327
|
-
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");
|
|
4308
|
+
return isRecord3(value) && hasOnlyKeys(value, ["id", "agentId", "runId", "messageRevision", "role", "content", "metadata", "sequenceWithinRun", "createdAt", "interrupted", "model", "usage"]) && 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") && (value.model === void 0 || isRecord3(value.model) && typeof value.model.provider === "string" && typeof value.model.id === "string") && (value.usage === void 0 || isRecord3(value.usage));
|
|
4328
4309
|
}
|
|
4329
4310
|
function isToolResult(value) {
|
|
4330
4311
|
if (!isRecord3(value)) return false;
|
|
@@ -5040,7 +5021,9 @@ function projectAssistantMessage(message, agentId, runId, sequenceWithinRun, opt
|
|
|
5040
5021
|
sequenceWithinRun,
|
|
5041
5022
|
createdAt: message.createdAt,
|
|
5042
5023
|
...message.metadata ? { metadata: message.metadata } : {},
|
|
5043
|
-
...options.interrupted ? { interrupted: true } : {}
|
|
5024
|
+
...options.interrupted ? { interrupted: true } : {},
|
|
5025
|
+
...message.model ? { model: message.model } : {},
|
|
5026
|
+
...message.usage ? { usage: message.usage } : {}
|
|
5044
5027
|
};
|
|
5045
5028
|
}
|
|
5046
5029
|
function durableInterruptedAssistantContent(content) {
|
|
@@ -5292,6 +5275,333 @@ function fromLoopResult(result) {
|
|
|
5292
5275
|
};
|
|
5293
5276
|
}
|
|
5294
5277
|
|
|
5278
|
+
// src/runtime/session-files.ts
|
|
5279
|
+
import { appendFileSync, chmodSync, existsSync as existsSync3, mkdirSync, readFileSync } from "fs";
|
|
5280
|
+
import { dirname as dirname5, join as join3 } from "path";
|
|
5281
|
+
function toEpochMs(isoString) {
|
|
5282
|
+
if (!isoString) return Date.now();
|
|
5283
|
+
const ms = new Date(isoString).getTime();
|
|
5284
|
+
return Number.isNaN(ms) ? Date.now() : ms;
|
|
5285
|
+
}
|
|
5286
|
+
function isContentBlock(value) {
|
|
5287
|
+
if (!value || typeof value !== "object") return false;
|
|
5288
|
+
const candidate = value;
|
|
5289
|
+
if (candidate.type === "text" && typeof candidate.text === "string") return true;
|
|
5290
|
+
if (candidate.type === "image" && typeof candidate.data === "string" && typeof candidate.mimeType === "string") return true;
|
|
5291
|
+
return false;
|
|
5292
|
+
}
|
|
5293
|
+
function convertToolResultContent(content) {
|
|
5294
|
+
if (content === void 0 || content === null) {
|
|
5295
|
+
return [{ type: "text", text: "" }];
|
|
5296
|
+
}
|
|
5297
|
+
if (typeof content === "string") {
|
|
5298
|
+
return [{ type: "text", text: content }];
|
|
5299
|
+
}
|
|
5300
|
+
if (isContentBlock(content)) {
|
|
5301
|
+
return content.type === "image" ? [{ type: "image", data: content.data, mimeType: content.mimeType }] : [{ type: "text", text: content.text }];
|
|
5302
|
+
}
|
|
5303
|
+
if (Array.isArray(content)) {
|
|
5304
|
+
if (content.length > 0 && content.every(isContentBlock)) {
|
|
5305
|
+
return content.map(
|
|
5306
|
+
(item) => item.type === "image" ? { type: "image", data: item.data, mimeType: item.mimeType } : { type: "text", text: item.text }
|
|
5307
|
+
);
|
|
5308
|
+
}
|
|
5309
|
+
return [{ type: "text", text: JSON.stringify(content) }];
|
|
5310
|
+
}
|
|
5311
|
+
return [{ type: "text", text: JSON.stringify(content) }];
|
|
5312
|
+
}
|
|
5313
|
+
function convertUserContent(content) {
|
|
5314
|
+
if (typeof content === "string") return content;
|
|
5315
|
+
return content.map(
|
|
5316
|
+
(part) => part.type === "image" ? { type: "image", data: part.data, mimeType: part.mimeType } : { type: "text", text: part.text }
|
|
5317
|
+
);
|
|
5318
|
+
}
|
|
5319
|
+
function convertAssistantContent(content, onToolCall) {
|
|
5320
|
+
if (typeof content === "string") {
|
|
5321
|
+
return {
|
|
5322
|
+
parts: [{ type: "text", text: content }],
|
|
5323
|
+
hasToolCall: false
|
|
5324
|
+
};
|
|
5325
|
+
}
|
|
5326
|
+
let hasToolCall = false;
|
|
5327
|
+
const parts = [];
|
|
5328
|
+
for (const part of content) {
|
|
5329
|
+
if (part.type === "text") {
|
|
5330
|
+
parts.push({ type: "text", text: part.text });
|
|
5331
|
+
} else if (part.type === "thinking") {
|
|
5332
|
+
parts.push({
|
|
5333
|
+
type: "thinking",
|
|
5334
|
+
thinking: part.thinking,
|
|
5335
|
+
...part.signature ? { thinkingSignature: part.signature } : {}
|
|
5336
|
+
});
|
|
5337
|
+
} else if (part.type === "tool_use") {
|
|
5338
|
+
hasToolCall = true;
|
|
5339
|
+
const callId = part.providerToolCallId ?? part.toolCallId;
|
|
5340
|
+
onToolCall?.(callId, part.name, part.toolCallId);
|
|
5341
|
+
parts.push({
|
|
5342
|
+
type: "toolCall",
|
|
5343
|
+
id: callId,
|
|
5344
|
+
name: part.name,
|
|
5345
|
+
arguments: part.input
|
|
5346
|
+
});
|
|
5347
|
+
}
|
|
5348
|
+
}
|
|
5349
|
+
return { parts, hasToolCall };
|
|
5350
|
+
}
|
|
5351
|
+
async function getAgentCreatedAt(runtime, agentId) {
|
|
5352
|
+
let after;
|
|
5353
|
+
while (true) {
|
|
5354
|
+
const page = await runtime.listAgents(after ? { after, limit: 100 } : { limit: 100 });
|
|
5355
|
+
const agent = page.items.find((item) => item.id === agentId);
|
|
5356
|
+
if (agent) return agent.createdAt;
|
|
5357
|
+
if (!page.next) break;
|
|
5358
|
+
after = page.next;
|
|
5359
|
+
}
|
|
5360
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
5361
|
+
}
|
|
5362
|
+
async function getFirstRunCwd(runtime, agentId) {
|
|
5363
|
+
let after;
|
|
5364
|
+
while (true) {
|
|
5365
|
+
const page = await runtime.listRuns(after ? { agentId, after, limit: 100 } : { agentId, limit: 100 });
|
|
5366
|
+
for (const runSummary of page.items) {
|
|
5367
|
+
try {
|
|
5368
|
+
const snapshot = await runtime.run(runSummary.id).snapshot();
|
|
5369
|
+
if (snapshot.cwd && snapshot.cwd.trim().length > 0) {
|
|
5370
|
+
return snapshot.cwd;
|
|
5371
|
+
}
|
|
5372
|
+
} catch {
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5375
|
+
if (!page.next) break;
|
|
5376
|
+
after = page.next;
|
|
5377
|
+
}
|
|
5378
|
+
return "";
|
|
5379
|
+
}
|
|
5380
|
+
function writeSessionEntry(state, entry) {
|
|
5381
|
+
appendFileSync(state.filePath, `${JSON.stringify(entry)}
|
|
5382
|
+
`, { encoding: "utf8", mode: 384 });
|
|
5383
|
+
try {
|
|
5384
|
+
chmodSync(state.filePath, 384);
|
|
5385
|
+
} catch {
|
|
5386
|
+
}
|
|
5387
|
+
state.knownEntryIds.add(entry.id);
|
|
5388
|
+
state.entryIdToParentId.set(entry.id, entry.parentId);
|
|
5389
|
+
state.lastEntryId = entry.id;
|
|
5390
|
+
}
|
|
5391
|
+
async function startSessionFilesConsumer(runtime, options) {
|
|
5392
|
+
const agentStates = /* @__PURE__ */ new Map();
|
|
5393
|
+
async function getOrInitState(agentId) {
|
|
5394
|
+
let state = agentStates.get(agentId);
|
|
5395
|
+
if (state) return state;
|
|
5396
|
+
const createdAt = await getAgentCreatedAt(runtime, agentId);
|
|
5397
|
+
const cwd = await getFirstRunCwd(runtime, agentId);
|
|
5398
|
+
const folderName = cwd.length > 0 ? `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--` : "--unknown--";
|
|
5399
|
+
const fileTimestamp = createdAt.replace(/[:.]/g, "-");
|
|
5400
|
+
const fileName = `${fileTimestamp}_${agentId}.jsonl`;
|
|
5401
|
+
const filePath = join3(options.dir, folderName, fileName);
|
|
5402
|
+
const knownEntryIds = /* @__PURE__ */ new Set();
|
|
5403
|
+
let lastEntryId = null;
|
|
5404
|
+
let lastModel;
|
|
5405
|
+
const entryIdToParentId = /* @__PURE__ */ new Map();
|
|
5406
|
+
const toolCallIdToName = /* @__PURE__ */ new Map();
|
|
5407
|
+
const writeHeader = () => {
|
|
5408
|
+
const header = { type: "session", version: 3, id: agentId, timestamp: createdAt, cwd };
|
|
5409
|
+
appendFileSync(filePath, `${JSON.stringify(header)}
|
|
5410
|
+
`, { encoding: "utf8", mode: 384 });
|
|
5411
|
+
};
|
|
5412
|
+
mkdirSync(dirname5(filePath), { recursive: true, mode: 448 });
|
|
5413
|
+
if (existsSync3(filePath)) {
|
|
5414
|
+
const content = readFileSync(filePath, "utf8");
|
|
5415
|
+
if (content.trim().length === 0) {
|
|
5416
|
+
writeHeader();
|
|
5417
|
+
} else {
|
|
5418
|
+
for (const line of content.split("\n")) {
|
|
5419
|
+
const trimmed = line.trim();
|
|
5420
|
+
if (!trimmed) continue;
|
|
5421
|
+
let parsed;
|
|
5422
|
+
try {
|
|
5423
|
+
parsed = JSON.parse(trimmed);
|
|
5424
|
+
} catch {
|
|
5425
|
+
continue;
|
|
5426
|
+
}
|
|
5427
|
+
if (parsed.type === "session") continue;
|
|
5428
|
+
if (typeof parsed.id === "string") {
|
|
5429
|
+
knownEntryIds.add(parsed.id);
|
|
5430
|
+
entryIdToParentId.set(parsed.id, parsed.parentId ?? null);
|
|
5431
|
+
lastEntryId = parsed.id;
|
|
5432
|
+
}
|
|
5433
|
+
if (parsed.type === "model_change" && typeof parsed.provider === "string" && typeof parsed.modelId === "string") {
|
|
5434
|
+
lastModel = { provider: parsed.provider, modelId: parsed.modelId };
|
|
5435
|
+
}
|
|
5436
|
+
if (parsed.type === "message" && parsed.message?.role === "assistant" && Array.isArray(parsed.message.content)) {
|
|
5437
|
+
for (const part of parsed.message.content) {
|
|
5438
|
+
if (part && part.type === "toolCall" && typeof part.id === "string" && typeof part.name === "string") {
|
|
5439
|
+
toolCallIdToName.set(part.id, part.name);
|
|
5440
|
+
}
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
}
|
|
5444
|
+
}
|
|
5445
|
+
} else {
|
|
5446
|
+
writeHeader();
|
|
5447
|
+
}
|
|
5448
|
+
state = {
|
|
5449
|
+
filePath,
|
|
5450
|
+
knownEntryIds,
|
|
5451
|
+
lastEntryId,
|
|
5452
|
+
entryIdToParentId,
|
|
5453
|
+
toolCallIdToName,
|
|
5454
|
+
...lastModel ? { lastModel } : {}
|
|
5455
|
+
};
|
|
5456
|
+
agentStates.set(agentId, state);
|
|
5457
|
+
return state;
|
|
5458
|
+
}
|
|
5459
|
+
async function onEvent(event) {
|
|
5460
|
+
try {
|
|
5461
|
+
if (event.kind !== "message_committed" && event.kind !== "message_revised") {
|
|
5462
|
+
return;
|
|
5463
|
+
}
|
|
5464
|
+
if (event.kind === "message_committed" && event.message.role === "interaction") {
|
|
5465
|
+
return;
|
|
5466
|
+
}
|
|
5467
|
+
const state = await getOrInitState(event.agentId);
|
|
5468
|
+
if (event.kind === "message_committed") {
|
|
5469
|
+
if (event.message.role === "user") {
|
|
5470
|
+
if (state.knownEntryIds.has(event.message.id)) return;
|
|
5471
|
+
const content = convertUserContent(event.message.content);
|
|
5472
|
+
const entry = {
|
|
5473
|
+
type: "message",
|
|
5474
|
+
id: event.message.id,
|
|
5475
|
+
parentId: state.lastEntryId,
|
|
5476
|
+
timestamp: event.message.createdAt,
|
|
5477
|
+
message: {
|
|
5478
|
+
role: "user",
|
|
5479
|
+
content,
|
|
5480
|
+
timestamp: toEpochMs(event.message.createdAt)
|
|
5481
|
+
}
|
|
5482
|
+
};
|
|
5483
|
+
writeSessionEntry(state, entry);
|
|
5484
|
+
} else if (event.message.role === "assistant") {
|
|
5485
|
+
if (state.knownEntryIds.has(event.message.id)) return;
|
|
5486
|
+
const model = event.message.model;
|
|
5487
|
+
const rawUsage = event.message.usage;
|
|
5488
|
+
if (model) {
|
|
5489
|
+
const isDifferentModel = !state.lastModel || state.lastModel.provider !== model.provider || state.lastModel.modelId !== model.id;
|
|
5490
|
+
if (isDifferentModel) {
|
|
5491
|
+
const modelChangeId = `${event.message.id}:model`;
|
|
5492
|
+
if (!state.knownEntryIds.has(modelChangeId)) {
|
|
5493
|
+
const modelChangeEntry = {
|
|
5494
|
+
type: "model_change",
|
|
5495
|
+
id: modelChangeId,
|
|
5496
|
+
parentId: state.lastEntryId,
|
|
5497
|
+
timestamp: event.message.createdAt,
|
|
5498
|
+
provider: model.provider,
|
|
5499
|
+
modelId: model.id
|
|
5500
|
+
};
|
|
5501
|
+
writeSessionEntry(state, modelChangeEntry);
|
|
5502
|
+
}
|
|
5503
|
+
state.lastModel = { provider: model.provider, modelId: model.id };
|
|
5504
|
+
}
|
|
5505
|
+
}
|
|
5506
|
+
const { parts, hasToolCall } = convertAssistantContent(
|
|
5507
|
+
event.message.content,
|
|
5508
|
+
(id, name, internalId) => {
|
|
5509
|
+
state.toolCallIdToName.set(id, name);
|
|
5510
|
+
if (internalId) state.toolCallIdToName.set(internalId, name);
|
|
5511
|
+
}
|
|
5512
|
+
);
|
|
5513
|
+
const assistantMessagePayload = {
|
|
5514
|
+
role: "assistant",
|
|
5515
|
+
content: parts,
|
|
5516
|
+
stopReason: hasToolCall ? "toolUse" : "stop",
|
|
5517
|
+
timestamp: toEpochMs(event.message.createdAt)
|
|
5518
|
+
};
|
|
5519
|
+
if (model || rawUsage) {
|
|
5520
|
+
if (model) {
|
|
5521
|
+
assistantMessagePayload.provider = model.provider;
|
|
5522
|
+
assistantMessagePayload.model = model.id;
|
|
5523
|
+
}
|
|
5524
|
+
const input = rawUsage?.inputTokens ?? 0;
|
|
5525
|
+
const output = rawUsage?.outputTokens ?? 0;
|
|
5526
|
+
const cacheRead = rawUsage?.cacheReadTokens ?? 0;
|
|
5527
|
+
const cacheWrite = rawUsage?.cacheWriteTokens ?? 0;
|
|
5528
|
+
const totalTokens = rawUsage?.totalTokens ?? input + output + cacheRead + cacheWrite;
|
|
5529
|
+
const cost = rawUsage?.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
5530
|
+
assistantMessagePayload.usage = {
|
|
5531
|
+
input,
|
|
5532
|
+
output,
|
|
5533
|
+
cacheRead,
|
|
5534
|
+
cacheWrite,
|
|
5535
|
+
...rawUsage?.cacheWrite1hTokens !== void 0 ? { cacheWrite1h: rawUsage.cacheWrite1hTokens } : {},
|
|
5536
|
+
...rawUsage?.reasoningTokens !== void 0 ? { reasoning: rawUsage.reasoningTokens } : {},
|
|
5537
|
+
totalTokens,
|
|
5538
|
+
cost
|
|
5539
|
+
};
|
|
5540
|
+
}
|
|
5541
|
+
const entry = {
|
|
5542
|
+
type: "message",
|
|
5543
|
+
id: event.message.id,
|
|
5544
|
+
parentId: state.lastEntryId,
|
|
5545
|
+
timestamp: event.message.createdAt,
|
|
5546
|
+
message: assistantMessagePayload
|
|
5547
|
+
};
|
|
5548
|
+
writeSessionEntry(state, entry);
|
|
5549
|
+
} else if (event.message.role === "tool") {
|
|
5550
|
+
for (let index = 0; index < event.message.content.length; index++) {
|
|
5551
|
+
const part = event.message.content[index];
|
|
5552
|
+
const entryId = `${event.message.id}:${index}`;
|
|
5553
|
+
if (state.knownEntryIds.has(entryId)) continue;
|
|
5554
|
+
const toolCallId = part.providerToolCallId ?? part.toolCallId;
|
|
5555
|
+
const toolName = state.toolCallIdToName.get(toolCallId) ?? state.toolCallIdToName.get(part.toolCallId) ?? "unknown";
|
|
5556
|
+
const isError = Boolean(
|
|
5557
|
+
part.result.isError ?? (part.result.ok !== void 0 ? !part.result.ok : Boolean(part.result.error))
|
|
5558
|
+
);
|
|
5559
|
+
const content = convertToolResultContent(part.result.content);
|
|
5560
|
+
const entry = {
|
|
5561
|
+
type: "message",
|
|
5562
|
+
id: entryId,
|
|
5563
|
+
parentId: state.lastEntryId,
|
|
5564
|
+
timestamp: event.message.createdAt,
|
|
5565
|
+
message: {
|
|
5566
|
+
role: "toolResult",
|
|
5567
|
+
toolCallId,
|
|
5568
|
+
toolName,
|
|
5569
|
+
content,
|
|
5570
|
+
isError,
|
|
5571
|
+
timestamp: toEpochMs(event.message.createdAt)
|
|
5572
|
+
}
|
|
5573
|
+
};
|
|
5574
|
+
writeSessionEntry(state, entry);
|
|
5575
|
+
}
|
|
5576
|
+
}
|
|
5577
|
+
} else if (event.kind === "message_revised") {
|
|
5578
|
+
const message = event.message;
|
|
5579
|
+
const revision = message.messageRevision ?? 1;
|
|
5580
|
+
const entryId = `${message.id}@${revision}`;
|
|
5581
|
+
if (state.knownEntryIds.has(entryId)) return;
|
|
5582
|
+
const parentId = state.entryIdToParentId.get(message.id) ?? null;
|
|
5583
|
+
const timestampIso = message.createdAt ?? event.createdAt;
|
|
5584
|
+
const content = convertUserContent(message.content);
|
|
5585
|
+
const entry = {
|
|
5586
|
+
type: "message",
|
|
5587
|
+
id: entryId,
|
|
5588
|
+
parentId,
|
|
5589
|
+
timestamp: timestampIso,
|
|
5590
|
+
message: {
|
|
5591
|
+
role: "user",
|
|
5592
|
+
content,
|
|
5593
|
+
timestamp: toEpochMs(timestampIso)
|
|
5594
|
+
}
|
|
5595
|
+
};
|
|
5596
|
+
writeSessionEntry(state, entry);
|
|
5597
|
+
}
|
|
5598
|
+
} catch (error) {
|
|
5599
|
+
console.error("Failed to write session file entry:", error);
|
|
5600
|
+
}
|
|
5601
|
+
}
|
|
5602
|
+
return runtime.consume({ consumerId: "rowan:session-files", signal: new AbortController().signal, onEvent });
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5295
5605
|
// src/runtime/transient-run-events.ts
|
|
5296
5606
|
var MAX_BUFFERED_EVENTS = 128;
|
|
5297
5607
|
var MAX_BUFFERED_TEXT = 64 * 1024;
|
|
@@ -5648,7 +5958,7 @@ function scopeToKey(scope) {
|
|
|
5648
5958
|
|
|
5649
5959
|
// src/extensions/runner.ts
|
|
5650
5960
|
import { execFile } from "child_process";
|
|
5651
|
-
import { dirname as
|
|
5961
|
+
import { dirname as dirname6, resolve as resolve5 } from "path";
|
|
5652
5962
|
import {
|
|
5653
5963
|
registerModel,
|
|
5654
5964
|
unregisterProviderModels,
|
|
@@ -6477,7 +6787,7 @@ var ExtensionRunner = class {
|
|
|
6477
6787
|
}
|
|
6478
6788
|
}
|
|
6479
6789
|
async loadRegisteredPhase(extension, registration) {
|
|
6480
|
-
const extensionBase = extension.path.startsWith("<") ? this.cwd :
|
|
6790
|
+
const extensionBase = extension.path.startsWith("<") ? this.cwd : dirname6(extension.path);
|
|
6481
6791
|
const phase = await loadPhase(resolve5(extensionBase, registration));
|
|
6482
6792
|
const name = phase.name;
|
|
6483
6793
|
if (this.phases.has(name)) {
|
|
@@ -6553,10 +6863,10 @@ function createExtensionRunner(options) {
|
|
|
6553
6863
|
}
|
|
6554
6864
|
|
|
6555
6865
|
// src/extensions/loader.ts
|
|
6556
|
-
import { existsSync as
|
|
6866
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
|
|
6557
6867
|
import { readdir as readdir3, readFile as readFile3, stat as stat2 } from "fs/promises";
|
|
6558
6868
|
import { fileURLToPath } from "url";
|
|
6559
|
-
import { basename as basename3, dirname as
|
|
6869
|
+
import { basename as basename3, dirname as dirname7, extname as extname2, join as join4, resolve as resolve6 } from "path";
|
|
6560
6870
|
import { createJiti } from "jiti";
|
|
6561
6871
|
function isExtensionFile(path) {
|
|
6562
6872
|
const extension = extname2(path).toLowerCase();
|
|
@@ -6566,12 +6876,12 @@ function isSyntheticPath(path) {
|
|
|
6566
6876
|
return path.startsWith("<") && path.endsWith(">");
|
|
6567
6877
|
}
|
|
6568
6878
|
function readManifestSync(dir) {
|
|
6569
|
-
const manifestPath =
|
|
6570
|
-
if (!
|
|
6879
|
+
const manifestPath = join4(dir, "package.json");
|
|
6880
|
+
if (!existsSync4(manifestPath)) {
|
|
6571
6881
|
return void 0;
|
|
6572
6882
|
}
|
|
6573
6883
|
try {
|
|
6574
|
-
const content =
|
|
6884
|
+
const content = readFileSync2(manifestPath, "utf8");
|
|
6575
6885
|
const pkg = JSON.parse(content);
|
|
6576
6886
|
const rowan = pkg.rowan;
|
|
6577
6887
|
if (!rowan) return void 0;
|
|
@@ -6590,7 +6900,7 @@ function jitiAliases() {
|
|
|
6590
6900
|
return {};
|
|
6591
6901
|
}
|
|
6592
6902
|
const agentSourcePath = fileURLToPath(new URL("../index.ts", moduleUrl));
|
|
6593
|
-
if (!
|
|
6903
|
+
if (!existsSync4(agentSourcePath)) {
|
|
6594
6904
|
return {};
|
|
6595
6905
|
}
|
|
6596
6906
|
return { "@rowan-agent/agent": agentSourcePath };
|
|
@@ -6614,21 +6924,21 @@ async function loadExtensionModule(extensionPath) {
|
|
|
6614
6924
|
return typeof module === "function" ? module : void 0;
|
|
6615
6925
|
}
|
|
6616
6926
|
async function readPackageManifest(path) {
|
|
6617
|
-
if (!
|
|
6927
|
+
if (!existsSync4(path)) {
|
|
6618
6928
|
return void 0;
|
|
6619
6929
|
}
|
|
6620
6930
|
const content = await readFile3(path, "utf8");
|
|
6621
6931
|
return JSON.parse(content);
|
|
6622
6932
|
}
|
|
6623
6933
|
async function resolveExtensionEntries(dir) {
|
|
6624
|
-
const manifest = await readPackageManifest(
|
|
6934
|
+
const manifest = await readPackageManifest(join4(dir, "package.json"));
|
|
6625
6935
|
const declared = manifest?.rowan?.extensions;
|
|
6626
6936
|
if (declared && declared.length > 0) {
|
|
6627
6937
|
return declared.map((entry) => resolve6(dir, entry));
|
|
6628
6938
|
}
|
|
6629
6939
|
for (const name of ["index.ts", "index.js"]) {
|
|
6630
|
-
const entry =
|
|
6631
|
-
if (
|
|
6940
|
+
const entry = join4(dir, name);
|
|
6941
|
+
if (existsSync4(entry)) {
|
|
6632
6942
|
return [entry];
|
|
6633
6943
|
}
|
|
6634
6944
|
}
|
|
@@ -6643,7 +6953,7 @@ async function discoverExtensionsInDir(dir) {
|
|
|
6643
6953
|
});
|
|
6644
6954
|
const paths = [];
|
|
6645
6955
|
for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
6646
|
-
const entryPath =
|
|
6956
|
+
const entryPath = join4(dir, entry.name);
|
|
6647
6957
|
if ((entry.isFile() || entry.isSymbolicLink()) && isExtensionFile(entry.name)) {
|
|
6648
6958
|
paths.push(entryPath);
|
|
6649
6959
|
continue;
|
|
@@ -6663,8 +6973,8 @@ async function discoverExtensionsInDir(dir) {
|
|
|
6663
6973
|
function loadExtensionFromFactory(factory, cwd, extensionPath = "<inline>", options = {}) {
|
|
6664
6974
|
const resolvedCwd = resolve6(cwd);
|
|
6665
6975
|
const resolvedPath = isSyntheticPath(extensionPath) ? extensionPath : resolve6(resolvedCwd, extensionPath);
|
|
6666
|
-
const name = options.name ?? (isSyntheticPath(extensionPath) ? extensionPath : basename3(
|
|
6667
|
-
const manifestDir = isSyntheticPath(extensionPath) ? resolvedCwd :
|
|
6976
|
+
const name = options.name ?? (isSyntheticPath(extensionPath) ? extensionPath : basename3(dirname7(resolvedPath)) || "unknown");
|
|
6977
|
+
const manifestDir = isSyntheticPath(extensionPath) ? resolvedCwd : dirname7(resolvedPath);
|
|
6668
6978
|
const manifest = readManifestSync(manifestDir);
|
|
6669
6979
|
const id = options.id ?? manifest?.id ?? name;
|
|
6670
6980
|
return {
|
|
@@ -6704,7 +7014,7 @@ async function loadExtensionsFromPath(path) {
|
|
|
6704
7014
|
const resolvedPath = resolve6(path);
|
|
6705
7015
|
const info = await stat2(resolvedPath);
|
|
6706
7016
|
if (!info.isDirectory()) {
|
|
6707
|
-
return loadExtensions([resolvedPath],
|
|
7017
|
+
return loadExtensions([resolvedPath], dirname7(resolvedPath));
|
|
6708
7018
|
}
|
|
6709
7019
|
const entries = await resolveExtensionEntries(resolvedPath) ?? await discoverExtensionsInDir(resolvedPath);
|
|
6710
7020
|
return loadExtensions(entries, resolvedPath);
|
|
@@ -6712,7 +7022,7 @@ async function loadExtensionsFromPath(path) {
|
|
|
6712
7022
|
|
|
6713
7023
|
// src/runtime/resource-registry.ts
|
|
6714
7024
|
import { stat as stat3, readdir as readdir4 } from "fs/promises";
|
|
6715
|
-
import { join as
|
|
7025
|
+
import { join as join5, resolve as resolve7 } from "path";
|
|
6716
7026
|
var ResourceRegistryError = class extends Error {
|
|
6717
7027
|
code;
|
|
6718
7028
|
constructor(code, message) {
|
|
@@ -7030,7 +7340,7 @@ async function loadDirectoryValues(kind, directory, sourceId) {
|
|
|
7030
7340
|
if (rootInfo.isFile()) {
|
|
7031
7341
|
targets.push(root);
|
|
7032
7342
|
} else if (rootInfo.isDirectory()) {
|
|
7033
|
-
const markerAtRoot =
|
|
7343
|
+
const markerAtRoot = join5(root, marker);
|
|
7034
7344
|
try {
|
|
7035
7345
|
const markerInfo = await stat3(markerAtRoot);
|
|
7036
7346
|
if (markerInfo.isFile()) targets.push(markerAtRoot);
|
|
@@ -7052,7 +7362,7 @@ async function loadDirectoryValues(kind, directory, sourceId) {
|
|
|
7052
7362
|
}
|
|
7053
7363
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
7054
7364
|
if (!entry.isDirectory()) continue;
|
|
7055
|
-
const target =
|
|
7365
|
+
const target = join5(root, entry.name, marker);
|
|
7056
7366
|
try {
|
|
7057
7367
|
const targetInfo = await stat3(target);
|
|
7058
7368
|
if (targetInfo.isFile()) targets.push(target);
|
|
@@ -7308,7 +7618,7 @@ async function spillLargeToolResult(result, archiveDir, toolName) {
|
|
|
7308
7618
|
await mkdir2(toolDir, { recursive: true, mode: 448 });
|
|
7309
7619
|
await chmod2(toolDir, 448).catch(() => void 0);
|
|
7310
7620
|
const safeToolName = toolName.replace(/[^a-zA-Z0-9._-]+/g, "_");
|
|
7311
|
-
const path =
|
|
7621
|
+
const path = join6(toolDir, `rowan-${safeToolName}-${Date.now()}-${randomUUID()}.log`);
|
|
7312
7622
|
await writeFile2(path, serialized, { encoding: "utf8", mode: 384 });
|
|
7313
7623
|
await chmod2(path, 384).catch(() => void 0);
|
|
7314
7624
|
const preview = new TextDecoder().decode(bytes.subarray(0, MAX_INLINE_TOOL_RESULT_BYTES));
|
|
@@ -7405,6 +7715,9 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
7405
7715
|
await options.bootstrap?.(runtime.resources);
|
|
7406
7716
|
runtime.startHeartbeat();
|
|
7407
7717
|
void runtime.pump();
|
|
7718
|
+
if (options.sessionFiles) {
|
|
7719
|
+
await startSessionFilesConsumer(runtime, options.sessionFiles);
|
|
7720
|
+
}
|
|
7408
7721
|
return runtime;
|
|
7409
7722
|
} catch (error) {
|
|
7410
7723
|
await runtime.resources.closeExtensions().catch(() => void 0);
|
|
@@ -8149,7 +8462,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8149
8462
|
onContext: assembly.setContext,
|
|
8150
8463
|
runtime: {
|
|
8151
8464
|
interact: (request) => this.liveInteract(run.id, request, controller.signal),
|
|
8152
|
-
tools: ({ toolCall, contentBlocks, driver, options, providerInitiated }) => {
|
|
8465
|
+
tools: ({ toolCall, contentBlocks, driver, options, providerInitiated, model: callModel, usage: callUsage }) => {
|
|
8153
8466
|
const task = toolQueue.then(async () => {
|
|
8154
8467
|
if (!providerInitiated) {
|
|
8155
8468
|
const execution = await this.executeToolBatch({
|
|
@@ -8163,6 +8476,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8163
8476
|
signal: controller.signal,
|
|
8164
8477
|
driver,
|
|
8165
8478
|
options,
|
|
8479
|
+
model: callModel ?? model,
|
|
8480
|
+
usage: callUsage,
|
|
8166
8481
|
onRevision: (rev) => {
|
|
8167
8482
|
executionRevision = rev;
|
|
8168
8483
|
}
|
|
@@ -8187,6 +8502,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8187
8502
|
options,
|
|
8188
8503
|
providerInitiated: true,
|
|
8189
8504
|
interactionIds,
|
|
8505
|
+
model: callModel ?? model,
|
|
8506
|
+
usage: callUsage,
|
|
8190
8507
|
onRevision: (rev) => {
|
|
8191
8508
|
executionRevision = rev;
|
|
8192
8509
|
}
|
|
@@ -8277,7 +8594,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8277
8594
|
toolQueue = task.then(() => void 0, () => void 0);
|
|
8278
8595
|
return task;
|
|
8279
8596
|
},
|
|
8280
|
-
toolsBatch: ({ toolCalls, contentBlocks, driver, options }) => {
|
|
8597
|
+
toolsBatch: ({ toolCalls, contentBlocks, driver, options, model: batchModel, usage: batchUsage }) => {
|
|
8281
8598
|
const task = toolQueue.then(async () => {
|
|
8282
8599
|
const execution = await this.executeToolBatch({
|
|
8283
8600
|
run,
|
|
@@ -8290,6 +8607,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8290
8607
|
signal: controller.signal,
|
|
8291
8608
|
driver,
|
|
8292
8609
|
options,
|
|
8610
|
+
model: batchModel ?? model,
|
|
8611
|
+
usage: batchUsage,
|
|
8293
8612
|
onRevision: (rev) => {
|
|
8294
8613
|
executionRevision = rev;
|
|
8295
8614
|
}
|
|
@@ -8517,6 +8836,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8517
8836
|
expectedRevision: revision,
|
|
8518
8837
|
requestMessageId: createId("msg"),
|
|
8519
8838
|
contentBlocks: input.contentBlocks,
|
|
8839
|
+
...input.model ? { model: input.model } : {},
|
|
8840
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8520
8841
|
calls: input.toolCalls.map((tc, i) => ({
|
|
8521
8842
|
toolCallId: toolCallIds[i],
|
|
8522
8843
|
providerToolCallId: tc.id,
|
|
@@ -8652,6 +8973,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8652
8973
|
expectedRevision: revision,
|
|
8653
8974
|
requestMessageId: createId("msg"),
|
|
8654
8975
|
contentBlocks: input.contentBlocks,
|
|
8976
|
+
...input.model ? { model: input.model } : {},
|
|
8977
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8655
8978
|
calls: [{
|
|
8656
8979
|
toolCallId,
|
|
8657
8980
|
providerToolCallId,
|
|
@@ -8749,6 +9072,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8749
9072
|
expectedRevision: revision,
|
|
8750
9073
|
requestMessageId: createId("msg"),
|
|
8751
9074
|
contentBlocks: input.contentBlocks,
|
|
9075
|
+
...input.model ? { model: input.model } : {},
|
|
9076
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8752
9077
|
calls: [{
|
|
8753
9078
|
toolCallId,
|
|
8754
9079
|
providerToolCallId,
|
|
@@ -8770,6 +9095,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8770
9095
|
expectedRevision: revision,
|
|
8771
9096
|
requestMessageId: createId("msg"),
|
|
8772
9097
|
contentBlocks: input.contentBlocks,
|
|
9098
|
+
...input.model ? { model: input.model } : {},
|
|
9099
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8773
9100
|
calls: [{
|
|
8774
9101
|
toolCallId,
|
|
8775
9102
|
providerToolCallId,
|
|
@@ -8824,6 +9151,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8824
9151
|
expectedRevision: revision,
|
|
8825
9152
|
requestMessageId: createId("msg"),
|
|
8826
9153
|
contentBlocks: input.contentBlocks,
|
|
9154
|
+
...input.model ? { model: input.model } : {},
|
|
9155
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8827
9156
|
calls: [{
|
|
8828
9157
|
toolCallId,
|
|
8829
9158
|
providerToolCallId,
|
|
@@ -8873,6 +9202,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8873
9202
|
expectedRevision: revision,
|
|
8874
9203
|
requestMessageId: createId("msg"),
|
|
8875
9204
|
contentBlocks: input.contentBlocks,
|
|
9205
|
+
...input.model ? { model: input.model } : {},
|
|
9206
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8876
9207
|
calls: [{
|
|
8877
9208
|
toolCallId,
|
|
8878
9209
|
providerToolCallId,
|
|
@@ -9197,7 +9528,7 @@ ${content}`;
|
|
|
9197
9528
|
archiveDirFor(agentId) {
|
|
9198
9529
|
const store = this.owned;
|
|
9199
9530
|
const archiveDir = store.contextArchiveDir?.(agentId);
|
|
9200
|
-
return archiveDir ?
|
|
9531
|
+
return archiveDir ? join6(archiveDir, "tool-results") : void 0;
|
|
9201
9532
|
}
|
|
9202
9533
|
async runConsumer(subscription) {
|
|
9203
9534
|
const registration = await this.owned.openConsumer(subscription.consumerId);
|
|
@@ -10355,6 +10686,8 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
10355
10686
|
execution: input.execution,
|
|
10356
10687
|
expectedRevision: input.expectedRevision,
|
|
10357
10688
|
requestMessageId: input.requestMessageId,
|
|
10689
|
+
...input.model ? { model: input.model } : {},
|
|
10690
|
+
...input.usage ? { usage: input.usage } : {},
|
|
10358
10691
|
calls: [{
|
|
10359
10692
|
providerToolCallId,
|
|
10360
10693
|
name: input.name,
|
|
@@ -10386,7 +10719,9 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
10386
10719
|
input.execution.executionId,
|
|
10387
10720
|
input.requestMessageId,
|
|
10388
10721
|
input.calls,
|
|
10389
|
-
input.contentBlocks ?? null
|
|
10722
|
+
input.contentBlocks ?? null,
|
|
10723
|
+
input.model ?? null,
|
|
10724
|
+
input.usage ?? null
|
|
10390
10725
|
]);
|
|
10391
10726
|
const replay = this.replayOperation(operationKey, operationPayload);
|
|
10392
10727
|
if (replay) return clone(replay);
|
|
@@ -10428,7 +10763,9 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
10428
10763
|
role: "assistant",
|
|
10429
10764
|
content: requestMessageContent(toolCalls, input.contentBlocks),
|
|
10430
10765
|
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
10431
|
-
createdAt: timestamp
|
|
10766
|
+
createdAt: timestamp,
|
|
10767
|
+
...input.model ? { model: input.model } : {},
|
|
10768
|
+
...input.usage ? { usage: input.usage } : {}
|
|
10432
10769
|
};
|
|
10433
10770
|
for (const toolCall of toolCalls) this.storeToolCall(toolCall);
|
|
10434
10771
|
this.storeMessage(requestMessage);
|
|
@@ -11480,8 +11817,8 @@ function requestMessageContent(toolCalls, contentBlocks) {
|
|
|
11480
11817
|
|
|
11481
11818
|
// src/runtime/sqlite-durable-store.ts
|
|
11482
11819
|
import { Database } from "bun:sqlite";
|
|
11483
|
-
import { appendFileSync, chmodSync, mkdirSync, readFileSync as
|
|
11484
|
-
import { dirname as
|
|
11820
|
+
import { appendFileSync as appendFileSync2, chmodSync as chmodSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync } from "fs";
|
|
11821
|
+
import { dirname as dirname8, join as join7, resolve as resolve8 } from "path";
|
|
11485
11822
|
import { tmpdir as tmpdir2 } from "os";
|
|
11486
11823
|
var SCHEMA_ID = "rowan.agent.runtime";
|
|
11487
11824
|
var SCHEMA_VERSION = "2";
|
|
@@ -11702,7 +12039,7 @@ var SqliteStore = class {
|
|
|
11702
12039
|
stmtUpdateState;
|
|
11703
12040
|
constructor(filename = ":memory:") {
|
|
11704
12041
|
this.database = new Database(filename, { create: true, readwrite: true, strict: true });
|
|
11705
|
-
this.archiveRoot = filename === ":memory:" ?
|
|
12042
|
+
this.archiveRoot = filename === ":memory:" ? join7(tmpdir2(), `rowan-context-archives-${crypto.randomUUID()}`) : join7(dirname8(resolve8(filename)), "context-archives");
|
|
11706
12043
|
}
|
|
11707
12044
|
async openOwner(input) {
|
|
11708
12045
|
this.assertOpen();
|
|
@@ -11796,7 +12133,7 @@ var SqliteStore = class {
|
|
|
11796
12133
|
}
|
|
11797
12134
|
/** Filesystem location owned by this Store for one Agent's readable archive. */
|
|
11798
12135
|
contextArchiveDir(agentId) {
|
|
11799
|
-
return
|
|
12136
|
+
return join7(this.archiveRoot, String(agentId));
|
|
11800
12137
|
}
|
|
11801
12138
|
async reserveAgent(lease, input) {
|
|
11802
12139
|
return this.invoke(lease, (store, current) => store.reserveAgent(current, input));
|
|
@@ -12392,7 +12729,7 @@ var SqliteStore = class {
|
|
|
12392
12729
|
mirrorChanges(tracker) {
|
|
12393
12730
|
for (const agentId of tracker.deletedAgentIds) {
|
|
12394
12731
|
const idStr = String(agentId);
|
|
12395
|
-
rmSync(
|
|
12732
|
+
rmSync(join7(this.archiveRoot, idStr), { recursive: true, force: true });
|
|
12396
12733
|
this.mirroredEventIds.delete(idStr);
|
|
12397
12734
|
this.mirroredCompactionIds.delete(idStr);
|
|
12398
12735
|
this.mirroredAgents.delete(idStr);
|
|
@@ -12400,15 +12737,15 @@ var SqliteStore = class {
|
|
|
12400
12737
|
for (const agent of tracker.upsertedAgents.values()) {
|
|
12401
12738
|
const idStr = String(agent.id);
|
|
12402
12739
|
this.mirroredAgents.add(idStr);
|
|
12403
|
-
const archiveDir =
|
|
12404
|
-
const toolDir =
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12740
|
+
const archiveDir = join7(this.archiveRoot, idStr);
|
|
12741
|
+
const toolDir = join7(archiveDir, "tool-results");
|
|
12742
|
+
mkdirSync2(toolDir, { recursive: true, mode: 448 });
|
|
12743
|
+
chmodSync2(archiveDir, 448);
|
|
12744
|
+
chmodSync2(toolDir, 448);
|
|
12408
12745
|
}
|
|
12409
12746
|
if (tracker.appendedEvents.length > 0) {
|
|
12410
|
-
|
|
12411
|
-
|
|
12747
|
+
mkdirSync2(this.archiveRoot, { recursive: true, mode: 448 });
|
|
12748
|
+
chmodSync2(this.archiveRoot, 448);
|
|
12412
12749
|
const eventsByAgent = /* @__PURE__ */ new Map();
|
|
12413
12750
|
for (const event of tracker.appendedEvents) {
|
|
12414
12751
|
const agentId = String(event.agentId);
|
|
@@ -12420,22 +12757,22 @@ var SqliteStore = class {
|
|
|
12420
12757
|
list.push(event);
|
|
12421
12758
|
}
|
|
12422
12759
|
for (const [agentId, events] of eventsByAgent) {
|
|
12423
|
-
const archiveDir =
|
|
12424
|
-
const toolDir =
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
const sessionPath =
|
|
12760
|
+
const archiveDir = join7(this.archiveRoot, agentId);
|
|
12761
|
+
const toolDir = join7(archiveDir, "tool-results");
|
|
12762
|
+
mkdirSync2(toolDir, { recursive: true, mode: 448 });
|
|
12763
|
+
chmodSync2(archiveDir, 448);
|
|
12764
|
+
chmodSync2(toolDir, 448);
|
|
12765
|
+
const sessionPath = join7(archiveDir, "session.jsonl");
|
|
12429
12766
|
try {
|
|
12430
|
-
|
|
12767
|
+
chmodSync2(sessionPath, 384);
|
|
12431
12768
|
} catch {
|
|
12432
12769
|
}
|
|
12433
12770
|
const known = this.mirroredEventIds.get(agentId) ?? /* @__PURE__ */ new Set();
|
|
12434
12771
|
const newEvents = events.filter((e) => !known.has(String(e.id)));
|
|
12435
12772
|
if (newEvents.length > 0) {
|
|
12436
12773
|
const lines = newEvents.map((e) => JSON.stringify({ schemaVersion: 1, kind: "rowan_event", event: e }) + "\n").join("");
|
|
12437
|
-
|
|
12438
|
-
|
|
12774
|
+
appendFileSync2(sessionPath, lines, { encoding: "utf8", mode: 384 });
|
|
12775
|
+
chmodSync2(sessionPath, 384);
|
|
12439
12776
|
for (const e of newEvents) known.add(String(e.id));
|
|
12440
12777
|
this.mirroredEventIds.set(agentId, known);
|
|
12441
12778
|
}
|
|
@@ -12444,13 +12781,13 @@ var SqliteStore = class {
|
|
|
12444
12781
|
if (tracker.upsertedContextCompactions.size > 0) {
|
|
12445
12782
|
for (const [agentId, record] of tracker.upsertedContextCompactions) {
|
|
12446
12783
|
const idStr = String(agentId);
|
|
12447
|
-
const archiveDir =
|
|
12448
|
-
const sessionPath =
|
|
12784
|
+
const archiveDir = join7(this.archiveRoot, idStr);
|
|
12785
|
+
const sessionPath = join7(archiveDir, "session.jsonl");
|
|
12449
12786
|
const knownCompactions = this.mirroredCompactionIds.get(idStr) ?? /* @__PURE__ */ new Set();
|
|
12450
12787
|
if (!knownCompactions.has(record.id)) {
|
|
12451
12788
|
const line = JSON.stringify({ schemaVersion: 1, kind: "context_compacted", record }) + "\n";
|
|
12452
|
-
|
|
12453
|
-
|
|
12789
|
+
appendFileSync2(sessionPath, line, { encoding: "utf8", mode: 384 });
|
|
12790
|
+
chmodSync2(sessionPath, 384);
|
|
12454
12791
|
knownCompactions.add(record.id);
|
|
12455
12792
|
this.mirroredCompactionIds.set(idStr, knownCompactions);
|
|
12456
12793
|
}
|
|
@@ -12459,32 +12796,32 @@ var SqliteStore = class {
|
|
|
12459
12796
|
}
|
|
12460
12797
|
/** Append the semantic durable event mirror and remove deleted Agent sidecars. */
|
|
12461
12798
|
mirrorInitialState(state) {
|
|
12462
|
-
|
|
12463
|
-
|
|
12799
|
+
mkdirSync2(this.archiveRoot, { recursive: true, mode: 448 });
|
|
12800
|
+
chmodSync2(this.archiveRoot, 448);
|
|
12464
12801
|
const currentAgents = new Set(state.agents.map((agent) => String(agent.id)));
|
|
12465
12802
|
for (const agentId of this.mirroredAgents) {
|
|
12466
12803
|
if (currentAgents.has(agentId)) continue;
|
|
12467
|
-
rmSync(
|
|
12804
|
+
rmSync(join7(this.archiveRoot, agentId), { recursive: true, force: true });
|
|
12468
12805
|
this.mirroredEventIds.delete(agentId);
|
|
12469
12806
|
this.mirroredCompactionIds.delete(agentId);
|
|
12470
12807
|
}
|
|
12471
12808
|
for (const agent of state.agents) {
|
|
12472
12809
|
const agentId = String(agent.id);
|
|
12473
|
-
const archiveDir =
|
|
12474
|
-
const toolDir =
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
const sessionPath =
|
|
12810
|
+
const archiveDir = join7(this.archiveRoot, agentId);
|
|
12811
|
+
const toolDir = join7(archiveDir, "tool-results");
|
|
12812
|
+
mkdirSync2(toolDir, { recursive: true, mode: 448 });
|
|
12813
|
+
chmodSync2(archiveDir, 448);
|
|
12814
|
+
chmodSync2(toolDir, 448);
|
|
12815
|
+
const sessionPath = join7(archiveDir, "session.jsonl");
|
|
12479
12816
|
try {
|
|
12480
|
-
|
|
12817
|
+
chmodSync2(sessionPath, 384);
|
|
12481
12818
|
} catch {
|
|
12482
12819
|
}
|
|
12483
12820
|
const known = this.mirroredEventIds.get(agentId) ?? /* @__PURE__ */ new Set();
|
|
12484
12821
|
const knownCompactions = this.mirroredCompactionIds.get(agentId) ?? /* @__PURE__ */ new Set();
|
|
12485
12822
|
if (known.size === 0 || knownCompactions.size === 0) {
|
|
12486
12823
|
try {
|
|
12487
|
-
for (const line of
|
|
12824
|
+
for (const line of readFileSync3(sessionPath, "utf8").split("\n")) {
|
|
12488
12825
|
if (!line.trim()) continue;
|
|
12489
12826
|
const parsed = JSON.parse(line);
|
|
12490
12827
|
if (parsed.event?.id) known.add(parsed.event.id);
|
|
@@ -12495,16 +12832,16 @@ var SqliteStore = class {
|
|
|
12495
12832
|
}
|
|
12496
12833
|
const lines = state.events.filter((event) => String(event.agentId) === agentId && !known.has(String(event.id))).map((event) => JSON.stringify({ schemaVersion: 1, kind: "rowan_event", event }) + "\n");
|
|
12497
12834
|
if (lines.length > 0) {
|
|
12498
|
-
|
|
12499
|
-
|
|
12835
|
+
appendFileSync2(sessionPath, lines.join(""), { encoding: "utf8", mode: 384 });
|
|
12836
|
+
chmodSync2(sessionPath, 384);
|
|
12500
12837
|
for (const event of state.events) {
|
|
12501
12838
|
if (String(event.agentId) === agentId) known.add(String(event.id));
|
|
12502
12839
|
}
|
|
12503
12840
|
}
|
|
12504
12841
|
const compactionLines = (state.contextCompactions ?? []).filter(([candidateId, record]) => String(candidateId) === agentId && !knownCompactions.has(record.id)).map(([, record]) => JSON.stringify({ schemaVersion: 1, kind: "context_compacted", record }) + "\n");
|
|
12505
12842
|
if (compactionLines.length > 0) {
|
|
12506
|
-
|
|
12507
|
-
|
|
12843
|
+
appendFileSync2(sessionPath, compactionLines.join(""), { encoding: "utf8", mode: 384 });
|
|
12844
|
+
chmodSync2(sessionPath, 384);
|
|
12508
12845
|
for (const [, record] of state.contextCompactions ?? []) {
|
|
12509
12846
|
if (String(record.agentId) === agentId) knownCompactions.add(record.id);
|
|
12510
12847
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rowan-agent/agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
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.
|
|
26
|
+
"@rowan-agent/models": "0.10.0",
|
|
27
27
|
"jiti": "2.7.0",
|
|
28
28
|
"typebox": "^1.0.0",
|
|
29
29
|
"yaml": "^2.7.0"
|