@alivault/pico 0.10.0 → 0.10.2
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/.output/nitro.json +1 -1
- package/.output/public/assets/{index-Cv9CWbsI.js → index-CEN6xdm0.js} +10 -10
- package/.output/public/assets/routes-YDDOri73.js +2195 -0
- package/.output/public/assets/styles-hk0oLlcJ.css +2 -0
- package/.output/server/_libs/@pierre/diffs+[...].mjs +322 -165
- package/.output/server/_libs/hast-util-from-parse5+[...].mjs +1 -1
- package/.output/server/_libs/hast-util-raw+[...].mjs +1 -1
- package/.output/server/_libs/hast-util-to-jsx-runtime+[...].mjs +1 -1
- package/.output/server/_libs/lucide-react.mjs +27 -1
- package/.output/server/_libs/mdast-util-gfm+[...].mjs +1 -1
- package/.output/server/_ssr/{router-BfWi4RfZ.mjs → router-CphHgwo2.mjs} +236 -99
- package/.output/server/_ssr/{routes-CSvcOSyF.mjs → routes-CELGJtcT.mjs} +1369 -377
- package/.output/server/_ssr/{routes-D6yf6dMU.mjs → routes-CHNxptm_.mjs} +1924 -41
- package/.output/server/_ssr/ssr.mjs +2 -2
- package/.output/server/{_tanstack-start-manifest_v-Am6Tm4xr.mjs → _tanstack-start-manifest_v-CIqGA3U0.mjs} +4 -4
- package/.output/server/index.mjs +486 -486
- package/package.json +2 -2
- package/.output/public/assets/routes-FmISceu0.js +0 -2160
- package/.output/public/assets/styles-DgbW000h.css +0 -2
- package/.output/server/_libs/sugar-high.mjs +0 -1036
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { i as __toESM } from "../_runtime.mjs";
|
|
2
2
|
import { $ as require_react, Q as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
|
|
3
3
|
import { a as createRouter, c as createRootRoute, n as Scripts, r as HeadContent, s as createFileRoute } from "../_libs/@tanstack/react-router+[...].mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { I as CircleCheck, S as Info, _ as OctagonX, a as TriangleAlert } from "../_libs/lucide-react.mjs";
|
|
5
|
+
import { B as createCompactionSummaryItem, G as extractToolText, I as appliedThemeClassColorMode, J as mergeAssistantBlocksForStreaming, L as assistantBlocksFromMessage, M as TooltipProvider, R as buildItemsFromSync, T as Spinner, U as extractMessageImages, W as extractMessageText$1, f as PICO_SHIKI_VARIABLE_DEFAULTS, kt as toolCategoryFromTool, n as APPLIED_THEME_STORAGE_KEY, t as APPLIED_THEME_CLASSES, u as PICO_CODE_SHIKI_THEME, x as Route$54 } from "./routes-CHNxptm_.mjs";
|
|
6
6
|
import { t as QueryClient } from "../_libs/tanstack__query-core.mjs";
|
|
7
7
|
import { t as setupRouterSsrQueryIntegration } from "../_libs/@tanstack/react-router-ssr-query+[...].mjs";
|
|
8
8
|
import { n as HotkeysProvider } from "../_libs/tanstack__react-hotkeys.mjs";
|
|
9
9
|
import { n as z, t as J } from "../_libs/next-themes.mjs";
|
|
10
10
|
import { t as Toaster } from "../_libs/sonner.mjs";
|
|
11
|
-
import {
|
|
11
|
+
import { c as bundledLanguages, l as bundledLanguagesAlias, s as codeToHtml, u as createCssVariablesTheme } from "../_libs/@pierre/diffs+[...].mjs";
|
|
12
12
|
import { t as createTwoFilesPatch } from "../_libs/diff.mjs";
|
|
13
13
|
import { n as Debouncer } from "../_libs/tanstack__pacer.mjs";
|
|
14
14
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -20,13 +20,17 @@ import os, { homedir } from "node:os";
|
|
|
20
20
|
import { performance } from "node:perf_hooks";
|
|
21
21
|
import { isMainThread } from "node:worker_threads";
|
|
22
22
|
import { execSync, spawn } from "node:child_process";
|
|
23
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/router-
|
|
23
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/router-CphHgwo2.js
|
|
24
24
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
25
25
|
var import_jsx_runtime = require_jsx_runtime();
|
|
26
|
+
function sonnerThemeFromAppliedTheme(theme) {
|
|
27
|
+
if (theme === "system") return "system";
|
|
28
|
+
return appliedThemeClassColorMode(theme) ?? "system";
|
|
29
|
+
}
|
|
26
30
|
var Toaster$1 = ({ ...props }) => {
|
|
27
31
|
const { theme = "system" } = z();
|
|
28
32
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Toaster, {
|
|
29
|
-
theme,
|
|
33
|
+
theme: sonnerThemeFromAppliedTheme(theme),
|
|
30
34
|
className: "toaster group",
|
|
31
35
|
icons: {
|
|
32
36
|
success: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleCheck, { className: "size-4" }),
|
|
@@ -39,6 +43,18 @@ var Toaster$1 = ({ ...props }) => {
|
|
|
39
43
|
"--normal-bg": "var(--popover)",
|
|
40
44
|
"--normal-text": "var(--popover-foreground)",
|
|
41
45
|
"--normal-border": "var(--border)",
|
|
46
|
+
"--success-bg": "color-mix(in oklab, var(--success) 14%, var(--popover))",
|
|
47
|
+
"--success-border": "color-mix(in oklab, var(--success) 35%, var(--border))",
|
|
48
|
+
"--success-text": "var(--success)",
|
|
49
|
+
"--info-bg": "color-mix(in oklab, var(--primary) 14%, var(--popover))",
|
|
50
|
+
"--info-border": "color-mix(in oklab, var(--primary) 35%, var(--border))",
|
|
51
|
+
"--info-text": "var(--primary)",
|
|
52
|
+
"--warning-bg": "color-mix(in oklab, var(--warning) 14%, var(--popover))",
|
|
53
|
+
"--warning-border": "color-mix(in oklab, var(--warning) 35%, var(--border))",
|
|
54
|
+
"--warning-text": "var(--warning)",
|
|
55
|
+
"--error-bg": "color-mix(in oklab, var(--danger) 14%, var(--popover))",
|
|
56
|
+
"--error-border": "color-mix(in oklab, var(--danger) 35%, var(--border))",
|
|
57
|
+
"--error-text": "var(--danger)",
|
|
42
58
|
"--border-radius": "var(--radius)"
|
|
43
59
|
},
|
|
44
60
|
toastOptions: { classNames: { toast: "cn-toast" } },
|
|
@@ -71,7 +87,7 @@ function AppProviders({ children }) {
|
|
|
71
87
|
})
|
|
72
88
|
});
|
|
73
89
|
}
|
|
74
|
-
var styles_default = "/assets/styles-
|
|
90
|
+
var styles_default = "/assets/styles-hk0oLlcJ.css";
|
|
75
91
|
var TANSTACK_DEVTOOLS_SETTINGS_KEY = "tanstack_devtools_settings";
|
|
76
92
|
var TANSTACK_DEVTOOLS_DEFAULTS_STORAGE_KEY = "pico-tanstack-devtools-defaults-v1";
|
|
77
93
|
var TANSTACK_DEVTOOLS_CONFIG = {
|
|
@@ -519,7 +535,7 @@ async function clearContextDraft(options) {
|
|
|
519
535
|
await disposeDraftIfUnused(draftEntry);
|
|
520
536
|
}
|
|
521
537
|
async function resolveRequestedEntry(options) {
|
|
522
|
-
const { url, context, getSessionEntryByKey, ensureSessionEntryById, getActiveEntry, isDraftEntry, getOrCreateDraftEntry, activateContextSession, notifyOnActivate = true, preferActiveDraft = false } = options;
|
|
538
|
+
const { url, context, getSessionEntryByKey, ensureSessionEntryById, getActiveEntry, isDraftEntry, getOrCreateDraftEntry, activateContextSession, notifyOnActivate = true, preferActiveDraft = false, preferActiveDraftOverRequestedSession = false } = options;
|
|
523
539
|
const activateRequestedEntry = async (entry) => {
|
|
524
540
|
await activateContextSession(context, entry, { notify: notifyOnActivate });
|
|
525
541
|
return entry;
|
|
@@ -529,39 +545,52 @@ async function resolveRequestedEntry(options) {
|
|
|
529
545
|
const requestedEntry = getSessionEntryByKey(requestedSessionKey);
|
|
530
546
|
if (requestedEntry) return await activateRequestedEntry(requestedEntry);
|
|
531
547
|
}
|
|
532
|
-
if (preferActiveDraft && context.draftKey) {
|
|
533
|
-
const draftEntry = getSessionEntryByKey(context.draftKey);
|
|
534
|
-
if (draftEntry && isDraftEntry(draftEntry)) return await activateRequestedEntry(draftEntry);
|
|
535
|
-
}
|
|
536
548
|
const requestedSessionId = url.searchParams.get("session");
|
|
537
549
|
if (requestedSessionId) {
|
|
550
|
+
if (preferActiveDraft && preferActiveDraftOverRequestedSession && context.draftKey && context.activeKey === context.draftKey) {
|
|
551
|
+
const activeDraftEntry = getSessionEntryByKey(context.draftKey);
|
|
552
|
+
if (activeDraftEntry && isDraftEntry(activeDraftEntry)) return await activateRequestedEntry(activeDraftEntry);
|
|
553
|
+
}
|
|
538
554
|
const requestedEntry = await ensureSessionEntryById(requestedSessionId);
|
|
539
555
|
if (requestedEntry) return await activateRequestedEntry(requestedEntry);
|
|
540
556
|
}
|
|
557
|
+
if (preferActiveDraft && context.draftKey) {
|
|
558
|
+
const draftEntry = getSessionEntryByKey(context.draftKey);
|
|
559
|
+
if (draftEntry && isDraftEntry(draftEntry)) return await activateRequestedEntry(draftEntry);
|
|
560
|
+
}
|
|
541
561
|
const activeEntry = getActiveEntry(context);
|
|
542
562
|
if (activeEntry) return await activateRequestedEntry(activeEntry);
|
|
543
563
|
return await getOrCreateDraftEntry(context);
|
|
544
564
|
}
|
|
565
|
+
var SPECIAL_SHIKI_LANGUAGES = new Set([
|
|
566
|
+
"ansi",
|
|
567
|
+
"plain",
|
|
568
|
+
"plaintext",
|
|
569
|
+
"text"
|
|
570
|
+
]);
|
|
571
|
+
var SUPPORTED_SHIKI_LANGUAGES = new Set([...Object.keys(bundledLanguages), ...Object.keys(bundledLanguagesAlias)]);
|
|
572
|
+
var picoCodeTheme = createCssVariablesTheme({
|
|
573
|
+
name: PICO_CODE_SHIKI_THEME,
|
|
574
|
+
variablePrefix: "--sh-",
|
|
575
|
+
variableDefaults: { ...PICO_SHIKI_VARIABLE_DEFAULTS },
|
|
576
|
+
fontStyle: false
|
|
577
|
+
});
|
|
545
578
|
function normalizeHighlightLanguage(language) {
|
|
546
579
|
const normalized = typeof language === "string" ? language.trim().toLowerCase().replace(/^language-/, "") : "";
|
|
547
580
|
if (!normalized) return "";
|
|
548
581
|
switch (normalized) {
|
|
549
|
-
case "js":
|
|
550
582
|
case "mjs":
|
|
551
583
|
case "cjs": return "javascript";
|
|
552
|
-
case "
|
|
553
|
-
case "
|
|
554
|
-
case "rs": return "rust";
|
|
584
|
+
case "cts":
|
|
585
|
+
case "mts": return "typescript";
|
|
555
586
|
case "golang": return "go";
|
|
556
587
|
case "htm":
|
|
557
588
|
case "xhtml": return "html";
|
|
558
|
-
case "
|
|
589
|
+
case "svg": return "xml";
|
|
559
590
|
case "shell":
|
|
560
|
-
case "shellscript":
|
|
561
|
-
case "sh":
|
|
562
|
-
case "zsh": return "bash";
|
|
591
|
+
case "shellscript": return "bash";
|
|
563
592
|
case "plain":
|
|
564
|
-
case "
|
|
593
|
+
case "txt": return "text";
|
|
565
594
|
case "h": return "c";
|
|
566
595
|
default: return normalized;
|
|
567
596
|
}
|
|
@@ -571,46 +600,34 @@ function countTextLines(text) {
|
|
|
571
600
|
for (let index = 0; index < text.length; index += 1) if (text.charCodeAt(index) === 10) lines += 1;
|
|
572
601
|
return lines;
|
|
573
602
|
}
|
|
574
|
-
function
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
case "jsonc":
|
|
582
|
-
case "html":
|
|
583
|
-
case "xml":
|
|
584
|
-
case "svg":
|
|
585
|
-
case "mdx": return null;
|
|
586
|
-
case "css": return css_exports;
|
|
587
|
-
case "python": return python_exports;
|
|
588
|
-
case "rust": return rust_exports;
|
|
589
|
-
case "c": return c_exports;
|
|
590
|
-
case "go": return go_exports;
|
|
591
|
-
case "java": return java_exports;
|
|
592
|
-
default: return;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
function buildHighlightPayload(options) {
|
|
603
|
+
function isSupportedShikiLanguage(language) {
|
|
604
|
+
return SPECIAL_SHIKI_LANGUAGES.has(language) || SUPPORTED_SHIKI_LANGUAGES.has(language);
|
|
605
|
+
}
|
|
606
|
+
function shikiCodeInnerHtml(html) {
|
|
607
|
+
return /<pre\b[^>]*><code>([\s\S]*)<\/code><\/pre>/.exec(html)?.[1] ?? html;
|
|
608
|
+
}
|
|
609
|
+
async function buildHighlightPayload(options) {
|
|
596
610
|
const text = typeof options.code === "string" ? options.code : "";
|
|
597
611
|
const normalizedLanguage = normalizeHighlightLanguage(options.language);
|
|
598
612
|
if (!text || !normalizedLanguage) return {
|
|
599
613
|
skipped: true,
|
|
600
614
|
language: normalizedLanguage || void 0
|
|
601
615
|
};
|
|
602
|
-
if (normalizedLanguage === "plaintext" || text.length > 1e5 || countTextLines(text) > 1500) return {
|
|
616
|
+
if (normalizedLanguage === "text" || normalizedLanguage === "plaintext" || text.length > 1e5 || countTextLines(text) > 1500) return {
|
|
603
617
|
skipped: true,
|
|
604
618
|
language: normalizedLanguage
|
|
605
619
|
};
|
|
606
|
-
|
|
607
|
-
if (sugarOptions === void 0) return {
|
|
620
|
+
if (!isSupportedShikiLanguage(normalizedLanguage)) return {
|
|
608
621
|
unsupported: true,
|
|
609
622
|
language: normalizedLanguage
|
|
610
623
|
};
|
|
611
624
|
return {
|
|
612
625
|
language: normalizedLanguage,
|
|
613
|
-
html:
|
|
626
|
+
html: shikiCodeInnerHtml(await codeToHtml(text, {
|
|
627
|
+
lang: normalizedLanguage,
|
|
628
|
+
theme: picoCodeTheme,
|
|
629
|
+
defaultColor: false
|
|
630
|
+
}))
|
|
614
631
|
};
|
|
615
632
|
}
|
|
616
633
|
function messageItemIndex(item) {
|
|
@@ -1113,40 +1130,85 @@ function countFullTurnUserAndAssistantMessages(messages) {
|
|
|
1113
1130
|
finishTurn(false);
|
|
1114
1131
|
return count;
|
|
1115
1132
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
let
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1133
|
+
function readSessionListMetricEntries(content) {
|
|
1134
|
+
const entries = [];
|
|
1135
|
+
for (const line of content.split("\n")) {
|
|
1136
|
+
if (!line.trim()) continue;
|
|
1137
|
+
let entry;
|
|
1138
|
+
try {
|
|
1139
|
+
entry = JSON.parse(line);
|
|
1140
|
+
} catch {
|
|
1141
|
+
continue;
|
|
1142
|
+
}
|
|
1143
|
+
if (!isRecord(entry) || entry.type === "session") continue;
|
|
1144
|
+
entries.push(entry);
|
|
1145
|
+
}
|
|
1146
|
+
return entries;
|
|
1147
|
+
}
|
|
1148
|
+
function sessionListMetricEntryId(entry) {
|
|
1149
|
+
return typeof entry.id === "string" && entry.id ? entry.id : "";
|
|
1150
|
+
}
|
|
1151
|
+
function sessionListMetricEntryParentId(entry) {
|
|
1152
|
+
return typeof entry.parentId === "string" && entry.parentId ? entry.parentId : "";
|
|
1153
|
+
}
|
|
1154
|
+
function sessionListMetricBranchEntries(entries, leafId) {
|
|
1155
|
+
if (leafId === void 0) return entries;
|
|
1156
|
+
if (leafId === null) return [];
|
|
1157
|
+
const byId = new Map(entries.flatMap((entry) => {
|
|
1158
|
+
const id = sessionListMetricEntryId(entry);
|
|
1159
|
+
return id ? [[id, entry]] : [];
|
|
1160
|
+
}));
|
|
1161
|
+
const leaf = byId.get(leafId);
|
|
1162
|
+
if (!leaf) return entries;
|
|
1163
|
+
const branch = [];
|
|
1164
|
+
let current = leaf;
|
|
1165
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1166
|
+
while (current) {
|
|
1167
|
+
const id = sessionListMetricEntryId(current);
|
|
1168
|
+
if (id) {
|
|
1169
|
+
if (visited.has(id)) break;
|
|
1170
|
+
visited.add(id);
|
|
1171
|
+
}
|
|
1172
|
+
branch.unshift(current);
|
|
1173
|
+
const parentId = sessionListMetricEntryParentId(current);
|
|
1174
|
+
current = parentId ? byId.get(parentId) : void 0;
|
|
1175
|
+
}
|
|
1176
|
+
return branch;
|
|
1177
|
+
}
|
|
1178
|
+
function collectSessionListMetricMessages(entries) {
|
|
1179
|
+
let lastTimestamp = 0;
|
|
1180
|
+
let lastValue;
|
|
1181
|
+
const messages = [];
|
|
1182
|
+
for (const entry of entries) {
|
|
1183
|
+
if (entry.type !== "message") continue;
|
|
1184
|
+
const message = isRecord(entry.message) ? entry.message : void 0;
|
|
1185
|
+
if (!message) continue;
|
|
1186
|
+
const messageWithTimestamp = {
|
|
1187
|
+
...message,
|
|
1188
|
+
timestamp: message.timestamp ?? entry.timestamp
|
|
1189
|
+
};
|
|
1190
|
+
if (messageWithTimestamp.role === "user") {
|
|
1191
|
+
const normalized = normalizeModifiedTimestamp(messageWithTimestamp.timestamp);
|
|
1192
|
+
const timestamp = modifiedTimestampValue(normalized);
|
|
1193
|
+
if (timestamp && timestamp >= lastTimestamp) {
|
|
1194
|
+
lastTimestamp = timestamp;
|
|
1195
|
+
lastValue = normalized;
|
|
1144
1196
|
}
|
|
1145
|
-
if (messageWithTimestamp.role === "user" || messageWithTimestamp.role === "assistant") messages.push(messageWithTimestamp);
|
|
1146
1197
|
}
|
|
1198
|
+
if (messageWithTimestamp.role === "user" || messageWithTimestamp.role === "assistant") messages.push(messageWithTimestamp);
|
|
1199
|
+
}
|
|
1200
|
+
return {
|
|
1201
|
+
lastUserMessageAt: lastValue,
|
|
1202
|
+
messages
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
async function readSessionListMetrics(sessionPath, options) {
|
|
1206
|
+
try {
|
|
1207
|
+
const entries = readSessionListMetricEntries(await readFile(sessionPath, "utf8"));
|
|
1208
|
+
const { lastUserMessageAt, messages } = collectSessionListMetricMessages(Object.prototype.hasOwnProperty.call(options ?? {}, "leafId") ? sessionListMetricBranchEntries(entries, options?.leafId) : entries);
|
|
1147
1209
|
const lastMessage = getSessionLastCompleteMessageInfo(messages);
|
|
1148
1210
|
return {
|
|
1149
|
-
lastUserMessageAt
|
|
1211
|
+
lastUserMessageAt,
|
|
1150
1212
|
lastMessageAt: lastMessage.timestamp,
|
|
1151
1213
|
lastMessagePreview: lastMessage.preview,
|
|
1152
1214
|
messageCount: countFullTurnUserAndAssistantMessages(messages)
|
|
@@ -3688,6 +3750,7 @@ var PicoRuntime = class {
|
|
|
3688
3750
|
encoder = new TextEncoder();
|
|
3689
3751
|
contexts = /* @__PURE__ */ new Map();
|
|
3690
3752
|
sessionEntries = /* @__PURE__ */ new Map();
|
|
3753
|
+
sessionTreeLeafOverrides = /* @__PURE__ */ new Map();
|
|
3691
3754
|
servicesByCwd = /* @__PURE__ */ new Map();
|
|
3692
3755
|
pendingUiRequests = /* @__PURE__ */ new Map();
|
|
3693
3756
|
activeOAuthLogins = /* @__PURE__ */ new Map();
|
|
@@ -3866,6 +3929,7 @@ var PicoRuntime = class {
|
|
|
3866
3929
|
id,
|
|
3867
3930
|
clients: /* @__PURE__ */ new Set(),
|
|
3868
3931
|
activeRevision: 0,
|
|
3932
|
+
selectionNonce: 0,
|
|
3869
3933
|
activeKey: void 0,
|
|
3870
3934
|
draftKey: void 0,
|
|
3871
3935
|
sessionScope: process.cwd(),
|
|
@@ -3878,6 +3942,31 @@ var PicoRuntime = class {
|
|
|
3878
3942
|
getSessionPath(entry) {
|
|
3879
3943
|
return entry.session.sessionFile ?? entry.key;
|
|
3880
3944
|
}
|
|
3945
|
+
getSessionTreeLeafOverrideKey(entry) {
|
|
3946
|
+
return entry.session.sessionFile || "";
|
|
3947
|
+
}
|
|
3948
|
+
rememberSessionTreeLeaf(entry, onlyExisting = false) {
|
|
3949
|
+
const key = this.getSessionTreeLeafOverrideKey(entry);
|
|
3950
|
+
if (!key) return;
|
|
3951
|
+
if (onlyExisting && !this.sessionTreeLeafOverrides.has(key)) return;
|
|
3952
|
+
const leafId = entry.session.sessionManager.getLeafId?.() ?? null;
|
|
3953
|
+
if (this.sessionTreeLeafOverrides.get(key) === leafId) return;
|
|
3954
|
+
this.sessionTreeLeafOverrides.set(key, leafId);
|
|
3955
|
+
this.invalidateSessionIndexCache();
|
|
3956
|
+
}
|
|
3957
|
+
restoreSessionTreeLeafOverride(manager, sessionPath) {
|
|
3958
|
+
if (!this.sessionTreeLeafOverrides.has(sessionPath)) return;
|
|
3959
|
+
const leafId = this.sessionTreeLeafOverrides.get(sessionPath) ?? null;
|
|
3960
|
+
if (leafId === null) {
|
|
3961
|
+
manager.resetLeaf?.();
|
|
3962
|
+
return;
|
|
3963
|
+
}
|
|
3964
|
+
if (!manager.getEntry?.(leafId)) {
|
|
3965
|
+
this.sessionTreeLeafOverrides.delete(sessionPath);
|
|
3966
|
+
return;
|
|
3967
|
+
}
|
|
3968
|
+
manager.branch?.(leafId);
|
|
3969
|
+
}
|
|
3881
3970
|
getActiveEntry(context) {
|
|
3882
3971
|
return context.activeKey ? this.sessionEntries.get(context.activeKey) : void 0;
|
|
3883
3972
|
}
|
|
@@ -3988,16 +4077,19 @@ var PicoRuntime = class {
|
|
|
3988
4077
|
return mergeSessionListEntry(target, fallback);
|
|
3989
4078
|
}
|
|
3990
4079
|
async sessionFallbackInfo(entry) {
|
|
3991
|
-
const
|
|
4080
|
+
const sessionName = entry.session.sessionName;
|
|
4081
|
+
const waitingForAutoName = Boolean(entry.sessionNaming.pendingGeneration && !cleanupSessionNameCandidate(sessionName));
|
|
4082
|
+
const firstMessage = waitingForAutoName ? "" : this.getSessionFirstMessage(entry);
|
|
4083
|
+
const listName = waitingForAutoName ? "New session" : sessionName;
|
|
3992
4084
|
const lastMessage = getSessionLastCompleteMessageInfo(entry.session.messages);
|
|
3993
4085
|
return {
|
|
3994
4086
|
path: entry.session.sessionFile,
|
|
3995
4087
|
id: entry.session.sessionId,
|
|
3996
4088
|
cwd: entry.cwd,
|
|
3997
|
-
name:
|
|
4089
|
+
name: listName,
|
|
3998
4090
|
firstMessage,
|
|
3999
4091
|
title: getSessionListTitle({
|
|
4000
|
-
name:
|
|
4092
|
+
name: listName,
|
|
4001
4093
|
firstMessage
|
|
4002
4094
|
}),
|
|
4003
4095
|
modified: await this.sessionEntryModified(entry),
|
|
@@ -4023,13 +4115,17 @@ var PicoRuntime = class {
|
|
|
4023
4115
|
const sessions = allSessions.filter((entry) => (entry.messageCount ?? 0) > 0);
|
|
4024
4116
|
const metricsStartedAt = performance.now();
|
|
4025
4117
|
const withMetrics = await Promise.all(sessions.map(async (entry) => {
|
|
4026
|
-
|
|
4118
|
+
let metrics;
|
|
4119
|
+
if (entry.path) {
|
|
4120
|
+
const hasLeafOverride = this.sessionTreeLeafOverrides.has(entry.path);
|
|
4121
|
+
metrics = await readSessionListMetrics(entry.path, hasLeafOverride ? { leafId: this.sessionTreeLeafOverrides.get(entry.path) ?? null } : void 0);
|
|
4122
|
+
}
|
|
4027
4123
|
return {
|
|
4028
4124
|
...entry,
|
|
4029
|
-
lastUserMessageAt: metrics
|
|
4030
|
-
lastMessageAt: metrics
|
|
4031
|
-
lastMessagePreview: metrics
|
|
4032
|
-
messageCount: metrics
|
|
4125
|
+
lastUserMessageAt: metrics ? metrics.lastUserMessageAt : entry.lastUserMessageAt,
|
|
4126
|
+
lastMessageAt: metrics ? metrics.lastMessageAt : entry.lastMessageAt,
|
|
4127
|
+
lastMessagePreview: metrics ? metrics.lastMessagePreview : entry.lastMessagePreview,
|
|
4128
|
+
messageCount: metrics ? metrics.messageCount : entry.messageCount
|
|
4033
4129
|
};
|
|
4034
4130
|
}));
|
|
4035
4131
|
this.logSessionLoadDebug("session_index:metrics", {
|
|
@@ -4370,6 +4466,16 @@ var PicoRuntime = class {
|
|
|
4370
4466
|
await this.bindSessionEntry(entry);
|
|
4371
4467
|
await Promise.all([this.broadcastEntryState(entry), this.broadcastSessionsAll()]);
|
|
4372
4468
|
}
|
|
4469
|
+
scheduleTreeNavigationSessionListChange(entry, previousLeafId, result) {
|
|
4470
|
+
if (result.cancelled || result.aborted) return;
|
|
4471
|
+
const nextLeafId = entry.session.sessionManager.getLeafId?.() ?? null;
|
|
4472
|
+
if (!result.summaryEntry && previousLeafId === nextLeafId) return;
|
|
4473
|
+
this.rememberSessionTreeLeaf(entry);
|
|
4474
|
+
this.touchSessionEntry(entry);
|
|
4475
|
+
this.broadcastSessionsAll().catch((error) => {
|
|
4476
|
+
console.error("[pico] failed to broadcast tree navigation sessions:", error);
|
|
4477
|
+
});
|
|
4478
|
+
}
|
|
4373
4479
|
syncGitWatchDirectories() {
|
|
4374
4480
|
const cwds = /* @__PURE__ */ new Set();
|
|
4375
4481
|
for (const context of this.contexts.values()) {
|
|
@@ -4649,7 +4755,8 @@ var PicoRuntime = class {
|
|
|
4649
4755
|
getOrCreateDraftEntry: async (activeContext) => await this.getOrCreateDraftEntry(activeContext),
|
|
4650
4756
|
activateContextSession: async (activeContext, entry, activateOptions) => await this.activateContextSession(activeContext, entry, activateOptions),
|
|
4651
4757
|
notifyOnActivate: options?.notifyOnActivate,
|
|
4652
|
-
preferActiveDraft: options?.preferActiveDraft
|
|
4758
|
+
preferActiveDraft: options?.preferActiveDraft,
|
|
4759
|
+
preferActiveDraftOverRequestedSession: options?.preferActiveDraftOverRequestedSession
|
|
4653
4760
|
});
|
|
4654
4761
|
}
|
|
4655
4762
|
async resolveRequest(request, options) {
|
|
@@ -4668,7 +4775,8 @@ var PicoRuntime = class {
|
|
|
4668
4775
|
try {
|
|
4669
4776
|
const activeEntry = await this.resolveRequestedEntry(url, context, {
|
|
4670
4777
|
notifyOnActivate: options?.notifyOnActivate ?? false,
|
|
4671
|
-
preferActiveDraft: options?.preferActiveDraft ?? true
|
|
4778
|
+
preferActiveDraft: options?.preferActiveDraft ?? true,
|
|
4779
|
+
preferActiveDraftOverRequestedSession: options?.preferActiveDraftOverRequestedSession ?? false
|
|
4672
4780
|
});
|
|
4673
4781
|
this.logSessionLoadDebug("request_resolve:done", {
|
|
4674
4782
|
pathname: url.pathname,
|
|
@@ -4793,6 +4901,7 @@ var PicoRuntime = class {
|
|
|
4793
4901
|
const sdk = await this.getSdk();
|
|
4794
4902
|
const openStartedAt = performance.now();
|
|
4795
4903
|
const sessionManager = sdk.SessionManager.open(sessionPath);
|
|
4904
|
+
this.restoreSessionTreeLeafOverride(sessionManager, sessionPath);
|
|
4796
4905
|
this.logSessionLoadDebug("session_manager:open", {
|
|
4797
4906
|
sessionPath,
|
|
4798
4907
|
cwd: sessionManager.getCwd(),
|
|
@@ -4809,7 +4918,9 @@ var PicoRuntime = class {
|
|
|
4809
4918
|
if (currentManager.isPersisted?.()) {
|
|
4810
4919
|
const currentSessionFile = entry.session.sessionFile;
|
|
4811
4920
|
if (!currentSessionFile) throw new Error("Persisted session is missing a session file");
|
|
4812
|
-
|
|
4921
|
+
const sessionManager = (await this.getSdk()).SessionManager.open(currentSessionFile, currentManager.getSessionDir?.(), entry.cwd);
|
|
4922
|
+
this.restoreSessionTreeLeafOverride(sessionManager, currentSessionFile);
|
|
4923
|
+
return sessionManager;
|
|
4813
4924
|
}
|
|
4814
4925
|
return await this.createForkedInMemorySessionManager(currentManager, currentManager.getLeafId?.(), entry.session.sessionFile);
|
|
4815
4926
|
}
|
|
@@ -5192,14 +5303,12 @@ var PicoRuntime = class {
|
|
|
5192
5303
|
};
|
|
5193
5304
|
},
|
|
5194
5305
|
navigateTree: async (targetId, navigateOptions) => {
|
|
5306
|
+
const previousLeafId = session.sessionManager.getLeafId?.() ?? null;
|
|
5195
5307
|
const result = await session.navigateTree(targetId, navigateOptions);
|
|
5196
5308
|
this.refreshRetainedConversationItems(entry);
|
|
5197
5309
|
if (result.editorText != null) entry.uiState.editorText = result.editorText;
|
|
5198
5310
|
await this.broadcastEntryState(entry);
|
|
5199
|
-
|
|
5200
|
-
this.touchSessionEntry(entry);
|
|
5201
|
-
await this.broadcastSessionsAll();
|
|
5202
|
-
}
|
|
5311
|
+
this.scheduleTreeNavigationSessionListChange(entry, previousLeafId, result);
|
|
5203
5312
|
return {
|
|
5204
5313
|
cancelled: Boolean(result.cancelled),
|
|
5205
5314
|
aborted: Boolean(result.aborted)
|
|
@@ -5326,6 +5435,7 @@ var PicoRuntime = class {
|
|
|
5326
5435
|
statusChanged = true;
|
|
5327
5436
|
}
|
|
5328
5437
|
if (statusChanged) this.broadcastSessionStatusAll(entry);
|
|
5438
|
+
this.rememberSessionTreeLeaf(entry, true);
|
|
5329
5439
|
await this.broadcastEntryState(entry);
|
|
5330
5440
|
if (type === "agent_start" || type === "agent_end" || type === "message_end" || type === "compaction_end" || type === "queue_update") await this.broadcastSessionsAll();
|
|
5331
5441
|
if (type === "agent_end" || type === "compaction_end") await this.cleanupInactiveContexts();
|
|
@@ -5383,12 +5493,13 @@ var PicoRuntime = class {
|
|
|
5383
5493
|
const bootstrapStartedAt = performance.now();
|
|
5384
5494
|
try {
|
|
5385
5495
|
const stateStartedAt = performance.now();
|
|
5386
|
-
|
|
5496
|
+
const bootstrapEntry = this.getActiveEntry(context) ?? activeEntry;
|
|
5497
|
+
this.sendStatePayloadToClient(context, client, this.currentStatePayload(bootstrapEntry, context), { forceFull: true });
|
|
5387
5498
|
this.logSessionLoadDebug("events_response:bootstrap_state", {
|
|
5388
5499
|
contextId: context.id,
|
|
5389
5500
|
clientId: client.id,
|
|
5390
5501
|
durationMs: roundedDurationMs(stateStartedAt),
|
|
5391
|
-
...this.sessionDebugDetails(
|
|
5502
|
+
...this.sessionDebugDetails(bootstrapEntry)
|
|
5392
5503
|
});
|
|
5393
5504
|
if (client.closed || request.signal.aborted) return;
|
|
5394
5505
|
const sessionsStartedAt = performance.now();
|
|
@@ -5438,7 +5549,10 @@ var PicoRuntime = class {
|
|
|
5438
5549
|
}
|
|
5439
5550
|
}
|
|
5440
5551
|
async prompt(request, body) {
|
|
5441
|
-
const { context, activeEntry } = await this.resolveRequest(request, {
|
|
5552
|
+
const { context, activeEntry } = await this.resolveRequest(request, {
|
|
5553
|
+
preferActiveDraft: true,
|
|
5554
|
+
preferActiveDraftOverRequestedSession: true
|
|
5555
|
+
});
|
|
5442
5556
|
const message = typeof body.message === "string" ? body.message : "";
|
|
5443
5557
|
const images = normalizePromptImages(body.images);
|
|
5444
5558
|
if (!message.trim() && images.length === 0) throw new Error("message or image is required");
|
|
@@ -5620,11 +5734,16 @@ var PicoRuntime = class {
|
|
|
5620
5734
|
const url = new URL(request.url);
|
|
5621
5735
|
const requestedSessionId = url.searchParams.get("session")?.trim() || "";
|
|
5622
5736
|
const requestedSessionPath = url.searchParams.get("sessionPath")?.trim() || "";
|
|
5737
|
+
const rawSelectionNonce = Number(url.searchParams.get("selectionNonce"));
|
|
5738
|
+
const selectionNonce = Number.isSafeInteger(rawSelectionNonce) && rawSelectionNonce > 0 ? rawSelectionNonce : 0;
|
|
5623
5739
|
const context = this.ensureContext(url.searchParams.get("context") || "default");
|
|
5624
5740
|
context.sessionScope = normalizeSessionScope(url.searchParams.get("scope"), process.cwd());
|
|
5741
|
+
if (selectionNonce > context.selectionNonce) context.selectionNonce = selectionNonce;
|
|
5625
5742
|
this.logSessionLoadDebug("select_session:start", {
|
|
5626
5743
|
requestedSessionId,
|
|
5627
5744
|
requestedSessionPath,
|
|
5745
|
+
selectionNonce,
|
|
5746
|
+
latestSelectionNonce: context.selectionNonce,
|
|
5628
5747
|
contextId: context.id
|
|
5629
5748
|
});
|
|
5630
5749
|
try {
|
|
@@ -5640,6 +5759,26 @@ var PicoRuntime = class {
|
|
|
5640
5759
|
...this.sessionDebugDetails(nextEntry)
|
|
5641
5760
|
});
|
|
5642
5761
|
if (!nextEntry) throw new Error(`Unknown session: ${requestedSessionId}`);
|
|
5762
|
+
if (request.signal.aborted) {
|
|
5763
|
+
this.logSessionLoadDebug("select_session:skip_aborted", {
|
|
5764
|
+
requestedSessionId,
|
|
5765
|
+
requestedSessionPath,
|
|
5766
|
+
selectionNonce,
|
|
5767
|
+
latestSelectionNonce: context.selectionNonce,
|
|
5768
|
+
...this.sessionDebugDetails(nextEntry)
|
|
5769
|
+
});
|
|
5770
|
+
return { ok: true };
|
|
5771
|
+
}
|
|
5772
|
+
if (selectionNonce > 0 && selectionNonce < context.selectionNonce) {
|
|
5773
|
+
this.logSessionLoadDebug("select_session:skip_stale", {
|
|
5774
|
+
requestedSessionId,
|
|
5775
|
+
requestedSessionPath,
|
|
5776
|
+
selectionNonce,
|
|
5777
|
+
latestSelectionNonce: context.selectionNonce,
|
|
5778
|
+
...this.sessionDebugDetails(nextEntry)
|
|
5779
|
+
});
|
|
5780
|
+
return { ok: true };
|
|
5781
|
+
}
|
|
5643
5782
|
const activateStartedAt = performance.now();
|
|
5644
5783
|
await this.activateContextSession(context, nextEntry);
|
|
5645
5784
|
this.logSessionLoadDebug("select_session:activate", {
|
|
@@ -5763,6 +5902,7 @@ var PicoRuntime = class {
|
|
|
5763
5902
|
const targetId = typeof body.targetId === "string" ? body.targetId.trim() : "";
|
|
5764
5903
|
if (!targetId) throw new Error("targetId is required");
|
|
5765
5904
|
if (this.getEntryStreamingState(activeEntry) || activeEntry.session.isStreaming) throw new Error("Abort the current response before navigating the tree.");
|
|
5905
|
+
const previousLeafId = activeEntry.session.sessionManager.getLeafId?.() ?? null;
|
|
5766
5906
|
const result = await activeEntry.session.navigateTree(targetId, {
|
|
5767
5907
|
summarize: Boolean(body.summarize),
|
|
5768
5908
|
customInstructions: typeof body.customInstructions === "string" ? body.customInstructions : void 0,
|
|
@@ -5771,11 +5911,8 @@ var PicoRuntime = class {
|
|
|
5771
5911
|
});
|
|
5772
5912
|
this.refreshRetainedConversationItems(activeEntry);
|
|
5773
5913
|
if (result.editorText != null) activeEntry.uiState.editorText = result.editorText;
|
|
5774
|
-
if (result.summaryEntry) {
|
|
5775
|
-
this.touchSessionEntry(activeEntry);
|
|
5776
|
-
await this.broadcastSessionsAll();
|
|
5777
|
-
}
|
|
5778
5914
|
await this.broadcastEntryState(activeEntry);
|
|
5915
|
+
this.scheduleTreeNavigationSessionListChange(activeEntry, previousLeafId, result);
|
|
5779
5916
|
return {
|
|
5780
5917
|
ok: true,
|
|
5781
5918
|
cancelled: Boolean(result.cancelled),
|
|
@@ -6366,7 +6503,7 @@ var PicoRuntime = class {
|
|
|
6366
6503
|
async highlightCode(code, language) {
|
|
6367
6504
|
const text = typeof code === "string" ? code : "";
|
|
6368
6505
|
try {
|
|
6369
|
-
const highlightInput = buildHighlightPayload({
|
|
6506
|
+
const highlightInput = await buildHighlightPayload({
|
|
6370
6507
|
code,
|
|
6371
6508
|
language
|
|
6372
6509
|
});
|