@hachej/boring-agent 0.1.103 → 0.1.105
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/{chunk-7QM22DU7.js → chunk-6DRHERVK.js} +7 -5
- package/dist/{chunk-TW7G33QH.js → chunk-F2OJI2LX.js} +64 -15
- package/dist/{chunk-6WKQ4FC4.js → chunk-LFN45QDZ.js} +259 -140
- package/dist/core/index.d.ts +5 -5
- package/dist/{createHarness-4Q6DQBRT.js → createHarness-GMBZZPTN.js} +1 -1
- package/dist/{errors-szpcDUFQ.d.ts → errors-DH7C01Pm.d.ts} +1 -1
- package/dist/{file-search-BXdSm-Yq.d.ts → file-search-qcD5zItr.d.ts} +3 -3
- package/dist/front/index.d.ts +12 -2
- package/dist/front/index.js +200 -135
- package/dist/front/styles.css +56 -15
- package/dist/{harness-erpL2SER.d.ts → harness-Dcd08yKr.d.ts} +1 -1
- package/dist/{lease-K-EZhdL-.d.ts → lease-DffrPrQn.d.ts} +1 -1
- package/dist/{piChatEvent-g1nIBh44.d.ts → piChatEvent-iNSXiFQq.d.ts} +5 -0
- package/dist/{piChatSessionService-DugeRHzb.d.ts → piChatSessionService-DQSQ_kWZ.d.ts} +1 -1
- package/dist/server/agent-host/testing/gatewayConformance.d.ts +5 -5
- package/dist/server/agent-host/testing/gatewayConformance.js +1 -1
- package/dist/server/index.d.ts +53 -42
- package/dist/server/index.js +5 -3
- package/dist/server/worker/index.js +3 -3
- package/dist/shared/index.d.ts +93 -19
- package/dist/shared/index.js +1 -1
- package/dist/{types-BnjMLAd5.d.ts → types-BTsdaAQ2.d.ts} +33 -14
- package/docs/ERROR_CODES.md +1 -1
- package/package.json +6 -6
|
@@ -174,12 +174,17 @@ var QueuedUserMessageSchema = z.object({
|
|
|
174
174
|
createdAt: z.string().optional()
|
|
175
175
|
});
|
|
176
176
|
var PiChatStatusSchema = z.enum(["idle", "hydrating", "submitted", "streaming", "aborting", "error"]);
|
|
177
|
+
var ChatModelSelectionSchema = z.object({
|
|
178
|
+
provider: nonEmptyString,
|
|
179
|
+
id: nonEmptyString
|
|
180
|
+
});
|
|
177
181
|
var PiChatSnapshotSchema = z.object({
|
|
178
182
|
protocolVersion: z.literal(1),
|
|
179
183
|
sessionId: nonEmptyString,
|
|
180
184
|
seq: seqNumber,
|
|
181
185
|
status: PiChatStatusSchema,
|
|
182
186
|
activeTurnId: z.string().optional(),
|
|
187
|
+
currentModel: ChatModelSelectionSchema.optional(),
|
|
183
188
|
messages: z.array(BoringChatMessageSchema),
|
|
184
189
|
queue: z.object({ followUps: z.array(QueuedUserMessageSchema) }),
|
|
185
190
|
followUpMode: z.literal("one-at-a-time"),
|
|
@@ -188,6 +193,7 @@ var PiChatSnapshotSchema = z.object({
|
|
|
188
193
|
var baseEvent = z.object({ seq: seqNumber });
|
|
189
194
|
var PiChatEventSchema = z.discriminatedUnion("type", [
|
|
190
195
|
baseEvent.extend({ type: z.literal("agent-start"), turnId: nonEmptyString }),
|
|
196
|
+
baseEvent.extend({ type: z.literal("model-changed"), currentModel: ChatModelSelectionSchema }),
|
|
191
197
|
baseEvent.extend({ type: z.literal("agent-end"), turnId: nonEmptyString, status: z.enum(["ok", "aborted", "error"]), willRetry: z.boolean().optional() }),
|
|
192
198
|
baseEvent.extend({
|
|
193
199
|
type: z.literal("message-start"),
|
|
@@ -258,10 +264,6 @@ var PiChatEventSchema = z.discriminatedUnion("type", [
|
|
|
258
264
|
]);
|
|
259
265
|
var PiChatHeartbeatFrameSchema = z.object({ type: z.literal("heartbeat"), now: z.string() });
|
|
260
266
|
var PiChatStreamFrameSchema = z.union([PiChatEventSchema, PiChatHeartbeatFrameSchema]);
|
|
261
|
-
var ChatModelSelectionSchema = z.object({
|
|
262
|
-
provider: nonEmptyString,
|
|
263
|
-
id: nonEmptyString
|
|
264
|
-
});
|
|
265
267
|
var ThinkingLevelSchema = z.enum(["off", "low", "medium", "high"]);
|
|
266
268
|
var ChatAttachmentPayloadSchema = z.object({
|
|
267
269
|
filename: z.string().optional(),
|
|
@@ -330,11 +332,11 @@ export {
|
|
|
330
332
|
BoringChatMessageSchema,
|
|
331
333
|
QueuedUserMessageSchema,
|
|
332
334
|
PiChatStatusSchema,
|
|
335
|
+
ChatModelSelectionSchema,
|
|
333
336
|
PiChatSnapshotSchema,
|
|
334
337
|
PiChatEventSchema,
|
|
335
338
|
PiChatHeartbeatFrameSchema,
|
|
336
339
|
PiChatStreamFrameSchema,
|
|
337
|
-
ChatModelSelectionSchema,
|
|
338
340
|
ThinkingLevelSchema,
|
|
339
341
|
ChatAttachmentPayloadSchema,
|
|
340
342
|
PromptPayloadSchema,
|
|
@@ -567,6 +567,28 @@ async function summarizeNativeTranscript(filepath) {
|
|
|
567
567
|
}
|
|
568
568
|
|
|
569
569
|
// src/server/harness/pi-coding-agent/sessions.ts
|
|
570
|
+
function legacyAssistantModel(entry) {
|
|
571
|
+
const message = entry.message;
|
|
572
|
+
if (message.role !== "assistant") return void 0;
|
|
573
|
+
if (typeof message.provider === "string" && typeof message.model === "string") {
|
|
574
|
+
return { provider: message.provider, id: message.model };
|
|
575
|
+
}
|
|
576
|
+
if (typeof message.model !== "object" || message.model === null) return void 0;
|
|
577
|
+
const model = message.model;
|
|
578
|
+
return typeof model.provider === "string" && typeof model.id === "string" ? { provider: model.provider, id: model.id } : void 0;
|
|
579
|
+
}
|
|
580
|
+
function currentModelFromTranscript(entries) {
|
|
581
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
582
|
+
const entry = entries[index];
|
|
583
|
+
if (!entry) continue;
|
|
584
|
+
if (entry.type === "model_change") return { provider: entry.provider, id: entry.modelId };
|
|
585
|
+
if (entry.type === "message") {
|
|
586
|
+
const model = legacyAssistantModel(entry);
|
|
587
|
+
if (model) return model;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return void 0;
|
|
591
|
+
}
|
|
570
592
|
function sessionBaseDir(explicitRoot) {
|
|
571
593
|
const explicit = explicitRoot?.trim();
|
|
572
594
|
if (explicit) return resolve(explicit);
|
|
@@ -666,11 +688,8 @@ var PiSessionStore = class {
|
|
|
666
688
|
}));
|
|
667
689
|
const existingFiles = fileStats.filter((item) => item !== null);
|
|
668
690
|
const referencedPiFiles = await this.referencedPiFiles(existingFiles);
|
|
669
|
-
const visibleFiles = await Promise.all(existingFiles.filter(({ filepath }) => !referencedPiFiles.has(resolve(filepath))).map(async (file) => ({
|
|
670
|
-
|
|
671
|
-
sortMtimeMs: await this.sessionSortMtimeMs(file)
|
|
672
|
-
})));
|
|
673
|
-
visibleFiles.sort((a, b) => b.sortMtimeMs - a.sortMtimeMs);
|
|
691
|
+
const visibleFiles = await Promise.all(existingFiles.filter(({ filepath }) => !referencedPiFiles.has(resolve(filepath))).map(async (file) => ({ ...file, ...await this.sessionSortKey(file) })));
|
|
692
|
+
visibleFiles.sort((a, b) => b.sortMtimeMs - a.sortMtimeMs || a.sortId.localeCompare(b.sortId));
|
|
674
693
|
const { offset, limit } = options;
|
|
675
694
|
const includeId = options.includeId;
|
|
676
695
|
const pageSummaries = await this.summarizeVisiblePage(visibleFiles, {
|
|
@@ -745,7 +764,11 @@ var PiSessionStore = class {
|
|
|
745
764
|
async loadEntries(ctx, sessionId) {
|
|
746
765
|
const resolved = await this.resolveSessionTranscript(ctx, sessionId);
|
|
747
766
|
const messages = resolved.transcriptEntries.filter((entry) => entry.type === "message").map((entry) => withStableMessageId(entry.message, entry.id));
|
|
748
|
-
return {
|
|
767
|
+
return {
|
|
768
|
+
id: resolved.resolvedSessionId,
|
|
769
|
+
messages,
|
|
770
|
+
currentModel: currentModelFromTranscript(resolved.transcriptEntries)
|
|
771
|
+
};
|
|
749
772
|
}
|
|
750
773
|
async loadAttachment(ctx, sessionId, messageId, index) {
|
|
751
774
|
const resolved = await this.resolveSessionTranscript(ctx, sessionId);
|
|
@@ -941,8 +964,8 @@ var PiSessionStore = class {
|
|
|
941
964
|
if (readHeaderSessionCtx(header) !== null) return null;
|
|
942
965
|
const existingWrapper = await this.findWrapperReferencingNativeSession(filepath);
|
|
943
966
|
if (existingWrapper) {
|
|
944
|
-
const
|
|
945
|
-
if (
|
|
967
|
+
const wrapperSessionId2 = await this.readSessionFileId(existingWrapper);
|
|
968
|
+
if (wrapperSessionId2 !== sessionId) return null;
|
|
946
969
|
const wrapperEntries = parseJsonlPrefixEntries2(await readJsonlPrefix2(existingWrapper));
|
|
947
970
|
const wrapperHeader = wrapperEntries.find((entry) => entry.type === "session");
|
|
948
971
|
if (!this.headerBelongsToCtx(wrapperHeader, ctx)) return null;
|
|
@@ -1043,21 +1066,37 @@ var PiSessionStore = class {
|
|
|
1043
1066
|
}));
|
|
1044
1067
|
return referenced;
|
|
1045
1068
|
}
|
|
1046
|
-
async
|
|
1069
|
+
async sessionSortKey({ filepath, stat }) {
|
|
1047
1070
|
let sortMtimeMs = stat.mtime.getTime();
|
|
1071
|
+
let headerId = void 0;
|
|
1072
|
+
const stemFallback = () => ({
|
|
1073
|
+
sortMtimeMs,
|
|
1074
|
+
sortId: wrapperSessionId(filepath)
|
|
1075
|
+
});
|
|
1048
1076
|
try {
|
|
1049
|
-
const
|
|
1077
|
+
const cached = await this.readPrefixCache(filepath, stat);
|
|
1078
|
+
headerId = cached.headerId ?? void 0;
|
|
1079
|
+
const linkedPiFile = cached.referencedPiFile;
|
|
1050
1080
|
if (linkedPiFile && resolve(linkedPiFile) !== resolve(filepath)) {
|
|
1051
1081
|
const linkedStat = await fsStat2(linkedPiFile);
|
|
1052
1082
|
sortMtimeMs = Math.max(sortMtimeMs, linkedStat.mtime.getTime());
|
|
1053
1083
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1084
|
+
if (!headerId) {
|
|
1085
|
+
return stemFallback();
|
|
1086
|
+
}
|
|
1087
|
+
if (!isTimestampNamedPiSessionFile(filepath, headerId)) {
|
|
1088
|
+
return { sortMtimeMs, sortId: headerId };
|
|
1057
1089
|
}
|
|
1090
|
+
if (cached.nativeSortMtimeMs !== void 0) {
|
|
1091
|
+
return { sortMtimeMs: cached.nativeSortMtimeMs, sortId: headerId };
|
|
1092
|
+
}
|
|
1093
|
+
const latest = await latestNativeMessageTimestamp(filepath, Number(stat.size));
|
|
1094
|
+
if (latest === void 0) return { sortMtimeMs, sortId: headerId };
|
|
1095
|
+
this.prefixCache.set(filepath, { ...cached, nativeSortMtimeMs: latest });
|
|
1096
|
+
return { sortMtimeMs: latest, sortId: headerId };
|
|
1058
1097
|
} catch {
|
|
1098
|
+
return headerId ? { sortMtimeMs, sortId: headerId } : stemFallback();
|
|
1059
1099
|
}
|
|
1060
|
-
return sortMtimeMs;
|
|
1061
1100
|
}
|
|
1062
1101
|
async summarizeFile(ctx, filepath, existingStat) {
|
|
1063
1102
|
try {
|
|
@@ -1106,6 +1145,10 @@ var PiSessionStore = class {
|
|
|
1106
1145
|
mtimeMs: fileStat.mtime.getTime(),
|
|
1107
1146
|
size: Number(fileStat.size),
|
|
1108
1147
|
referencedPiFile: linkedPiFile,
|
|
1148
|
+
// Carried so a later `sessionSortMtimeMs` on this same entry still
|
|
1149
|
+
// recognises a native transcript instead of falling back to mtime.
|
|
1150
|
+
headerId: header.id,
|
|
1151
|
+
...cached?.nativeSortMtimeMs !== void 0 ? { nativeSortMtimeMs: cached.nativeSortMtimeMs } : {},
|
|
1109
1152
|
sessionCtx,
|
|
1110
1153
|
...linked ? { linkedMtimeMs: linked.mtime.getTime(), linkedSize: linked.size } : {},
|
|
1111
1154
|
...!nativeSummary ? { summary } : {}
|
|
@@ -1136,11 +1179,13 @@ var PiSessionStore = class {
|
|
|
1136
1179
|
if (cached) return cached;
|
|
1137
1180
|
const content = await readJsonlPrefix2(filepath);
|
|
1138
1181
|
const entries = parseJsonlPrefixEntries2(content);
|
|
1182
|
+
const header = entries.find((item) => item.type === "session");
|
|
1139
1183
|
const entry = {
|
|
1140
1184
|
mtimeMs: fileStat.mtime.getTime(),
|
|
1141
1185
|
size: Number(fileStat.size),
|
|
1142
1186
|
referencedPiFile: extractPiSessionFilePath(entries),
|
|
1143
|
-
|
|
1187
|
+
headerId: header?.id ?? null,
|
|
1188
|
+
sessionCtx: readHeaderSessionCtx(header)
|
|
1144
1189
|
};
|
|
1145
1190
|
this.prefixCache.set(filepath, entry);
|
|
1146
1191
|
return entry;
|
|
@@ -1405,6 +1450,10 @@ function extractSessionHeaderId(entries) {
|
|
|
1405
1450
|
function nativeSessionFilename(sessionId, isoTimestamp) {
|
|
1406
1451
|
return `${isoTimestamp.replace(/[:.]/g, "-")}_${sessionId}.jsonl`;
|
|
1407
1452
|
}
|
|
1453
|
+
function wrapperSessionId(filepath) {
|
|
1454
|
+
const base = basename(filepath);
|
|
1455
|
+
return base.endsWith(".jsonl") ? base.slice(0, -".jsonl".length) : base;
|
|
1456
|
+
}
|
|
1408
1457
|
function isTimestampNamedPiSessionFile(filepath, sessionId) {
|
|
1409
1458
|
const filename = basename(filepath);
|
|
1410
1459
|
return /^\d{4}-\d{2}-\d{2}/.test(filename) && filename.endsWith(`_${sessionId}.jsonl`);
|