@rowan-agent/agent 0.20.2 → 0.22.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 +43 -29
- package/dist/index.js +480 -177
- package/package.json +2 -2
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
|
|
@@ -1401,7 +1401,8 @@ async function invokeModel(input) {
|
|
|
1401
1401
|
metadataPhase: input.phaseId,
|
|
1402
1402
|
output: input.output,
|
|
1403
1403
|
onThinkingDelta: input.onThinkingDelta,
|
|
1404
|
-
onToolCallDelta: input.onToolCallDelta
|
|
1404
|
+
onToolCallDelta: input.onToolCallDelta,
|
|
1405
|
+
model: input.request.model
|
|
1405
1406
|
});
|
|
1406
1407
|
const response = result.doneResponse ?? {
|
|
1407
1408
|
content: result.text,
|
|
@@ -1417,6 +1418,8 @@ async function invokeModel(input) {
|
|
|
1417
1418
|
contentBlocks: result.contentBlocks,
|
|
1418
1419
|
toolCalls: result.toolCalls,
|
|
1419
1420
|
stopReason: result.stopReason,
|
|
1421
|
+
model: input.request.model,
|
|
1422
|
+
usage: response.usage,
|
|
1420
1423
|
transcript: {
|
|
1421
1424
|
request: input.request,
|
|
1422
1425
|
response
|
|
@@ -1540,7 +1543,7 @@ async function collectStreamResult(input) {
|
|
|
1540
1543
|
input.message.replaceContent(activeMessageId, contentBlocksToMessageContent(contentBlocks2));
|
|
1541
1544
|
}
|
|
1542
1545
|
if (persistAssistant && activeMessageId) {
|
|
1543
|
-
if (hasContent2) await input.message.end(activeMessageId);
|
|
1546
|
+
if (hasContent2) await input.message.end(activeMessageId, { model: input.model, usage: event.response?.usage });
|
|
1544
1547
|
else input.message.discard(activeMessageId);
|
|
1545
1548
|
activeMessageId = void 0;
|
|
1546
1549
|
}
|
|
@@ -1549,13 +1552,13 @@ async function collectStreamResult(input) {
|
|
|
1549
1552
|
const abortResult = LoopGuard.checkAbort(input.config.signal);
|
|
1550
1553
|
if (abortResult.stopReason !== "none") {
|
|
1551
1554
|
if (persistAssistant && activeMessageId) {
|
|
1552
|
-
await input.message.end(activeMessageId);
|
|
1555
|
+
await input.message.end(activeMessageId, { model: input.model });
|
|
1553
1556
|
activeMessageId = void 0;
|
|
1554
1557
|
}
|
|
1555
1558
|
return { text: abortResult.message, contentBlocks: [], toolCalls: [], stopReason: "aborted" };
|
|
1556
1559
|
}
|
|
1557
1560
|
if (persistAssistant && activeMessageId) {
|
|
1558
|
-
await input.message.end(activeMessageId);
|
|
1561
|
+
await input.message.end(activeMessageId, { model: input.model, usage: doneResponse?.usage });
|
|
1559
1562
|
}
|
|
1560
1563
|
const hasContent = (lastPartial?.contentBlocks?.length ?? 0) > 0 || (doneResponse?.content?.length ?? 0) > 0 || (doneResponse?.toolCalls?.length ?? 0) > 0;
|
|
1561
1564
|
if (!hasContent && stopReason !== "error" && stopReason !== "aborted") {
|
|
@@ -1617,7 +1620,7 @@ function createExtensionAPI(hooks, options, runtime, eventBus) {
|
|
|
1617
1620
|
let outputPayload = phaseIn?.state?.payload;
|
|
1618
1621
|
let nextPhase;
|
|
1619
1622
|
let outputMessage;
|
|
1620
|
-
|
|
1623
|
+
const api = {
|
|
1621
1624
|
hooks: {
|
|
1622
1625
|
on: (eventType, handler) => {
|
|
1623
1626
|
assertActive();
|
|
@@ -1780,27 +1783,17 @@ function createExtensionAPI(hooks, options, runtime, eventBus) {
|
|
|
1780
1783
|
},
|
|
1781
1784
|
getNextPhase: () => nextPhase,
|
|
1782
1785
|
getMessage: () => outputMessage
|
|
1783
|
-
},
|
|
1784
|
-
host: {
|
|
1785
|
-
contribute: (contribution) => {
|
|
1786
|
-
assertActive();
|
|
1787
|
-
if (!contribution || typeof contribution !== "object" || Array.isArray(contribution)) {
|
|
1788
|
-
throw new TypeError("Host contribution must be an object.");
|
|
1789
|
-
}
|
|
1790
|
-
if (typeof contribution.kind !== "string" || contribution.kind.trim() === "") {
|
|
1791
|
-
throw new TypeError("Host contribution requires a non-empty kind.");
|
|
1792
|
-
}
|
|
1793
|
-
if (typeof contribution.id !== "string" || contribution.id.trim() === "") {
|
|
1794
|
-
throw new TypeError("Host contribution requires a non-empty id.");
|
|
1795
|
-
}
|
|
1796
|
-
assertJsonValue(contribution, "Host contribution");
|
|
1797
|
-
const dispose = options?.contributeToHost ? options.contributeToHost(contribution) : () => {
|
|
1798
|
-
};
|
|
1799
|
-
trackCleanup?.(dispose);
|
|
1800
|
-
return dispose;
|
|
1801
|
-
}
|
|
1802
1786
|
}
|
|
1803
1787
|
};
|
|
1788
|
+
if (options?.namespaces) {
|
|
1789
|
+
for (const [key, value] of Object.entries(options.namespaces)) {
|
|
1790
|
+
if (key in api) {
|
|
1791
|
+
throw new Error(`Host API namespace collision: "${key}" is a built-in API key.`);
|
|
1792
|
+
}
|
|
1793
|
+
Object.defineProperty(api, key, { value, enumerable: true });
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
return api;
|
|
1804
1797
|
}
|
|
1805
1798
|
|
|
1806
1799
|
// src/harness/phases/interactions.ts
|
|
@@ -2706,6 +2699,7 @@ function buildModelRequest(input, options) {
|
|
|
2706
2699
|
model: options?.model ?? { provider: "", id: "" },
|
|
2707
2700
|
...options?.thinkingLevel === void 0 ? {} : { thinkingLevel: options.thinkingLevel },
|
|
2708
2701
|
...options?.providerOptions === void 0 ? {} : { providerOptions: options.providerOptions },
|
|
2702
|
+
...options?.sessionId === void 0 ? {} : { sessionId: options.sessionId },
|
|
2709
2703
|
system: systemText,
|
|
2710
2704
|
messages,
|
|
2711
2705
|
tools: modelTools.length > 0 ? modelTools : void 0
|
|
@@ -2971,9 +2965,15 @@ function createMessageManager(context, onMessage, onMessageDelta) {
|
|
|
2971
2965
|
if (!active) return;
|
|
2972
2966
|
active.message.content = content;
|
|
2973
2967
|
},
|
|
2974
|
-
async end(messageId) {
|
|
2968
|
+
async end(messageId, meta) {
|
|
2975
2969
|
const active = activeMessages.get(messageId);
|
|
2976
2970
|
if (!active) return;
|
|
2971
|
+
if (meta?.model) {
|
|
2972
|
+
active.message.model = meta.model;
|
|
2973
|
+
}
|
|
2974
|
+
if (meta?.usage) {
|
|
2975
|
+
active.message.usage = meta.usage;
|
|
2976
|
+
}
|
|
2977
2977
|
if (!active.emitted && (active.message.content === "" || active.message.content.length === 0)) {
|
|
2978
2978
|
activeMessages.delete(messageId);
|
|
2979
2979
|
return;
|
|
@@ -3042,6 +3042,7 @@ async function executePhaseWithModel(ctx) {
|
|
|
3042
3042
|
};
|
|
3043
3043
|
let executableToolCalls;
|
|
3044
3044
|
let roundContentBlocks;
|
|
3045
|
+
let collected;
|
|
3045
3046
|
const checkpoint = ctx.execution.interaction.checkpoint();
|
|
3046
3047
|
if (checkpoint && typeof checkpoint === "object" && checkpoint.kind === "tool_call_suspension") {
|
|
3047
3048
|
const toolSuspension = checkpoint;
|
|
@@ -3054,7 +3055,7 @@ async function executePhaseWithModel(ctx) {
|
|
|
3054
3055
|
toolCalls: [...toolSuspension.toolCalls]
|
|
3055
3056
|
};
|
|
3056
3057
|
} else {
|
|
3057
|
-
|
|
3058
|
+
collected = await ctx.execution.invokeModel(roundContext);
|
|
3058
3059
|
output = {
|
|
3059
3060
|
message: collected.text,
|
|
3060
3061
|
phase: ctx.phase.name,
|
|
@@ -3087,7 +3088,13 @@ async function executePhaseWithModel(ctx) {
|
|
|
3087
3088
|
return output;
|
|
3088
3089
|
}
|
|
3089
3090
|
}
|
|
3090
|
-
const
|
|
3091
|
+
const currentModel = ctx.phase.model ?? ctx.config.model;
|
|
3092
|
+
const results = await ctx.execution.executeTools(
|
|
3093
|
+
roundContext,
|
|
3094
|
+
executableToolCalls,
|
|
3095
|
+
roundContentBlocks,
|
|
3096
|
+
{ model: currentModel, usage: collected?.usage }
|
|
3097
|
+
);
|
|
3091
3098
|
for (const result of results) {
|
|
3092
3099
|
const messageId = ctx.messageManager.start("tool", createToolResultContent(result), {
|
|
3093
3100
|
phase: ctx.phase.name
|
|
@@ -3641,7 +3648,9 @@ async function executeToolCalls(input) {
|
|
|
3641
3648
|
config: input.config,
|
|
3642
3649
|
toolCalls: input.toolCalls,
|
|
3643
3650
|
contentBlocks: input.contentBlocks,
|
|
3644
|
-
driver: input.driver
|
|
3651
|
+
driver: input.driver,
|
|
3652
|
+
model: input.model,
|
|
3653
|
+
usage: input.usage
|
|
3645
3654
|
});
|
|
3646
3655
|
if (results2.length !== input.toolCalls.length) throw new Error("Runtime returned an invalid Tool batch result");
|
|
3647
3656
|
return results2.map((result, index) => ({
|
|
@@ -3713,6 +3722,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3713
3722
|
appendSystemPrompt: phaseContext.appendSystemPrompt
|
|
3714
3723
|
}, {
|
|
3715
3724
|
model: phase.model ?? config.model,
|
|
3725
|
+
sessionId: config.execution.agentId,
|
|
3716
3726
|
...config.thinkingLevel === void 0 ? {} : { thinkingLevel: config.thinkingLevel },
|
|
3717
3727
|
...config.providerOptions === void 0 ? {} : { providerOptions: config.providerOptions }
|
|
3718
3728
|
});
|
|
@@ -3798,7 +3808,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3798
3808
|
await config.onPhaseStatus?.(phase.name, status);
|
|
3799
3809
|
},
|
|
3800
3810
|
executeTool: executePhaseTool,
|
|
3801
|
-
async executeTools(phaseContext, toolCalls, contentBlocks) {
|
|
3811
|
+
async executeTools(phaseContext, toolCalls, contentBlocks, meta) {
|
|
3802
3812
|
return runTurn(async () => {
|
|
3803
3813
|
const tools = phaseContext.tools.filter((tool) => tool.name !== PhaseRouteTool);
|
|
3804
3814
|
for (const toolCall of toolCalls) {
|
|
@@ -3816,7 +3826,9 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3816
3826
|
tools,
|
|
3817
3827
|
toolCalls,
|
|
3818
3828
|
contentBlocks,
|
|
3819
|
-
driver: interaction
|
|
3829
|
+
driver: interaction,
|
|
3830
|
+
model: meta?.model,
|
|
3831
|
+
usage: meta?.usage
|
|
3820
3832
|
});
|
|
3821
3833
|
for (const result of results) {
|
|
3822
3834
|
await toolExecutionManager.end(result.toolCallId, result.toolName, result, !result.ok);
|
|
@@ -4283,7 +4295,7 @@ function normalizeUserInput(input) {
|
|
|
4283
4295
|
return normalized;
|
|
4284
4296
|
}
|
|
4285
4297
|
function isAssistantMessage(value) {
|
|
4286
|
-
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");
|
|
4298
|
+
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));
|
|
4287
4299
|
}
|
|
4288
4300
|
function isToolResult(value) {
|
|
4289
4301
|
if (!isRecord3(value)) return false;
|
|
@@ -4999,7 +5011,9 @@ function projectAssistantMessage(message, agentId, runId, sequenceWithinRun, opt
|
|
|
4999
5011
|
sequenceWithinRun,
|
|
5000
5012
|
createdAt: message.createdAt,
|
|
5001
5013
|
...message.metadata ? { metadata: message.metadata } : {},
|
|
5002
|
-
...options.interrupted ? { interrupted: true } : {}
|
|
5014
|
+
...options.interrupted ? { interrupted: true } : {},
|
|
5015
|
+
...message.model ? { model: message.model } : {},
|
|
5016
|
+
...message.usage ? { usage: message.usage } : {}
|
|
5003
5017
|
};
|
|
5004
5018
|
}
|
|
5005
5019
|
function durableInterruptedAssistantContent(content) {
|
|
@@ -5251,6 +5265,333 @@ function fromLoopResult(result) {
|
|
|
5251
5265
|
};
|
|
5252
5266
|
}
|
|
5253
5267
|
|
|
5268
|
+
// src/runtime/session-files.ts
|
|
5269
|
+
import { appendFileSync, chmodSync, existsSync as existsSync3, mkdirSync, readFileSync } from "fs";
|
|
5270
|
+
import { dirname as dirname5, join as join3 } from "path";
|
|
5271
|
+
function toEpochMs(isoString) {
|
|
5272
|
+
if (!isoString) return Date.now();
|
|
5273
|
+
const ms = new Date(isoString).getTime();
|
|
5274
|
+
return Number.isNaN(ms) ? Date.now() : ms;
|
|
5275
|
+
}
|
|
5276
|
+
function isContentBlock(value) {
|
|
5277
|
+
if (!value || typeof value !== "object") return false;
|
|
5278
|
+
const candidate = value;
|
|
5279
|
+
if (candidate.type === "text" && typeof candidate.text === "string") return true;
|
|
5280
|
+
if (candidate.type === "image" && typeof candidate.data === "string" && typeof candidate.mimeType === "string") return true;
|
|
5281
|
+
return false;
|
|
5282
|
+
}
|
|
5283
|
+
function convertToolResultContent(content) {
|
|
5284
|
+
if (content === void 0 || content === null) {
|
|
5285
|
+
return [{ type: "text", text: "" }];
|
|
5286
|
+
}
|
|
5287
|
+
if (typeof content === "string") {
|
|
5288
|
+
return [{ type: "text", text: content }];
|
|
5289
|
+
}
|
|
5290
|
+
if (isContentBlock(content)) {
|
|
5291
|
+
return content.type === "image" ? [{ type: "image", data: content.data, mimeType: content.mimeType }] : [{ type: "text", text: content.text }];
|
|
5292
|
+
}
|
|
5293
|
+
if (Array.isArray(content)) {
|
|
5294
|
+
if (content.length > 0 && content.every(isContentBlock)) {
|
|
5295
|
+
return content.map(
|
|
5296
|
+
(item) => item.type === "image" ? { type: "image", data: item.data, mimeType: item.mimeType } : { type: "text", text: item.text }
|
|
5297
|
+
);
|
|
5298
|
+
}
|
|
5299
|
+
return [{ type: "text", text: JSON.stringify(content) }];
|
|
5300
|
+
}
|
|
5301
|
+
return [{ type: "text", text: JSON.stringify(content) }];
|
|
5302
|
+
}
|
|
5303
|
+
function convertUserContent(content) {
|
|
5304
|
+
if (typeof content === "string") return content;
|
|
5305
|
+
return content.map(
|
|
5306
|
+
(part) => part.type === "image" ? { type: "image", data: part.data, mimeType: part.mimeType } : { type: "text", text: part.text }
|
|
5307
|
+
);
|
|
5308
|
+
}
|
|
5309
|
+
function convertAssistantContent(content, onToolCall) {
|
|
5310
|
+
if (typeof content === "string") {
|
|
5311
|
+
return {
|
|
5312
|
+
parts: [{ type: "text", text: content }],
|
|
5313
|
+
hasToolCall: false
|
|
5314
|
+
};
|
|
5315
|
+
}
|
|
5316
|
+
let hasToolCall = false;
|
|
5317
|
+
const parts = [];
|
|
5318
|
+
for (const part of content) {
|
|
5319
|
+
if (part.type === "text") {
|
|
5320
|
+
parts.push({ type: "text", text: part.text });
|
|
5321
|
+
} else if (part.type === "thinking") {
|
|
5322
|
+
parts.push({
|
|
5323
|
+
type: "thinking",
|
|
5324
|
+
thinking: part.thinking,
|
|
5325
|
+
...part.signature ? { thinkingSignature: part.signature } : {}
|
|
5326
|
+
});
|
|
5327
|
+
} else if (part.type === "tool_use") {
|
|
5328
|
+
hasToolCall = true;
|
|
5329
|
+
const callId = part.providerToolCallId ?? part.toolCallId;
|
|
5330
|
+
onToolCall?.(callId, part.name, part.toolCallId);
|
|
5331
|
+
parts.push({
|
|
5332
|
+
type: "toolCall",
|
|
5333
|
+
id: callId,
|
|
5334
|
+
name: part.name,
|
|
5335
|
+
arguments: part.input
|
|
5336
|
+
});
|
|
5337
|
+
}
|
|
5338
|
+
}
|
|
5339
|
+
return { parts, hasToolCall };
|
|
5340
|
+
}
|
|
5341
|
+
async function getAgentCreatedAt(runtime, agentId) {
|
|
5342
|
+
let after;
|
|
5343
|
+
while (true) {
|
|
5344
|
+
const page = await runtime.listAgents(after ? { after, limit: 100 } : { limit: 100 });
|
|
5345
|
+
const agent = page.items.find((item) => item.id === agentId);
|
|
5346
|
+
if (agent) return agent.createdAt;
|
|
5347
|
+
if (!page.next) break;
|
|
5348
|
+
after = page.next;
|
|
5349
|
+
}
|
|
5350
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
5351
|
+
}
|
|
5352
|
+
async function getFirstRunCwd(runtime, agentId) {
|
|
5353
|
+
let after;
|
|
5354
|
+
while (true) {
|
|
5355
|
+
const page = await runtime.listRuns(after ? { agentId, after, limit: 100 } : { agentId, limit: 100 });
|
|
5356
|
+
for (const runSummary of page.items) {
|
|
5357
|
+
try {
|
|
5358
|
+
const snapshot = await runtime.run(runSummary.id).snapshot();
|
|
5359
|
+
if (snapshot.cwd && snapshot.cwd.trim().length > 0) {
|
|
5360
|
+
return snapshot.cwd;
|
|
5361
|
+
}
|
|
5362
|
+
} catch {
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
5365
|
+
if (!page.next) break;
|
|
5366
|
+
after = page.next;
|
|
5367
|
+
}
|
|
5368
|
+
return "";
|
|
5369
|
+
}
|
|
5370
|
+
function writeSessionEntry(state, entry) {
|
|
5371
|
+
appendFileSync(state.filePath, `${JSON.stringify(entry)}
|
|
5372
|
+
`, { encoding: "utf8", mode: 384 });
|
|
5373
|
+
try {
|
|
5374
|
+
chmodSync(state.filePath, 384);
|
|
5375
|
+
} catch {
|
|
5376
|
+
}
|
|
5377
|
+
state.knownEntryIds.add(entry.id);
|
|
5378
|
+
state.entryIdToParentId.set(entry.id, entry.parentId);
|
|
5379
|
+
state.lastEntryId = entry.id;
|
|
5380
|
+
}
|
|
5381
|
+
async function startSessionFilesConsumer(runtime, options) {
|
|
5382
|
+
const agentStates = /* @__PURE__ */ new Map();
|
|
5383
|
+
async function getOrInitState(agentId) {
|
|
5384
|
+
let state = agentStates.get(agentId);
|
|
5385
|
+
if (state) return state;
|
|
5386
|
+
const createdAt = await getAgentCreatedAt(runtime, agentId);
|
|
5387
|
+
const cwd = await getFirstRunCwd(runtime, agentId);
|
|
5388
|
+
const folderName = cwd.length > 0 ? `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--` : "--unknown--";
|
|
5389
|
+
const fileTimestamp = createdAt.replace(/[:.]/g, "-");
|
|
5390
|
+
const fileName = `${fileTimestamp}_${agentId}.jsonl`;
|
|
5391
|
+
const filePath = join3(options.dir, folderName, fileName);
|
|
5392
|
+
const knownEntryIds = /* @__PURE__ */ new Set();
|
|
5393
|
+
let lastEntryId = null;
|
|
5394
|
+
let lastModel;
|
|
5395
|
+
const entryIdToParentId = /* @__PURE__ */ new Map();
|
|
5396
|
+
const toolCallIdToName = /* @__PURE__ */ new Map();
|
|
5397
|
+
const writeHeader = () => {
|
|
5398
|
+
const header = { type: "session", version: 3, id: agentId, timestamp: createdAt, cwd };
|
|
5399
|
+
appendFileSync(filePath, `${JSON.stringify(header)}
|
|
5400
|
+
`, { encoding: "utf8", mode: 384 });
|
|
5401
|
+
};
|
|
5402
|
+
mkdirSync(dirname5(filePath), { recursive: true, mode: 448 });
|
|
5403
|
+
if (existsSync3(filePath)) {
|
|
5404
|
+
const content = readFileSync(filePath, "utf8");
|
|
5405
|
+
if (content.trim().length === 0) {
|
|
5406
|
+
writeHeader();
|
|
5407
|
+
} else {
|
|
5408
|
+
for (const line of content.split("\n")) {
|
|
5409
|
+
const trimmed = line.trim();
|
|
5410
|
+
if (!trimmed) continue;
|
|
5411
|
+
let parsed;
|
|
5412
|
+
try {
|
|
5413
|
+
parsed = JSON.parse(trimmed);
|
|
5414
|
+
} catch {
|
|
5415
|
+
continue;
|
|
5416
|
+
}
|
|
5417
|
+
if (parsed.type === "session") continue;
|
|
5418
|
+
if (typeof parsed.id === "string") {
|
|
5419
|
+
knownEntryIds.add(parsed.id);
|
|
5420
|
+
entryIdToParentId.set(parsed.id, parsed.parentId ?? null);
|
|
5421
|
+
lastEntryId = parsed.id;
|
|
5422
|
+
}
|
|
5423
|
+
if (parsed.type === "model_change" && typeof parsed.provider === "string" && typeof parsed.modelId === "string") {
|
|
5424
|
+
lastModel = { provider: parsed.provider, modelId: parsed.modelId };
|
|
5425
|
+
}
|
|
5426
|
+
if (parsed.type === "message" && parsed.message?.role === "assistant" && Array.isArray(parsed.message.content)) {
|
|
5427
|
+
for (const part of parsed.message.content) {
|
|
5428
|
+
if (part && part.type === "toolCall" && typeof part.id === "string" && typeof part.name === "string") {
|
|
5429
|
+
toolCallIdToName.set(part.id, part.name);
|
|
5430
|
+
}
|
|
5431
|
+
}
|
|
5432
|
+
}
|
|
5433
|
+
}
|
|
5434
|
+
}
|
|
5435
|
+
} else {
|
|
5436
|
+
writeHeader();
|
|
5437
|
+
}
|
|
5438
|
+
state = {
|
|
5439
|
+
filePath,
|
|
5440
|
+
knownEntryIds,
|
|
5441
|
+
lastEntryId,
|
|
5442
|
+
entryIdToParentId,
|
|
5443
|
+
toolCallIdToName,
|
|
5444
|
+
...lastModel ? { lastModel } : {}
|
|
5445
|
+
};
|
|
5446
|
+
agentStates.set(agentId, state);
|
|
5447
|
+
return state;
|
|
5448
|
+
}
|
|
5449
|
+
async function onEvent(event) {
|
|
5450
|
+
try {
|
|
5451
|
+
if (event.kind !== "message_committed" && event.kind !== "message_revised") {
|
|
5452
|
+
return;
|
|
5453
|
+
}
|
|
5454
|
+
if (event.kind === "message_committed" && event.message.role === "interaction") {
|
|
5455
|
+
return;
|
|
5456
|
+
}
|
|
5457
|
+
const state = await getOrInitState(event.agentId);
|
|
5458
|
+
if (event.kind === "message_committed") {
|
|
5459
|
+
if (event.message.role === "user") {
|
|
5460
|
+
if (state.knownEntryIds.has(event.message.id)) return;
|
|
5461
|
+
const content = convertUserContent(event.message.content);
|
|
5462
|
+
const entry = {
|
|
5463
|
+
type: "message",
|
|
5464
|
+
id: event.message.id,
|
|
5465
|
+
parentId: state.lastEntryId,
|
|
5466
|
+
timestamp: event.message.createdAt,
|
|
5467
|
+
message: {
|
|
5468
|
+
role: "user",
|
|
5469
|
+
content,
|
|
5470
|
+
timestamp: toEpochMs(event.message.createdAt)
|
|
5471
|
+
}
|
|
5472
|
+
};
|
|
5473
|
+
writeSessionEntry(state, entry);
|
|
5474
|
+
} else if (event.message.role === "assistant") {
|
|
5475
|
+
if (state.knownEntryIds.has(event.message.id)) return;
|
|
5476
|
+
const model = event.message.model;
|
|
5477
|
+
const rawUsage = event.message.usage;
|
|
5478
|
+
if (model) {
|
|
5479
|
+
const isDifferentModel = !state.lastModel || state.lastModel.provider !== model.provider || state.lastModel.modelId !== model.id;
|
|
5480
|
+
if (isDifferentModel) {
|
|
5481
|
+
const modelChangeId = `${event.message.id}:model`;
|
|
5482
|
+
if (!state.knownEntryIds.has(modelChangeId)) {
|
|
5483
|
+
const modelChangeEntry = {
|
|
5484
|
+
type: "model_change",
|
|
5485
|
+
id: modelChangeId,
|
|
5486
|
+
parentId: state.lastEntryId,
|
|
5487
|
+
timestamp: event.message.createdAt,
|
|
5488
|
+
provider: model.provider,
|
|
5489
|
+
modelId: model.id
|
|
5490
|
+
};
|
|
5491
|
+
writeSessionEntry(state, modelChangeEntry);
|
|
5492
|
+
}
|
|
5493
|
+
state.lastModel = { provider: model.provider, modelId: model.id };
|
|
5494
|
+
}
|
|
5495
|
+
}
|
|
5496
|
+
const { parts, hasToolCall } = convertAssistantContent(
|
|
5497
|
+
event.message.content,
|
|
5498
|
+
(id, name, internalId) => {
|
|
5499
|
+
state.toolCallIdToName.set(id, name);
|
|
5500
|
+
if (internalId) state.toolCallIdToName.set(internalId, name);
|
|
5501
|
+
}
|
|
5502
|
+
);
|
|
5503
|
+
const assistantMessagePayload = {
|
|
5504
|
+
role: "assistant",
|
|
5505
|
+
content: parts,
|
|
5506
|
+
stopReason: hasToolCall ? "toolUse" : "stop",
|
|
5507
|
+
timestamp: toEpochMs(event.message.createdAt)
|
|
5508
|
+
};
|
|
5509
|
+
if (model || rawUsage) {
|
|
5510
|
+
if (model) {
|
|
5511
|
+
assistantMessagePayload.provider = model.provider;
|
|
5512
|
+
assistantMessagePayload.model = model.id;
|
|
5513
|
+
}
|
|
5514
|
+
const input = rawUsage?.inputTokens ?? 0;
|
|
5515
|
+
const output = rawUsage?.outputTokens ?? 0;
|
|
5516
|
+
const cacheRead = rawUsage?.cacheReadTokens ?? 0;
|
|
5517
|
+
const cacheWrite = rawUsage?.cacheWriteTokens ?? 0;
|
|
5518
|
+
const totalTokens = rawUsage?.totalTokens ?? input + output + cacheRead + cacheWrite;
|
|
5519
|
+
const cost = rawUsage?.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
5520
|
+
assistantMessagePayload.usage = {
|
|
5521
|
+
input,
|
|
5522
|
+
output,
|
|
5523
|
+
cacheRead,
|
|
5524
|
+
cacheWrite,
|
|
5525
|
+
...rawUsage?.cacheWrite1hTokens !== void 0 ? { cacheWrite1h: rawUsage.cacheWrite1hTokens } : {},
|
|
5526
|
+
...rawUsage?.reasoningTokens !== void 0 ? { reasoning: rawUsage.reasoningTokens } : {},
|
|
5527
|
+
totalTokens,
|
|
5528
|
+
cost
|
|
5529
|
+
};
|
|
5530
|
+
}
|
|
5531
|
+
const entry = {
|
|
5532
|
+
type: "message",
|
|
5533
|
+
id: event.message.id,
|
|
5534
|
+
parentId: state.lastEntryId,
|
|
5535
|
+
timestamp: event.message.createdAt,
|
|
5536
|
+
message: assistantMessagePayload
|
|
5537
|
+
};
|
|
5538
|
+
writeSessionEntry(state, entry);
|
|
5539
|
+
} else if (event.message.role === "tool") {
|
|
5540
|
+
for (let index = 0; index < event.message.content.length; index++) {
|
|
5541
|
+
const part = event.message.content[index];
|
|
5542
|
+
const entryId = `${event.message.id}:${index}`;
|
|
5543
|
+
if (state.knownEntryIds.has(entryId)) continue;
|
|
5544
|
+
const toolCallId = part.providerToolCallId ?? part.toolCallId;
|
|
5545
|
+
const toolName = state.toolCallIdToName.get(toolCallId) ?? state.toolCallIdToName.get(part.toolCallId) ?? "unknown";
|
|
5546
|
+
const isError = Boolean(
|
|
5547
|
+
part.result.isError ?? (part.result.ok !== void 0 ? !part.result.ok : Boolean(part.result.error))
|
|
5548
|
+
);
|
|
5549
|
+
const content = convertToolResultContent(part.result.content);
|
|
5550
|
+
const entry = {
|
|
5551
|
+
type: "message",
|
|
5552
|
+
id: entryId,
|
|
5553
|
+
parentId: state.lastEntryId,
|
|
5554
|
+
timestamp: event.message.createdAt,
|
|
5555
|
+
message: {
|
|
5556
|
+
role: "toolResult",
|
|
5557
|
+
toolCallId,
|
|
5558
|
+
toolName,
|
|
5559
|
+
content,
|
|
5560
|
+
isError,
|
|
5561
|
+
timestamp: toEpochMs(event.message.createdAt)
|
|
5562
|
+
}
|
|
5563
|
+
};
|
|
5564
|
+
writeSessionEntry(state, entry);
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5567
|
+
} else if (event.kind === "message_revised") {
|
|
5568
|
+
const message = event.message;
|
|
5569
|
+
const revision = message.messageRevision ?? 1;
|
|
5570
|
+
const entryId = `${message.id}@${revision}`;
|
|
5571
|
+
if (state.knownEntryIds.has(entryId)) return;
|
|
5572
|
+
const parentId = state.entryIdToParentId.get(message.id) ?? null;
|
|
5573
|
+
const timestampIso = message.createdAt ?? event.createdAt;
|
|
5574
|
+
const content = convertUserContent(message.content);
|
|
5575
|
+
const entry = {
|
|
5576
|
+
type: "message",
|
|
5577
|
+
id: entryId,
|
|
5578
|
+
parentId,
|
|
5579
|
+
timestamp: timestampIso,
|
|
5580
|
+
message: {
|
|
5581
|
+
role: "user",
|
|
5582
|
+
content,
|
|
5583
|
+
timestamp: toEpochMs(timestampIso)
|
|
5584
|
+
}
|
|
5585
|
+
};
|
|
5586
|
+
writeSessionEntry(state, entry);
|
|
5587
|
+
}
|
|
5588
|
+
} catch (error) {
|
|
5589
|
+
console.error("Failed to write session file entry:", error);
|
|
5590
|
+
}
|
|
5591
|
+
}
|
|
5592
|
+
return runtime.consume({ consumerId: "rowan:session-files", signal: new AbortController().signal, onEvent });
|
|
5593
|
+
}
|
|
5594
|
+
|
|
5254
5595
|
// src/runtime/transient-run-events.ts
|
|
5255
5596
|
var MAX_BUFFERED_EVENTS = 128;
|
|
5256
5597
|
var MAX_BUFFERED_TEXT = 64 * 1024;
|
|
@@ -5485,6 +5826,9 @@ var InMemoryExtensionHost = class {
|
|
|
5485
5826
|
globalState = /* @__PURE__ */ new Map();
|
|
5486
5827
|
listeners = /* @__PURE__ */ new Set();
|
|
5487
5828
|
constructor(options = {}) {
|
|
5829
|
+
if (options.extendApi) {
|
|
5830
|
+
this.extendApi = options.extendApi;
|
|
5831
|
+
}
|
|
5488
5832
|
if (options.configs) {
|
|
5489
5833
|
for (const [scopeKey, extMap] of Object.entries(options.configs)) {
|
|
5490
5834
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -5607,7 +5951,7 @@ function scopeToKey(scope) {
|
|
|
5607
5951
|
|
|
5608
5952
|
// src/extensions/runner.ts
|
|
5609
5953
|
import { execFile } from "child_process";
|
|
5610
|
-
import { dirname as
|
|
5954
|
+
import { dirname as dirname6, resolve as resolve5 } from "path";
|
|
5611
5955
|
import {
|
|
5612
5956
|
registerModel,
|
|
5613
5957
|
unregisterProviderModels,
|
|
@@ -5770,8 +6114,6 @@ var ExtensionRunner = class {
|
|
|
5770
6114
|
errorListeners = /* @__PURE__ */ new Set();
|
|
5771
6115
|
// Capability change listeners
|
|
5772
6116
|
capabilityListeners = /* @__PURE__ */ new Set();
|
|
5773
|
-
// Host contribution change listeners
|
|
5774
|
-
hostContributionListeners = /* @__PURE__ */ new Set();
|
|
5775
6117
|
/** Current agent context — set by the agent before each phase */
|
|
5776
6118
|
currentContext;
|
|
5777
6119
|
constructor(options) {
|
|
@@ -5869,18 +6211,19 @@ var ExtensionRunner = class {
|
|
|
5869
6211
|
async loadExtensions(extensions) {
|
|
5870
6212
|
for (const ext of extensions) {
|
|
5871
6213
|
const extensionId = ext.id ?? ext.manifest?.id ?? ext.name;
|
|
6214
|
+
const hostApi = this.host.extendApi?.(extensionId);
|
|
5872
6215
|
const extension = {
|
|
5873
6216
|
id: extensionId,
|
|
5874
6217
|
path: ext.path,
|
|
5875
6218
|
tools: /* @__PURE__ */ new Map(),
|
|
5876
6219
|
phases: /* @__PURE__ */ new Set(),
|
|
5877
6220
|
capabilities: /* @__PURE__ */ new Map(),
|
|
5878
|
-
hostContributions: /* @__PURE__ */ new Map(),
|
|
5879
6221
|
cleanup: [],
|
|
5880
|
-
runtime: createExtensionRuntime()
|
|
6222
|
+
runtime: createExtensionRuntime(),
|
|
6223
|
+
hostApi
|
|
5881
6224
|
};
|
|
5882
6225
|
try {
|
|
5883
|
-
const api = this.createExtensionAPI(extension, ext.manifest);
|
|
6226
|
+
const api = this.createExtensionAPI(extension, ext.manifest, hostApi?.namespaces);
|
|
5884
6227
|
const disposer = await ext.factory(api);
|
|
5885
6228
|
if (typeof disposer === "function") extension.disposer = disposer;
|
|
5886
6229
|
this.extensions.push(extension);
|
|
@@ -5888,9 +6231,6 @@ var ExtensionRunner = class {
|
|
|
5888
6231
|
if (extension.capabilities.size > 0) {
|
|
5889
6232
|
this.notifyCapabilitiesChanged();
|
|
5890
6233
|
}
|
|
5891
|
-
if (extension.hostContributions.size > 0) {
|
|
5892
|
-
this.notifyHostContributionsChanged();
|
|
5893
|
-
}
|
|
5894
6234
|
} catch (error) {
|
|
5895
6235
|
await this.rollbackExtension(extension);
|
|
5896
6236
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -6019,24 +6359,6 @@ var ExtensionRunner = class {
|
|
|
6019
6359
|
this.capabilityListeners.add(listener);
|
|
6020
6360
|
return () => this.capabilityListeners.delete(listener);
|
|
6021
6361
|
}
|
|
6022
|
-
/** Get all contributed host elements across all extensions. */
|
|
6023
|
-
getHostContributions() {
|
|
6024
|
-
const result = [];
|
|
6025
|
-
for (const ext of this.extensions) {
|
|
6026
|
-
for (const contrib of ext.hostContributions.values()) {
|
|
6027
|
-
result.push(contrib);
|
|
6028
|
-
}
|
|
6029
|
-
}
|
|
6030
|
-
return Object.freeze(result);
|
|
6031
|
-
}
|
|
6032
|
-
/**
|
|
6033
|
-
* Subscribe to host contribution changes (contributions added, removed, or extensions disposed).
|
|
6034
|
-
* Returns an unsubscribe function.
|
|
6035
|
-
*/
|
|
6036
|
-
onHostContributionsChanged(listener) {
|
|
6037
|
-
this.hostContributionListeners.add(listener);
|
|
6038
|
-
return () => this.hostContributionListeners.delete(listener);
|
|
6039
|
-
}
|
|
6040
6362
|
triggerUiAction(event) {
|
|
6041
6363
|
this.events.emit("ui.action", event);
|
|
6042
6364
|
}
|
|
@@ -6197,7 +6519,7 @@ var ExtensionRunner = class {
|
|
|
6197
6519
|
* Registration methods write to the extension tracking object.
|
|
6198
6520
|
* Action methods delegate to the shared runtime.
|
|
6199
6521
|
*/
|
|
6200
|
-
createExtensionAPI(extension, manifest) {
|
|
6522
|
+
createExtensionAPI(extension, manifest, namespaces) {
|
|
6201
6523
|
const runner = this;
|
|
6202
6524
|
const extContext = {
|
|
6203
6525
|
get cwd() {
|
|
@@ -6254,9 +6576,9 @@ var ExtensionRunner = class {
|
|
|
6254
6576
|
registerTool: (tool) => this.registerTool(extension, tool),
|
|
6255
6577
|
unregisterTool: (toolName) => this.unregisterTool(extension, toolName),
|
|
6256
6578
|
contributeCapability: (contribution) => this.contributeCapability(extension, contribution),
|
|
6257
|
-
contributeToHost: (contribution) => this.contributeToHost(extension, contribution),
|
|
6258
6579
|
context: extContext,
|
|
6259
6580
|
manifest,
|
|
6581
|
+
namespaces,
|
|
6260
6582
|
trackCleanup: (cleanup) => extension.cleanup.push(cleanup),
|
|
6261
6583
|
config: {
|
|
6262
6584
|
get: async (scope) => {
|
|
@@ -6364,44 +6686,6 @@ var ExtensionRunner = class {
|
|
|
6364
6686
|
}
|
|
6365
6687
|
}
|
|
6366
6688
|
}
|
|
6367
|
-
contributeToHost(extension, contribution) {
|
|
6368
|
-
const key = `${contribution.kind}:${contribution.id}`;
|
|
6369
|
-
const entry = {
|
|
6370
|
-
...contribution
|
|
6371
|
-
};
|
|
6372
|
-
extension.hostContributions.set(key, entry);
|
|
6373
|
-
if (this.extensions.includes(extension)) {
|
|
6374
|
-
this.notifyHostContributionsChanged();
|
|
6375
|
-
}
|
|
6376
|
-
let disposed = false;
|
|
6377
|
-
const dispose = () => {
|
|
6378
|
-
if (disposed) return;
|
|
6379
|
-
disposed = true;
|
|
6380
|
-
if (extension.hostContributions.get(key) === entry) {
|
|
6381
|
-
extension.hostContributions.delete(key);
|
|
6382
|
-
if (this.extensions.includes(extension)) {
|
|
6383
|
-
this.notifyHostContributionsChanged();
|
|
6384
|
-
}
|
|
6385
|
-
}
|
|
6386
|
-
};
|
|
6387
|
-
extension.cleanup.push(dispose);
|
|
6388
|
-
return dispose;
|
|
6389
|
-
}
|
|
6390
|
-
notifyHostContributionsChanged() {
|
|
6391
|
-
const contributions = this.getHostContributions();
|
|
6392
|
-
for (const listener of this.hostContributionListeners) {
|
|
6393
|
-
try {
|
|
6394
|
-
listener(contributions);
|
|
6395
|
-
} catch (error) {
|
|
6396
|
-
this.emitError({
|
|
6397
|
-
extensionPath: "<runtime>",
|
|
6398
|
-
event: "host_contributions_changed",
|
|
6399
|
-
error: error instanceof Error ? error.message : String(error),
|
|
6400
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
6401
|
-
});
|
|
6402
|
-
}
|
|
6403
|
-
}
|
|
6404
|
-
}
|
|
6405
6689
|
async registerPhase(extension, registration) {
|
|
6406
6690
|
if (typeof registration === "string") {
|
|
6407
6691
|
if (registration.length === 0) {
|
|
@@ -6436,7 +6720,7 @@ var ExtensionRunner = class {
|
|
|
6436
6720
|
}
|
|
6437
6721
|
}
|
|
6438
6722
|
async loadRegisteredPhase(extension, registration) {
|
|
6439
|
-
const extensionBase = extension.path.startsWith("<") ? this.cwd :
|
|
6723
|
+
const extensionBase = extension.path.startsWith("<") ? this.cwd : dirname6(extension.path);
|
|
6440
6724
|
const phase = await loadPhase(resolve5(extensionBase, registration));
|
|
6441
6725
|
const name = phase.name;
|
|
6442
6726
|
if (this.phases.has(name)) {
|
|
@@ -6490,21 +6774,21 @@ var ExtensionRunner = class {
|
|
|
6490
6774
|
for (const name of extension.phases) this.phases.delete(name);
|
|
6491
6775
|
const hadCapabilities = extension.capabilities.size > 0;
|
|
6492
6776
|
extension.capabilities.clear();
|
|
6493
|
-
const hadHostContributions = extension.hostContributions.size > 0;
|
|
6494
|
-
extension.hostContributions.clear();
|
|
6495
6777
|
for (const cleanup of [...extension.cleanup].reverse()) {
|
|
6496
6778
|
await Promise.resolve().then(() => cleanup()).catch(() => void 0);
|
|
6497
6779
|
}
|
|
6498
6780
|
if (extension.disposer) {
|
|
6499
6781
|
await Promise.resolve().then(() => extension.disposer()).catch(() => void 0);
|
|
6500
6782
|
}
|
|
6783
|
+
if (extension.hostApi?.dispose) {
|
|
6784
|
+
const hostDispose = extension.hostApi.dispose;
|
|
6785
|
+
extension.hostApi = { ...extension.hostApi, dispose: void 0 };
|
|
6786
|
+
await Promise.resolve().then(() => hostDispose()).catch(() => void 0);
|
|
6787
|
+
}
|
|
6501
6788
|
this._phaseCache = null;
|
|
6502
6789
|
if (hadCapabilities) {
|
|
6503
6790
|
this.notifyCapabilitiesChanged();
|
|
6504
6791
|
}
|
|
6505
|
-
if (hadHostContributions) {
|
|
6506
|
-
this.notifyHostContributionsChanged();
|
|
6507
|
-
}
|
|
6508
6792
|
}
|
|
6509
6793
|
};
|
|
6510
6794
|
function createExtensionRunner(options) {
|
|
@@ -6512,10 +6796,10 @@ function createExtensionRunner(options) {
|
|
|
6512
6796
|
}
|
|
6513
6797
|
|
|
6514
6798
|
// src/extensions/loader.ts
|
|
6515
|
-
import { existsSync as
|
|
6799
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
|
|
6516
6800
|
import { readdir as readdir3, readFile as readFile3, stat as stat2 } from "fs/promises";
|
|
6517
6801
|
import { fileURLToPath } from "url";
|
|
6518
|
-
import { basename as basename3, dirname as
|
|
6802
|
+
import { basename as basename3, dirname as dirname7, extname as extname2, join as join4, resolve as resolve6 } from "path";
|
|
6519
6803
|
import { createJiti } from "jiti";
|
|
6520
6804
|
function isExtensionFile(path) {
|
|
6521
6805
|
const extension = extname2(path).toLowerCase();
|
|
@@ -6525,12 +6809,12 @@ function isSyntheticPath(path) {
|
|
|
6525
6809
|
return path.startsWith("<") && path.endsWith(">");
|
|
6526
6810
|
}
|
|
6527
6811
|
function readManifestSync(dir) {
|
|
6528
|
-
const manifestPath =
|
|
6529
|
-
if (!
|
|
6812
|
+
const manifestPath = join4(dir, "package.json");
|
|
6813
|
+
if (!existsSync4(manifestPath)) {
|
|
6530
6814
|
return void 0;
|
|
6531
6815
|
}
|
|
6532
6816
|
try {
|
|
6533
|
-
const content =
|
|
6817
|
+
const content = readFileSync2(manifestPath, "utf8");
|
|
6534
6818
|
const pkg = JSON.parse(content);
|
|
6535
6819
|
const rowan = pkg.rowan;
|
|
6536
6820
|
if (!rowan) return void 0;
|
|
@@ -6549,7 +6833,7 @@ function jitiAliases() {
|
|
|
6549
6833
|
return {};
|
|
6550
6834
|
}
|
|
6551
6835
|
const agentSourcePath = fileURLToPath(new URL("../index.ts", moduleUrl));
|
|
6552
|
-
if (!
|
|
6836
|
+
if (!existsSync4(agentSourcePath)) {
|
|
6553
6837
|
return {};
|
|
6554
6838
|
}
|
|
6555
6839
|
return { "@rowan-agent/agent": agentSourcePath };
|
|
@@ -6573,21 +6857,21 @@ async function loadExtensionModule(extensionPath) {
|
|
|
6573
6857
|
return typeof module === "function" ? module : void 0;
|
|
6574
6858
|
}
|
|
6575
6859
|
async function readPackageManifest(path) {
|
|
6576
|
-
if (!
|
|
6860
|
+
if (!existsSync4(path)) {
|
|
6577
6861
|
return void 0;
|
|
6578
6862
|
}
|
|
6579
6863
|
const content = await readFile3(path, "utf8");
|
|
6580
6864
|
return JSON.parse(content);
|
|
6581
6865
|
}
|
|
6582
6866
|
async function resolveExtensionEntries(dir) {
|
|
6583
|
-
const manifest = await readPackageManifest(
|
|
6867
|
+
const manifest = await readPackageManifest(join4(dir, "package.json"));
|
|
6584
6868
|
const declared = manifest?.rowan?.extensions;
|
|
6585
6869
|
if (declared && declared.length > 0) {
|
|
6586
6870
|
return declared.map((entry) => resolve6(dir, entry));
|
|
6587
6871
|
}
|
|
6588
6872
|
for (const name of ["index.ts", "index.js"]) {
|
|
6589
|
-
const entry =
|
|
6590
|
-
if (
|
|
6873
|
+
const entry = join4(dir, name);
|
|
6874
|
+
if (existsSync4(entry)) {
|
|
6591
6875
|
return [entry];
|
|
6592
6876
|
}
|
|
6593
6877
|
}
|
|
@@ -6602,7 +6886,7 @@ async function discoverExtensionsInDir(dir) {
|
|
|
6602
6886
|
});
|
|
6603
6887
|
const paths = [];
|
|
6604
6888
|
for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
6605
|
-
const entryPath =
|
|
6889
|
+
const entryPath = join4(dir, entry.name);
|
|
6606
6890
|
if ((entry.isFile() || entry.isSymbolicLink()) && isExtensionFile(entry.name)) {
|
|
6607
6891
|
paths.push(entryPath);
|
|
6608
6892
|
continue;
|
|
@@ -6622,8 +6906,8 @@ async function discoverExtensionsInDir(dir) {
|
|
|
6622
6906
|
function loadExtensionFromFactory(factory, cwd, extensionPath = "<inline>", options = {}) {
|
|
6623
6907
|
const resolvedCwd = resolve6(cwd);
|
|
6624
6908
|
const resolvedPath = isSyntheticPath(extensionPath) ? extensionPath : resolve6(resolvedCwd, extensionPath);
|
|
6625
|
-
const name = options.name ?? (isSyntheticPath(extensionPath) ? extensionPath : basename3(
|
|
6626
|
-
const manifestDir = isSyntheticPath(extensionPath) ? resolvedCwd :
|
|
6909
|
+
const name = options.name ?? (isSyntheticPath(extensionPath) ? extensionPath : basename3(dirname7(resolvedPath)) || "unknown");
|
|
6910
|
+
const manifestDir = isSyntheticPath(extensionPath) ? resolvedCwd : dirname7(resolvedPath);
|
|
6627
6911
|
const manifest = readManifestSync(manifestDir);
|
|
6628
6912
|
const id = options.id ?? manifest?.id ?? name;
|
|
6629
6913
|
return {
|
|
@@ -6663,7 +6947,7 @@ async function loadExtensionsFromPath(path) {
|
|
|
6663
6947
|
const resolvedPath = resolve6(path);
|
|
6664
6948
|
const info = await stat2(resolvedPath);
|
|
6665
6949
|
if (!info.isDirectory()) {
|
|
6666
|
-
return loadExtensions([resolvedPath],
|
|
6950
|
+
return loadExtensions([resolvedPath], dirname7(resolvedPath));
|
|
6667
6951
|
}
|
|
6668
6952
|
const entries = await resolveExtensionEntries(resolvedPath) ?? await discoverExtensionsInDir(resolvedPath);
|
|
6669
6953
|
return loadExtensions(entries, resolvedPath);
|
|
@@ -6671,7 +6955,7 @@ async function loadExtensionsFromPath(path) {
|
|
|
6671
6955
|
|
|
6672
6956
|
// src/runtime/resource-registry.ts
|
|
6673
6957
|
import { stat as stat3, readdir as readdir4 } from "fs/promises";
|
|
6674
|
-
import { join as
|
|
6958
|
+
import { join as join5, resolve as resolve7 } from "path";
|
|
6675
6959
|
var ResourceRegistryError = class extends Error {
|
|
6676
6960
|
code;
|
|
6677
6961
|
constructor(code, message) {
|
|
@@ -6989,7 +7273,7 @@ async function loadDirectoryValues(kind, directory, sourceId) {
|
|
|
6989
7273
|
if (rootInfo.isFile()) {
|
|
6990
7274
|
targets.push(root);
|
|
6991
7275
|
} else if (rootInfo.isDirectory()) {
|
|
6992
|
-
const markerAtRoot =
|
|
7276
|
+
const markerAtRoot = join5(root, marker);
|
|
6993
7277
|
try {
|
|
6994
7278
|
const markerInfo = await stat3(markerAtRoot);
|
|
6995
7279
|
if (markerInfo.isFile()) targets.push(markerAtRoot);
|
|
@@ -7011,7 +7295,7 @@ async function loadDirectoryValues(kind, directory, sourceId) {
|
|
|
7011
7295
|
}
|
|
7012
7296
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
7013
7297
|
if (!entry.isDirectory()) continue;
|
|
7014
|
-
const target =
|
|
7298
|
+
const target = join5(root, entry.name, marker);
|
|
7015
7299
|
try {
|
|
7016
7300
|
const targetInfo = await stat3(target);
|
|
7017
7301
|
if (targetInfo.isFile()) targets.push(target);
|
|
@@ -7267,7 +7551,7 @@ async function spillLargeToolResult(result, archiveDir, toolName) {
|
|
|
7267
7551
|
await mkdir2(toolDir, { recursive: true, mode: 448 });
|
|
7268
7552
|
await chmod2(toolDir, 448).catch(() => void 0);
|
|
7269
7553
|
const safeToolName = toolName.replace(/[^a-zA-Z0-9._-]+/g, "_");
|
|
7270
|
-
const path =
|
|
7554
|
+
const path = join6(toolDir, `rowan-${safeToolName}-${Date.now()}-${randomUUID()}.log`);
|
|
7271
7555
|
await writeFile2(path, serialized, { encoding: "utf8", mode: 384 });
|
|
7272
7556
|
await chmod2(path, 384).catch(() => void 0);
|
|
7273
7557
|
const preview = new TextDecoder().decode(bytes.subarray(0, MAX_INLINE_TOOL_RESULT_BYTES));
|
|
@@ -7364,6 +7648,9 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
7364
7648
|
await options.bootstrap?.(runtime.resources);
|
|
7365
7649
|
runtime.startHeartbeat();
|
|
7366
7650
|
void runtime.pump();
|
|
7651
|
+
if (options.sessionFiles) {
|
|
7652
|
+
await startSessionFilesConsumer(runtime, options.sessionFiles);
|
|
7653
|
+
}
|
|
7367
7654
|
return runtime;
|
|
7368
7655
|
} catch (error) {
|
|
7369
7656
|
await runtime.resources.closeExtensions().catch(() => void 0);
|
|
@@ -7624,14 +7911,6 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
7624
7911
|
this.assertOpen();
|
|
7625
7912
|
return this.resources.extensionRunner.onCapabilitiesChanged(listener);
|
|
7626
7913
|
}
|
|
7627
|
-
listHostContributions() {
|
|
7628
|
-
this.assertOpen();
|
|
7629
|
-
return this.resources.extensionRunner.getHostContributions();
|
|
7630
|
-
}
|
|
7631
|
-
onHostContributionsChanged(listener) {
|
|
7632
|
-
this.assertOpen();
|
|
7633
|
-
return this.resources.extensionRunner.onHostContributionsChanged(listener);
|
|
7634
|
-
}
|
|
7635
7914
|
triggerUiAction(event) {
|
|
7636
7915
|
this.assertOpen();
|
|
7637
7916
|
this.resources.extensionRunner.triggerUiAction(event);
|
|
@@ -8108,7 +8387,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8108
8387
|
onContext: assembly.setContext,
|
|
8109
8388
|
runtime: {
|
|
8110
8389
|
interact: (request) => this.liveInteract(run.id, request, controller.signal),
|
|
8111
|
-
tools: ({ toolCall, contentBlocks, driver, options, providerInitiated }) => {
|
|
8390
|
+
tools: ({ toolCall, contentBlocks, driver, options, providerInitiated, model: callModel, usage: callUsage }) => {
|
|
8112
8391
|
const task = toolQueue.then(async () => {
|
|
8113
8392
|
if (!providerInitiated) {
|
|
8114
8393
|
const execution = await this.executeToolBatch({
|
|
@@ -8122,6 +8401,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8122
8401
|
signal: controller.signal,
|
|
8123
8402
|
driver,
|
|
8124
8403
|
options,
|
|
8404
|
+
model: callModel ?? model,
|
|
8405
|
+
usage: callUsage,
|
|
8125
8406
|
onRevision: (rev) => {
|
|
8126
8407
|
executionRevision = rev;
|
|
8127
8408
|
}
|
|
@@ -8146,6 +8427,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8146
8427
|
options,
|
|
8147
8428
|
providerInitiated: true,
|
|
8148
8429
|
interactionIds,
|
|
8430
|
+
model: callModel ?? model,
|
|
8431
|
+
usage: callUsage,
|
|
8149
8432
|
onRevision: (rev) => {
|
|
8150
8433
|
executionRevision = rev;
|
|
8151
8434
|
}
|
|
@@ -8236,7 +8519,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8236
8519
|
toolQueue = task.then(() => void 0, () => void 0);
|
|
8237
8520
|
return task;
|
|
8238
8521
|
},
|
|
8239
|
-
toolsBatch: ({ toolCalls, contentBlocks, driver, options }) => {
|
|
8522
|
+
toolsBatch: ({ toolCalls, contentBlocks, driver, options, model: batchModel, usage: batchUsage }) => {
|
|
8240
8523
|
const task = toolQueue.then(async () => {
|
|
8241
8524
|
const execution = await this.executeToolBatch({
|
|
8242
8525
|
run,
|
|
@@ -8249,6 +8532,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8249
8532
|
signal: controller.signal,
|
|
8250
8533
|
driver,
|
|
8251
8534
|
options,
|
|
8535
|
+
model: batchModel ?? model,
|
|
8536
|
+
usage: batchUsage,
|
|
8252
8537
|
onRevision: (rev) => {
|
|
8253
8538
|
executionRevision = rev;
|
|
8254
8539
|
}
|
|
@@ -8476,6 +8761,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8476
8761
|
expectedRevision: revision,
|
|
8477
8762
|
requestMessageId: createId("msg"),
|
|
8478
8763
|
contentBlocks: input.contentBlocks,
|
|
8764
|
+
...input.model ? { model: input.model } : {},
|
|
8765
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8479
8766
|
calls: input.toolCalls.map((tc, i) => ({
|
|
8480
8767
|
toolCallId: toolCallIds[i],
|
|
8481
8768
|
providerToolCallId: tc.id,
|
|
@@ -8611,6 +8898,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8611
8898
|
expectedRevision: revision,
|
|
8612
8899
|
requestMessageId: createId("msg"),
|
|
8613
8900
|
contentBlocks: input.contentBlocks,
|
|
8901
|
+
...input.model ? { model: input.model } : {},
|
|
8902
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8614
8903
|
calls: [{
|
|
8615
8904
|
toolCallId,
|
|
8616
8905
|
providerToolCallId,
|
|
@@ -8708,6 +8997,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8708
8997
|
expectedRevision: revision,
|
|
8709
8998
|
requestMessageId: createId("msg"),
|
|
8710
8999
|
contentBlocks: input.contentBlocks,
|
|
9000
|
+
...input.model ? { model: input.model } : {},
|
|
9001
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8711
9002
|
calls: [{
|
|
8712
9003
|
toolCallId,
|
|
8713
9004
|
providerToolCallId,
|
|
@@ -8729,6 +9020,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8729
9020
|
expectedRevision: revision,
|
|
8730
9021
|
requestMessageId: createId("msg"),
|
|
8731
9022
|
contentBlocks: input.contentBlocks,
|
|
9023
|
+
...input.model ? { model: input.model } : {},
|
|
9024
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8732
9025
|
calls: [{
|
|
8733
9026
|
toolCallId,
|
|
8734
9027
|
providerToolCallId,
|
|
@@ -8783,6 +9076,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8783
9076
|
expectedRevision: revision,
|
|
8784
9077
|
requestMessageId: createId("msg"),
|
|
8785
9078
|
contentBlocks: input.contentBlocks,
|
|
9079
|
+
...input.model ? { model: input.model } : {},
|
|
9080
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8786
9081
|
calls: [{
|
|
8787
9082
|
toolCallId,
|
|
8788
9083
|
providerToolCallId,
|
|
@@ -8832,6 +9127,8 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
8832
9127
|
expectedRevision: revision,
|
|
8833
9128
|
requestMessageId: createId("msg"),
|
|
8834
9129
|
contentBlocks: input.contentBlocks,
|
|
9130
|
+
...input.model ? { model: input.model } : {},
|
|
9131
|
+
...input.usage ? { usage: input.usage } : {},
|
|
8835
9132
|
calls: [{
|
|
8836
9133
|
toolCallId,
|
|
8837
9134
|
providerToolCallId,
|
|
@@ -9156,7 +9453,7 @@ ${content}`;
|
|
|
9156
9453
|
archiveDirFor(agentId) {
|
|
9157
9454
|
const store = this.owned;
|
|
9158
9455
|
const archiveDir = store.contextArchiveDir?.(agentId);
|
|
9159
|
-
return archiveDir ?
|
|
9456
|
+
return archiveDir ? join6(archiveDir, "tool-results") : void 0;
|
|
9160
9457
|
}
|
|
9161
9458
|
async runConsumer(subscription) {
|
|
9162
9459
|
const registration = await this.owned.openConsumer(subscription.consumerId);
|
|
@@ -10314,6 +10611,8 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
10314
10611
|
execution: input.execution,
|
|
10315
10612
|
expectedRevision: input.expectedRevision,
|
|
10316
10613
|
requestMessageId: input.requestMessageId,
|
|
10614
|
+
...input.model ? { model: input.model } : {},
|
|
10615
|
+
...input.usage ? { usage: input.usage } : {},
|
|
10317
10616
|
calls: [{
|
|
10318
10617
|
providerToolCallId,
|
|
10319
10618
|
name: input.name,
|
|
@@ -10345,7 +10644,9 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
10345
10644
|
input.execution.executionId,
|
|
10346
10645
|
input.requestMessageId,
|
|
10347
10646
|
input.calls,
|
|
10348
|
-
input.contentBlocks ?? null
|
|
10647
|
+
input.contentBlocks ?? null,
|
|
10648
|
+
input.model ?? null,
|
|
10649
|
+
input.usage ?? null
|
|
10349
10650
|
]);
|
|
10350
10651
|
const replay = this.replayOperation(operationKey, operationPayload);
|
|
10351
10652
|
if (replay) return clone(replay);
|
|
@@ -10387,7 +10688,9 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
10387
10688
|
role: "assistant",
|
|
10388
10689
|
content: requestMessageContent(toolCalls, input.contentBlocks),
|
|
10389
10690
|
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
10390
|
-
createdAt: timestamp
|
|
10691
|
+
createdAt: timestamp,
|
|
10692
|
+
...input.model ? { model: input.model } : {},
|
|
10693
|
+
...input.usage ? { usage: input.usage } : {}
|
|
10391
10694
|
};
|
|
10392
10695
|
for (const toolCall of toolCalls) this.storeToolCall(toolCall);
|
|
10393
10696
|
this.storeMessage(requestMessage);
|
|
@@ -11439,8 +11742,8 @@ function requestMessageContent(toolCalls, contentBlocks) {
|
|
|
11439
11742
|
|
|
11440
11743
|
// src/runtime/sqlite-durable-store.ts
|
|
11441
11744
|
import { Database } from "bun:sqlite";
|
|
11442
|
-
import { appendFileSync, chmodSync, mkdirSync, readFileSync as
|
|
11443
|
-
import { dirname as
|
|
11745
|
+
import { appendFileSync as appendFileSync2, chmodSync as chmodSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync } from "fs";
|
|
11746
|
+
import { dirname as dirname8, join as join7, resolve as resolve8 } from "path";
|
|
11444
11747
|
import { tmpdir as tmpdir2 } from "os";
|
|
11445
11748
|
var SCHEMA_ID = "rowan.agent.runtime";
|
|
11446
11749
|
var SCHEMA_VERSION = "2";
|
|
@@ -11661,7 +11964,7 @@ var SqliteStore = class {
|
|
|
11661
11964
|
stmtUpdateState;
|
|
11662
11965
|
constructor(filename = ":memory:") {
|
|
11663
11966
|
this.database = new Database(filename, { create: true, readwrite: true, strict: true });
|
|
11664
|
-
this.archiveRoot = filename === ":memory:" ?
|
|
11967
|
+
this.archiveRoot = filename === ":memory:" ? join7(tmpdir2(), `rowan-context-archives-${crypto.randomUUID()}`) : join7(dirname8(resolve8(filename)), "context-archives");
|
|
11665
11968
|
}
|
|
11666
11969
|
async openOwner(input) {
|
|
11667
11970
|
this.assertOpen();
|
|
@@ -11755,7 +12058,7 @@ var SqliteStore = class {
|
|
|
11755
12058
|
}
|
|
11756
12059
|
/** Filesystem location owned by this Store for one Agent's readable archive. */
|
|
11757
12060
|
contextArchiveDir(agentId) {
|
|
11758
|
-
return
|
|
12061
|
+
return join7(this.archiveRoot, String(agentId));
|
|
11759
12062
|
}
|
|
11760
12063
|
async reserveAgent(lease, input) {
|
|
11761
12064
|
return this.invoke(lease, (store, current) => store.reserveAgent(current, input));
|
|
@@ -12351,7 +12654,7 @@ var SqliteStore = class {
|
|
|
12351
12654
|
mirrorChanges(tracker) {
|
|
12352
12655
|
for (const agentId of tracker.deletedAgentIds) {
|
|
12353
12656
|
const idStr = String(agentId);
|
|
12354
|
-
rmSync(
|
|
12657
|
+
rmSync(join7(this.archiveRoot, idStr), { recursive: true, force: true });
|
|
12355
12658
|
this.mirroredEventIds.delete(idStr);
|
|
12356
12659
|
this.mirroredCompactionIds.delete(idStr);
|
|
12357
12660
|
this.mirroredAgents.delete(idStr);
|
|
@@ -12359,15 +12662,15 @@ var SqliteStore = class {
|
|
|
12359
12662
|
for (const agent of tracker.upsertedAgents.values()) {
|
|
12360
12663
|
const idStr = String(agent.id);
|
|
12361
12664
|
this.mirroredAgents.add(idStr);
|
|
12362
|
-
const archiveDir =
|
|
12363
|
-
const toolDir =
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12665
|
+
const archiveDir = join7(this.archiveRoot, idStr);
|
|
12666
|
+
const toolDir = join7(archiveDir, "tool-results");
|
|
12667
|
+
mkdirSync2(toolDir, { recursive: true, mode: 448 });
|
|
12668
|
+
chmodSync2(archiveDir, 448);
|
|
12669
|
+
chmodSync2(toolDir, 448);
|
|
12367
12670
|
}
|
|
12368
12671
|
if (tracker.appendedEvents.length > 0) {
|
|
12369
|
-
|
|
12370
|
-
|
|
12672
|
+
mkdirSync2(this.archiveRoot, { recursive: true, mode: 448 });
|
|
12673
|
+
chmodSync2(this.archiveRoot, 448);
|
|
12371
12674
|
const eventsByAgent = /* @__PURE__ */ new Map();
|
|
12372
12675
|
for (const event of tracker.appendedEvents) {
|
|
12373
12676
|
const agentId = String(event.agentId);
|
|
@@ -12379,22 +12682,22 @@ var SqliteStore = class {
|
|
|
12379
12682
|
list.push(event);
|
|
12380
12683
|
}
|
|
12381
12684
|
for (const [agentId, events] of eventsByAgent) {
|
|
12382
|
-
const archiveDir =
|
|
12383
|
-
const toolDir =
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
|
|
12387
|
-
const sessionPath =
|
|
12685
|
+
const archiveDir = join7(this.archiveRoot, agentId);
|
|
12686
|
+
const toolDir = join7(archiveDir, "tool-results");
|
|
12687
|
+
mkdirSync2(toolDir, { recursive: true, mode: 448 });
|
|
12688
|
+
chmodSync2(archiveDir, 448);
|
|
12689
|
+
chmodSync2(toolDir, 448);
|
|
12690
|
+
const sessionPath = join7(archiveDir, "session.jsonl");
|
|
12388
12691
|
try {
|
|
12389
|
-
|
|
12692
|
+
chmodSync2(sessionPath, 384);
|
|
12390
12693
|
} catch {
|
|
12391
12694
|
}
|
|
12392
12695
|
const known = this.mirroredEventIds.get(agentId) ?? /* @__PURE__ */ new Set();
|
|
12393
12696
|
const newEvents = events.filter((e) => !known.has(String(e.id)));
|
|
12394
12697
|
if (newEvents.length > 0) {
|
|
12395
12698
|
const lines = newEvents.map((e) => JSON.stringify({ schemaVersion: 1, kind: "rowan_event", event: e }) + "\n").join("");
|
|
12396
|
-
|
|
12397
|
-
|
|
12699
|
+
appendFileSync2(sessionPath, lines, { encoding: "utf8", mode: 384 });
|
|
12700
|
+
chmodSync2(sessionPath, 384);
|
|
12398
12701
|
for (const e of newEvents) known.add(String(e.id));
|
|
12399
12702
|
this.mirroredEventIds.set(agentId, known);
|
|
12400
12703
|
}
|
|
@@ -12403,13 +12706,13 @@ var SqliteStore = class {
|
|
|
12403
12706
|
if (tracker.upsertedContextCompactions.size > 0) {
|
|
12404
12707
|
for (const [agentId, record] of tracker.upsertedContextCompactions) {
|
|
12405
12708
|
const idStr = String(agentId);
|
|
12406
|
-
const archiveDir =
|
|
12407
|
-
const sessionPath =
|
|
12709
|
+
const archiveDir = join7(this.archiveRoot, idStr);
|
|
12710
|
+
const sessionPath = join7(archiveDir, "session.jsonl");
|
|
12408
12711
|
const knownCompactions = this.mirroredCompactionIds.get(idStr) ?? /* @__PURE__ */ new Set();
|
|
12409
12712
|
if (!knownCompactions.has(record.id)) {
|
|
12410
12713
|
const line = JSON.stringify({ schemaVersion: 1, kind: "context_compacted", record }) + "\n";
|
|
12411
|
-
|
|
12412
|
-
|
|
12714
|
+
appendFileSync2(sessionPath, line, { encoding: "utf8", mode: 384 });
|
|
12715
|
+
chmodSync2(sessionPath, 384);
|
|
12413
12716
|
knownCompactions.add(record.id);
|
|
12414
12717
|
this.mirroredCompactionIds.set(idStr, knownCompactions);
|
|
12415
12718
|
}
|
|
@@ -12418,32 +12721,32 @@ var SqliteStore = class {
|
|
|
12418
12721
|
}
|
|
12419
12722
|
/** Append the semantic durable event mirror and remove deleted Agent sidecars. */
|
|
12420
12723
|
mirrorInitialState(state) {
|
|
12421
|
-
|
|
12422
|
-
|
|
12724
|
+
mkdirSync2(this.archiveRoot, { recursive: true, mode: 448 });
|
|
12725
|
+
chmodSync2(this.archiveRoot, 448);
|
|
12423
12726
|
const currentAgents = new Set(state.agents.map((agent) => String(agent.id)));
|
|
12424
12727
|
for (const agentId of this.mirroredAgents) {
|
|
12425
12728
|
if (currentAgents.has(agentId)) continue;
|
|
12426
|
-
rmSync(
|
|
12729
|
+
rmSync(join7(this.archiveRoot, agentId), { recursive: true, force: true });
|
|
12427
12730
|
this.mirroredEventIds.delete(agentId);
|
|
12428
12731
|
this.mirroredCompactionIds.delete(agentId);
|
|
12429
12732
|
}
|
|
12430
12733
|
for (const agent of state.agents) {
|
|
12431
12734
|
const agentId = String(agent.id);
|
|
12432
|
-
const archiveDir =
|
|
12433
|
-
const toolDir =
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
const sessionPath =
|
|
12735
|
+
const archiveDir = join7(this.archiveRoot, agentId);
|
|
12736
|
+
const toolDir = join7(archiveDir, "tool-results");
|
|
12737
|
+
mkdirSync2(toolDir, { recursive: true, mode: 448 });
|
|
12738
|
+
chmodSync2(archiveDir, 448);
|
|
12739
|
+
chmodSync2(toolDir, 448);
|
|
12740
|
+
const sessionPath = join7(archiveDir, "session.jsonl");
|
|
12438
12741
|
try {
|
|
12439
|
-
|
|
12742
|
+
chmodSync2(sessionPath, 384);
|
|
12440
12743
|
} catch {
|
|
12441
12744
|
}
|
|
12442
12745
|
const known = this.mirroredEventIds.get(agentId) ?? /* @__PURE__ */ new Set();
|
|
12443
12746
|
const knownCompactions = this.mirroredCompactionIds.get(agentId) ?? /* @__PURE__ */ new Set();
|
|
12444
12747
|
if (known.size === 0 || knownCompactions.size === 0) {
|
|
12445
12748
|
try {
|
|
12446
|
-
for (const line of
|
|
12749
|
+
for (const line of readFileSync3(sessionPath, "utf8").split("\n")) {
|
|
12447
12750
|
if (!line.trim()) continue;
|
|
12448
12751
|
const parsed = JSON.parse(line);
|
|
12449
12752
|
if (parsed.event?.id) known.add(parsed.event.id);
|
|
@@ -12454,16 +12757,16 @@ var SqliteStore = class {
|
|
|
12454
12757
|
}
|
|
12455
12758
|
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");
|
|
12456
12759
|
if (lines.length > 0) {
|
|
12457
|
-
|
|
12458
|
-
|
|
12760
|
+
appendFileSync2(sessionPath, lines.join(""), { encoding: "utf8", mode: 384 });
|
|
12761
|
+
chmodSync2(sessionPath, 384);
|
|
12459
12762
|
for (const event of state.events) {
|
|
12460
12763
|
if (String(event.agentId) === agentId) known.add(String(event.id));
|
|
12461
12764
|
}
|
|
12462
12765
|
}
|
|
12463
12766
|
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");
|
|
12464
12767
|
if (compactionLines.length > 0) {
|
|
12465
|
-
|
|
12466
|
-
|
|
12768
|
+
appendFileSync2(sessionPath, compactionLines.join(""), { encoding: "utf8", mode: 384 });
|
|
12769
|
+
chmodSync2(sessionPath, 384);
|
|
12467
12770
|
for (const [, record] of state.contextCompactions ?? []) {
|
|
12468
12771
|
if (String(record.agentId) === agentId) knownCompactions.add(record.id);
|
|
12469
12772
|
}
|