@geminixiang/mikan 0.2.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/CHANGELOG.md +324 -0
- package/LICENSE +22 -0
- package/README.md +297 -0
- package/dist/adapter.d.ts +134 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +2 -0
- package/dist/adapter.js.map +1 -0
- package/dist/adapters/discord/bot.d.ts +63 -0
- package/dist/adapters/discord/bot.d.ts.map +1 -0
- package/dist/adapters/discord/bot.js +577 -0
- package/dist/adapters/discord/bot.js.map +1 -0
- package/dist/adapters/discord/context.d.ts +9 -0
- package/dist/adapters/discord/context.d.ts.map +1 -0
- package/dist/adapters/discord/context.js +245 -0
- package/dist/adapters/discord/context.js.map +1 -0
- package/dist/adapters/discord/index.d.ts +3 -0
- package/dist/adapters/discord/index.d.ts.map +1 -0
- package/dist/adapters/discord/index.js +3 -0
- package/dist/adapters/discord/index.js.map +1 -0
- package/dist/adapters/shared.d.ts +91 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/adapters/shared.js +191 -0
- package/dist/adapters/shared.js.map +1 -0
- package/dist/adapters/slack/bot.d.ts +139 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -0
- package/dist/adapters/slack/bot.js +1272 -0
- package/dist/adapters/slack/bot.js.map +1 -0
- package/dist/adapters/slack/branch-manager.d.ts +28 -0
- package/dist/adapters/slack/branch-manager.d.ts.map +1 -0
- package/dist/adapters/slack/branch-manager.js +117 -0
- package/dist/adapters/slack/branch-manager.js.map +1 -0
- package/dist/adapters/slack/context.d.ts +12 -0
- package/dist/adapters/slack/context.d.ts.map +1 -0
- package/dist/adapters/slack/context.js +327 -0
- package/dist/adapters/slack/context.js.map +1 -0
- package/dist/adapters/slack/index.d.ts +3 -0
- package/dist/adapters/slack/index.d.ts.map +1 -0
- package/dist/adapters/slack/index.js +3 -0
- package/dist/adapters/slack/index.js.map +1 -0
- package/dist/adapters/slack/session.d.ts +38 -0
- package/dist/adapters/slack/session.d.ts.map +1 -0
- package/dist/adapters/slack/session.js +66 -0
- package/dist/adapters/slack/session.js.map +1 -0
- package/dist/adapters/slack/tools/attach.d.ts +12 -0
- package/dist/adapters/slack/tools/attach.d.ts.map +1 -0
- package/dist/adapters/slack/tools/attach.js +40 -0
- package/dist/adapters/slack/tools/attach.js.map +1 -0
- package/dist/adapters/telegram/bot.d.ts +51 -0
- package/dist/adapters/telegram/bot.d.ts.map +1 -0
- package/dist/adapters/telegram/bot.js +430 -0
- package/dist/adapters/telegram/bot.js.map +1 -0
- package/dist/adapters/telegram/context.d.ts +9 -0
- package/dist/adapters/telegram/context.d.ts.map +1 -0
- package/dist/adapters/telegram/context.js +190 -0
- package/dist/adapters/telegram/context.js.map +1 -0
- package/dist/adapters/telegram/html.d.ts +3 -0
- package/dist/adapters/telegram/html.d.ts.map +1 -0
- package/dist/adapters/telegram/html.js +98 -0
- package/dist/adapters/telegram/html.js.map +1 -0
- package/dist/adapters/telegram/index.d.ts +3 -0
- package/dist/adapters/telegram/index.d.ts.map +1 -0
- package/dist/adapters/telegram/index.js +3 -0
- package/dist/adapters/telegram/index.js.map +1 -0
- package/dist/agent.d.ts +36 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +1147 -0
- package/dist/agent.js.map +1 -0
- package/dist/commands/auto-reply.d.ts +5 -0
- package/dist/commands/auto-reply.d.ts.map +1 -0
- package/dist/commands/auto-reply.js +79 -0
- package/dist/commands/auto-reply.js.map +1 -0
- package/dist/commands/index.d.ts +5 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +18 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/login.d.ts +5 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +91 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/model.d.ts +14 -0
- package/dist/commands/model.d.ts.map +1 -0
- package/dist/commands/model.js +110 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/new.d.ts +5 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +24 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/parse.d.ts +7 -0
- package/dist/commands/parse.d.ts.map +1 -0
- package/dist/commands/parse.js +17 -0
- package/dist/commands/parse.js.map +1 -0
- package/dist/commands/registry.d.ts +4 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +9 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/sandbox.d.ts +10 -0
- package/dist/commands/sandbox.d.ts.map +1 -0
- package/dist/commands/sandbox.js +83 -0
- package/dist/commands/sandbox.js.map +1 -0
- package/dist/commands/session-view.d.ts +5 -0
- package/dist/commands/session-view.d.ts.map +1 -0
- package/dist/commands/session-view.js +62 -0
- package/dist/commands/session-view.js.map +1 -0
- package/dist/commands/types.d.ts +41 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/utils.d.ts +8 -0
- package/dist/commands/utils.d.ts.map +1 -0
- package/dist/commands/utils.js +14 -0
- package/dist/commands/utils.js.map +1 -0
- package/dist/config.d.ts +59 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +370 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +24 -0
- package/dist/context.js.map +1 -0
- package/dist/conversation-history.d.ts +16 -0
- package/dist/conversation-history.d.ts.map +1 -0
- package/dist/conversation-history.js +144 -0
- package/dist/conversation-history.js.map +1 -0
- package/dist/download.d.ts +2 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +89 -0
- package/dist/download.js.map +1 -0
- package/dist/env.d.ts +3 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +12 -0
- package/dist/env.js.map +1 -0
- package/dist/events.d.ts +85 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +483 -0
- package/dist/events.js.map +1 -0
- package/dist/execution-resolver.d.ts +25 -0
- package/dist/execution-resolver.d.ts.map +1 -0
- package/dist/execution-resolver.js +167 -0
- package/dist/execution-resolver.js.map +1 -0
- package/dist/file-guards.d.ts +9 -0
- package/dist/file-guards.d.ts.map +1 -0
- package/dist/file-guards.js +56 -0
- package/dist/file-guards.js.map +1 -0
- package/dist/fs-atomic.d.ts +10 -0
- package/dist/fs-atomic.d.ts.map +1 -0
- package/dist/fs-atomic.js +45 -0
- package/dist/fs-atomic.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/instrument.d.ts +2 -0
- package/dist/instrument.d.ts.map +1 -0
- package/dist/instrument.js +10 -0
- package/dist/instrument.js.map +1 -0
- package/dist/log.d.ts +36 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +206 -0
- package/dist/log.js.map +1 -0
- package/dist/login/index.d.ts +42 -0
- package/dist/login/index.d.ts.map +1 -0
- package/dist/login/index.js +239 -0
- package/dist/login/index.js.map +1 -0
- package/dist/login/portal.d.ts +19 -0
- package/dist/login/portal.d.ts.map +1 -0
- package/dist/login/portal.js +1544 -0
- package/dist/login/portal.js.map +1 -0
- package/dist/login/session.d.ts +26 -0
- package/dist/login/session.d.ts.map +1 -0
- package/dist/login/session.js +56 -0
- package/dist/login/session.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +366 -0
- package/dist/main.js.map +1 -0
- package/dist/provisioner.d.ts +83 -0
- package/dist/provisioner.d.ts.map +1 -0
- package/dist/provisioner.js +500 -0
- package/dist/provisioner.js.map +1 -0
- package/dist/runtime/conversation-orchestrator.d.ts +40 -0
- package/dist/runtime/conversation-orchestrator.d.ts.map +1 -0
- package/dist/runtime/conversation-orchestrator.js +183 -0
- package/dist/runtime/conversation-orchestrator.js.map +1 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/session-runtime.d.ts +26 -0
- package/dist/runtime/session-runtime.d.ts.map +1 -0
- package/dist/runtime/session-runtime.js +221 -0
- package/dist/runtime/session-runtime.js.map +1 -0
- package/dist/sandbox/cloudflare.d.ts +15 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -0
- package/dist/sandbox/cloudflare.js +138 -0
- package/dist/sandbox/cloudflare.js.map +1 -0
- package/dist/sandbox/container.d.ts +16 -0
- package/dist/sandbox/container.d.ts.map +1 -0
- package/dist/sandbox/container.js +138 -0
- package/dist/sandbox/container.js.map +1 -0
- package/dist/sandbox/errors.d.ts +6 -0
- package/dist/sandbox/errors.d.ts.map +1 -0
- package/dist/sandbox/errors.js +11 -0
- package/dist/sandbox/errors.js.map +1 -0
- package/dist/sandbox/firecracker.d.ts +17 -0
- package/dist/sandbox/firecracker.d.ts.map +1 -0
- package/dist/sandbox/firecracker.js +212 -0
- package/dist/sandbox/firecracker.js.map +1 -0
- package/dist/sandbox/host.d.ts +11 -0
- package/dist/sandbox/host.d.ts.map +1 -0
- package/dist/sandbox/host.js +89 -0
- package/dist/sandbox/host.js.map +1 -0
- package/dist/sandbox/image.d.ts +5 -0
- package/dist/sandbox/image.d.ts.map +1 -0
- package/dist/sandbox/image.js +30 -0
- package/dist/sandbox/image.js.map +1 -0
- package/dist/sandbox/index.d.ts +22 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +54 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/path-context.d.ts +4 -0
- package/dist/sandbox/path-context.d.ts.map +1 -0
- package/dist/sandbox/path-context.js +20 -0
- package/dist/sandbox/path-context.js.map +1 -0
- package/dist/sandbox/types.d.ts +67 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/types.js +2 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/sandbox/utils.d.ts +4 -0
- package/dist/sandbox/utils.d.ts.map +1 -0
- package/dist/sandbox/utils.js +51 -0
- package/dist/sandbox/utils.js.map +1 -0
- package/dist/sentry.d.ts +50 -0
- package/dist/sentry.d.ts.map +1 -0
- package/dist/sentry.js +257 -0
- package/dist/sentry.js.map +1 -0
- package/dist/session-view/command.d.ts +5 -0
- package/dist/session-view/command.d.ts.map +1 -0
- package/dist/session-view/command.js +7 -0
- package/dist/session-view/command.js.map +1 -0
- package/dist/session-view/portal.d.ts +16 -0
- package/dist/session-view/portal.d.ts.map +1 -0
- package/dist/session-view/portal.js +1822 -0
- package/dist/session-view/portal.js.map +1 -0
- package/dist/session-view/service.d.ts +34 -0
- package/dist/session-view/service.d.ts.map +1 -0
- package/dist/session-view/service.js +434 -0
- package/dist/session-view/service.js.map +1 -0
- package/dist/session-view/store.d.ts +18 -0
- package/dist/session-view/store.d.ts.map +1 -0
- package/dist/session-view/store.js +36 -0
- package/dist/session-view/store.js.map +1 -0
- package/dist/sessions/metadata.d.ts +15 -0
- package/dist/sessions/metadata.d.ts.map +1 -0
- package/dist/sessions/metadata.js +11 -0
- package/dist/sessions/metadata.js.map +1 -0
- package/dist/sessions/policy.d.ts +13 -0
- package/dist/sessions/policy.d.ts.map +1 -0
- package/dist/sessions/policy.js +23 -0
- package/dist/sessions/policy.js.map +1 -0
- package/dist/sessions/store.d.ts +103 -0
- package/dist/sessions/store.d.ts.map +1 -0
- package/dist/sessions/store.js +349 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/store.d.ts +58 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +152 -0
- package/dist/store.js.map +1 -0
- package/dist/tool-diagnostics.d.ts +2 -0
- package/dist/tool-diagnostics.d.ts.map +1 -0
- package/dist/tool-diagnostics.js +7 -0
- package/dist/tool-diagnostics.js.map +1 -0
- package/dist/tools/bash.d.ts +10 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +80 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit.d.ts +11 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +133 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/event.d.ts +62 -0
- package/dist/tools/event.d.ts.map +1 -0
- package/dist/tools/event.js +138 -0
- package/dist/tools/event.js.map +1 -0
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +23 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read.d.ts +11 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +136 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/truncate.d.ts +57 -0
- package/dist/tools/truncate.d.ts.map +1 -0
- package/dist/tools/truncate.js +184 -0
- package/dist/tools/truncate.js.map +1 -0
- package/dist/tools/write.d.ts +10 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +33 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/trigger.d.ts +31 -0
- package/dist/trigger.d.ts.map +1 -0
- package/dist/trigger.js +98 -0
- package/dist/trigger.js.map +1 -0
- package/dist/ui-copy.d.ts +12 -0
- package/dist/ui-copy.d.ts.map +1 -0
- package/dist/ui-copy.js +36 -0
- package/dist/ui-copy.js.map +1 -0
- package/dist/vault-routing.d.ts +4 -0
- package/dist/vault-routing.d.ts.map +1 -0
- package/dist/vault-routing.js +16 -0
- package/dist/vault-routing.js.map +1 -0
- package/dist/vault.d.ts +72 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +281 -0
- package/dist/vault.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { basename, dirname, join, resolve } from "path";
|
|
2
|
+
import { existsSync, readdirSync } from "fs";
|
|
3
|
+
import { SessionManager, } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { getThreadSessionFile, resolveChannelSessionFile, tryResolveThreadSession, } from "../sessions/store.js";
|
|
5
|
+
import { isPlatformHistorySession } from "../sessions/metadata.js";
|
|
6
|
+
import * as log from "../log.js";
|
|
7
|
+
export function resolveExistingSessionFile(workingDir, conversationId, sessionKey) {
|
|
8
|
+
const conversationDir = join(workingDir, conversationId);
|
|
9
|
+
if (sessionKey.includes(":")) {
|
|
10
|
+
return tryResolveThreadSession(getThreadSessionFile(conversationDir, sessionKey));
|
|
11
|
+
}
|
|
12
|
+
return resolveChannelSessionFile(conversationDir);
|
|
13
|
+
}
|
|
14
|
+
export function loadSessionViewModel(sessionFile) {
|
|
15
|
+
const resolvedFile = resolve(sessionFile);
|
|
16
|
+
const sm = SessionManager.open(resolvedFile);
|
|
17
|
+
const header = sm.getHeader();
|
|
18
|
+
if (!header)
|
|
19
|
+
throw new Error(`No valid session found: ${sessionFile}`);
|
|
20
|
+
const entries = sm.getEntries();
|
|
21
|
+
const updatedAt = entries.at(-1)?.timestamp ?? header.timestamp;
|
|
22
|
+
const title = sm.getSessionName() || `Session ${header.id.slice(0, 8)}`;
|
|
23
|
+
const parent = header.parentSession
|
|
24
|
+
? buildSessionRelation(resolve(header.parentSession), "parent")
|
|
25
|
+
: undefined;
|
|
26
|
+
const forks = listRelatedSessionFiles(resolvedFile)
|
|
27
|
+
.filter((candidate) => candidate !== resolvedFile)
|
|
28
|
+
.map((candidate) => buildSessionRelation(candidate, "fork", resolvedFile))
|
|
29
|
+
.filter((relation) => relation !== null)
|
|
30
|
+
.toSorted((a, b) => (a.updatedAt < b.updatedAt ? -1 : a.updatedAt > b.updatedAt ? 1 : 0));
|
|
31
|
+
const forksByEntryId = new Map();
|
|
32
|
+
for (const fork of forks) {
|
|
33
|
+
if (!fork.anchorEntryId)
|
|
34
|
+
continue;
|
|
35
|
+
const bucket = forksByEntryId.get(fork.anchorEntryId) ?? [];
|
|
36
|
+
bucket.push(fork);
|
|
37
|
+
forksByEntryId.set(fork.anchorEntryId, bucket);
|
|
38
|
+
}
|
|
39
|
+
const items = entries.flatMap((entry) => {
|
|
40
|
+
const item = mapEntryToItem(entry);
|
|
41
|
+
if (!item)
|
|
42
|
+
return [];
|
|
43
|
+
if (item.entryId) {
|
|
44
|
+
const anchoredForks = forksByEntryId.get(item.entryId);
|
|
45
|
+
if (anchoredForks) {
|
|
46
|
+
item.forks = anchoredForks;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return [item];
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
sessionId: header.id,
|
|
53
|
+
fileName: basename(resolvedFile),
|
|
54
|
+
title,
|
|
55
|
+
createdAt: header.timestamp,
|
|
56
|
+
updatedAt,
|
|
57
|
+
entryCount: entries.length,
|
|
58
|
+
items,
|
|
59
|
+
parent: parent ?? undefined,
|
|
60
|
+
forks,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function resolveRequestedSessionFile(baseSessionFile, requestedFileName) {
|
|
64
|
+
const resolvedBase = resolve(baseSessionFile);
|
|
65
|
+
if (!requestedFileName)
|
|
66
|
+
return resolvedBase;
|
|
67
|
+
const trimmed = requestedFileName.trim();
|
|
68
|
+
if (!trimmed)
|
|
69
|
+
return resolvedBase;
|
|
70
|
+
const fileName = basename(trimmed);
|
|
71
|
+
if (fileName !== trimmed || !fileName.endsWith(".jsonl"))
|
|
72
|
+
return null;
|
|
73
|
+
const candidate = join(dirname(resolvedBase), fileName);
|
|
74
|
+
if (!existsSync(candidate))
|
|
75
|
+
return null;
|
|
76
|
+
let sm;
|
|
77
|
+
try {
|
|
78
|
+
sm = SessionManager.open(candidate);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
throw new Error(`Session file is corrupted: ${candidate}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
82
|
+
}
|
|
83
|
+
if (!sm.getHeader()) {
|
|
84
|
+
throw new Error(`Session file is missing a valid header: ${candidate}`);
|
|
85
|
+
}
|
|
86
|
+
return candidate;
|
|
87
|
+
}
|
|
88
|
+
function listRelatedSessionFiles(sessionFile) {
|
|
89
|
+
const dir = dirname(sessionFile);
|
|
90
|
+
if (!existsSync(dir))
|
|
91
|
+
return [];
|
|
92
|
+
return readdirSync(dir)
|
|
93
|
+
.filter((name) => name.endsWith(".jsonl"))
|
|
94
|
+
.map((fileName) => join(dir, fileName));
|
|
95
|
+
}
|
|
96
|
+
function buildSessionRelation(sessionFile, kind, expectedParent) {
|
|
97
|
+
let sm;
|
|
98
|
+
try {
|
|
99
|
+
sm = SessionManager.open(sessionFile);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
log.logWarning(`Skipping corrupted session file while building ${kind} relation: ${sessionFile}`, err instanceof Error ? err.message : String(err));
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const header = sm.getHeader();
|
|
106
|
+
if (!header) {
|
|
107
|
+
log.logWarning(`Skipping session file with missing header while building ${kind} relation: ${sessionFile}`);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (kind === "fork") {
|
|
111
|
+
const parentSession = resolve(header.parentSession ?? "");
|
|
112
|
+
if (parentSession !== expectedParent &&
|
|
113
|
+
!(expectedParent &&
|
|
114
|
+
isPlatformHistorySession(expectedParent) &&
|
|
115
|
+
isPlatformHistorySession(parentSession))) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const entries = sm.getEntries();
|
|
120
|
+
const updatedAt = entries.at(-1)?.timestamp ?? header.timestamp;
|
|
121
|
+
const anchorEntryId = kind === "fork" && expectedParent
|
|
122
|
+
? findForkAnchorEntryId(SessionManager.open(expectedParent).getEntries(), entries)
|
|
123
|
+
: undefined;
|
|
124
|
+
return {
|
|
125
|
+
kind,
|
|
126
|
+
fileName: basename(sessionFile),
|
|
127
|
+
sessionId: header.id,
|
|
128
|
+
title: sm.getSessionName() || `Session ${header.id.slice(0, 8)}`,
|
|
129
|
+
updatedAt,
|
|
130
|
+
entryCount: entries.length,
|
|
131
|
+
summary: extractSessionSummary(entries),
|
|
132
|
+
anchorEntryId,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function findForkAnchorEntryId(parentEntries, childEntries) {
|
|
136
|
+
let sharedCount = 0;
|
|
137
|
+
while (sharedCount < parentEntries.length &&
|
|
138
|
+
sharedCount < childEntries.length &&
|
|
139
|
+
parentEntries[sharedCount]?.id === childEntries[sharedCount]?.id) {
|
|
140
|
+
sharedCount += 1;
|
|
141
|
+
}
|
|
142
|
+
if (sharedCount > 0) {
|
|
143
|
+
return parentEntries[sharedCount - 1]?.id;
|
|
144
|
+
}
|
|
145
|
+
const childRoot = findComparableUserMessage(childEntries);
|
|
146
|
+
if (!childRoot)
|
|
147
|
+
return undefined;
|
|
148
|
+
return findParentAnchorByRootMessage(parentEntries, childRoot);
|
|
149
|
+
}
|
|
150
|
+
function findParentAnchorByRootMessage(parentEntries, childRoot) {
|
|
151
|
+
let textMatchId;
|
|
152
|
+
for (const entry of parentEntries) {
|
|
153
|
+
const comparable = getComparableUserMessage(entry);
|
|
154
|
+
if (!comparable)
|
|
155
|
+
continue;
|
|
156
|
+
if (comparable.normalizedText !== childRoot.normalizedText)
|
|
157
|
+
continue;
|
|
158
|
+
if (childRoot.messageTimestamp !== undefined &&
|
|
159
|
+
comparable.messageTimestamp !== undefined &&
|
|
160
|
+
comparable.messageTimestamp === childRoot.messageTimestamp) {
|
|
161
|
+
return entry.id;
|
|
162
|
+
}
|
|
163
|
+
textMatchId ??= entry.id;
|
|
164
|
+
}
|
|
165
|
+
return textMatchId;
|
|
166
|
+
}
|
|
167
|
+
function findComparableUserMessage(entries) {
|
|
168
|
+
for (const entry of entries) {
|
|
169
|
+
const comparable = getComparableUserMessage(entry);
|
|
170
|
+
if (comparable)
|
|
171
|
+
return comparable;
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
function getComparableUserMessage(entry) {
|
|
176
|
+
if (entry.type !== "message" || entry.message.role !== "user")
|
|
177
|
+
return null;
|
|
178
|
+
const body = contentToText(entry.message.content);
|
|
179
|
+
const normalizedText = normalizeComparableUserText(body);
|
|
180
|
+
if (!normalizedText)
|
|
181
|
+
return null;
|
|
182
|
+
const messageTimestamp = typeof entry.message.timestamp === "number" ? entry.message.timestamp : undefined;
|
|
183
|
+
return { normalizedText, messageTimestamp };
|
|
184
|
+
}
|
|
185
|
+
function normalizeComparableUserText(text) {
|
|
186
|
+
const withoutTimestamp = text.replace(/^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{2}:[0-9]{2}\]\s+(?=\[[^\]]+\](?:\s+\[in-thread:[^\]]+\])?:\s)/, "");
|
|
187
|
+
return stripSlackAttachmentBlock(withoutTimestamp).trim();
|
|
188
|
+
}
|
|
189
|
+
function stripSlackAttachmentBlock(text) {
|
|
190
|
+
return text.replace(/\n*<slack_attachments>\n[\s\S]*?\n<\/slack_attachments>\s*$/g, "");
|
|
191
|
+
}
|
|
192
|
+
function extractSessionSummary(entries) {
|
|
193
|
+
for (const entry of entries) {
|
|
194
|
+
if (entry.type !== "message")
|
|
195
|
+
continue;
|
|
196
|
+
const item = mapEntryToItem(entry);
|
|
197
|
+
if (!item?.body)
|
|
198
|
+
continue;
|
|
199
|
+
return collapseSummary(item.body);
|
|
200
|
+
}
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
function collapseSummary(text) {
|
|
204
|
+
const singleLine = text.replace(/\s+/g, " ").trim();
|
|
205
|
+
return singleLine.length > 96 ? `${singleLine.slice(0, 93)}…` : singleLine;
|
|
206
|
+
}
|
|
207
|
+
function mapEntryToItem(entry) {
|
|
208
|
+
switch (entry.type) {
|
|
209
|
+
case "message":
|
|
210
|
+
return mapMessageEntry(entry);
|
|
211
|
+
case "model_change":
|
|
212
|
+
return {
|
|
213
|
+
kind: "system",
|
|
214
|
+
title: "Model changed",
|
|
215
|
+
body: `${entry.provider} / ${entry.modelId}`,
|
|
216
|
+
meta: entry.timestamp,
|
|
217
|
+
tone: "muted",
|
|
218
|
+
};
|
|
219
|
+
case "thinking_level_change":
|
|
220
|
+
return {
|
|
221
|
+
kind: "system",
|
|
222
|
+
title: "Thinking level changed",
|
|
223
|
+
body: entry.thinkingLevel,
|
|
224
|
+
meta: entry.timestamp,
|
|
225
|
+
tone: "muted",
|
|
226
|
+
};
|
|
227
|
+
case "compaction":
|
|
228
|
+
return mapCompactionEntry(entry);
|
|
229
|
+
case "branch_summary":
|
|
230
|
+
return mapBranchSummaryEntry(entry);
|
|
231
|
+
case "custom_message":
|
|
232
|
+
return {
|
|
233
|
+
kind: "system",
|
|
234
|
+
title: `Custom message · ${entry.customType}`,
|
|
235
|
+
body: contentToText(entry.content),
|
|
236
|
+
meta: entry.timestamp,
|
|
237
|
+
tone: "muted",
|
|
238
|
+
};
|
|
239
|
+
case "custom":
|
|
240
|
+
return {
|
|
241
|
+
kind: "system",
|
|
242
|
+
title: `Custom data · ${entry.customType}`,
|
|
243
|
+
body: entry.data === undefined ? "(no data)" : JSON.stringify(entry.data, null, 2),
|
|
244
|
+
meta: entry.timestamp,
|
|
245
|
+
tone: "muted",
|
|
246
|
+
};
|
|
247
|
+
case "label":
|
|
248
|
+
return {
|
|
249
|
+
kind: "system",
|
|
250
|
+
title: "Label updated",
|
|
251
|
+
body: entry.label || "(cleared)",
|
|
252
|
+
meta: entry.timestamp,
|
|
253
|
+
tone: "muted",
|
|
254
|
+
};
|
|
255
|
+
case "session_info":
|
|
256
|
+
return entry.name
|
|
257
|
+
? {
|
|
258
|
+
kind: "system",
|
|
259
|
+
title: "Session renamed",
|
|
260
|
+
body: entry.name,
|
|
261
|
+
meta: entry.timestamp,
|
|
262
|
+
tone: "muted",
|
|
263
|
+
}
|
|
264
|
+
: null;
|
|
265
|
+
default:
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function mapMessageEntry(entry) {
|
|
270
|
+
const message = entry.message;
|
|
271
|
+
switch (message.role) {
|
|
272
|
+
case "user":
|
|
273
|
+
return {
|
|
274
|
+
kind: "user",
|
|
275
|
+
title: "User",
|
|
276
|
+
body: contentToText(message.content),
|
|
277
|
+
meta: entry.timestamp,
|
|
278
|
+
entryId: entry.id,
|
|
279
|
+
};
|
|
280
|
+
case "assistant": {
|
|
281
|
+
const assistantBody = assistantContentToText(message.content) ||
|
|
282
|
+
(message.errorMessage ? `_${message.errorMessage}_` : "");
|
|
283
|
+
const metaParts = [message.provider, message.model, message.stopReason].filter(Boolean);
|
|
284
|
+
return {
|
|
285
|
+
kind: "assistant",
|
|
286
|
+
title: "Assistant",
|
|
287
|
+
body: assistantBody,
|
|
288
|
+
meta: metaParts.length > 0 ? `${entry.timestamp} · ${metaParts.join(" · ")}` : entry.timestamp,
|
|
289
|
+
entryId: entry.id,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
case "toolResult":
|
|
293
|
+
return {
|
|
294
|
+
kind: "tool",
|
|
295
|
+
title: `Tool result · ${String(message.toolName ?? "unknown")}`,
|
|
296
|
+
body: contentToText(message.content),
|
|
297
|
+
meta: entry.timestamp,
|
|
298
|
+
tone: message.isError ? "err" : "ok",
|
|
299
|
+
entryId: entry.id,
|
|
300
|
+
};
|
|
301
|
+
case "bashExecution": {
|
|
302
|
+
const command = String(message.command ?? "").trim();
|
|
303
|
+
const output = String(message.output ?? "").trim();
|
|
304
|
+
const details = [
|
|
305
|
+
typeof message.exitCode === "number" ? `[exitCode] ${message.exitCode}` : "",
|
|
306
|
+
message.cancelled ? `[cancelled] true` : "",
|
|
307
|
+
message.truncated ? `[truncated] true` : "",
|
|
308
|
+
].filter(Boolean);
|
|
309
|
+
const body = [command ? `$ ${command}` : "", output, ...details].filter(Boolean).join("\n\n");
|
|
310
|
+
return {
|
|
311
|
+
kind: "tool",
|
|
312
|
+
title: "Bash execution",
|
|
313
|
+
body: body || "(no output)",
|
|
314
|
+
meta: entry.timestamp,
|
|
315
|
+
entryId: entry.id,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
case "custom":
|
|
319
|
+
return {
|
|
320
|
+
kind: "system",
|
|
321
|
+
title: `Custom message · ${String(message.customType ?? "custom")}`,
|
|
322
|
+
body: contentToText(message.content),
|
|
323
|
+
meta: entry.timestamp,
|
|
324
|
+
tone: "muted",
|
|
325
|
+
entryId: entry.id,
|
|
326
|
+
};
|
|
327
|
+
case "branchSummary":
|
|
328
|
+
return {
|
|
329
|
+
kind: "system",
|
|
330
|
+
title: "Branch summary",
|
|
331
|
+
body: String(message.summary ?? ""),
|
|
332
|
+
meta: entry.timestamp,
|
|
333
|
+
tone: "muted",
|
|
334
|
+
entryId: entry.id,
|
|
335
|
+
};
|
|
336
|
+
case "compactionSummary":
|
|
337
|
+
return {
|
|
338
|
+
kind: "system",
|
|
339
|
+
title: "Compaction summary",
|
|
340
|
+
body: String(message.summary ?? ""),
|
|
341
|
+
meta: entry.timestamp,
|
|
342
|
+
tone: "muted",
|
|
343
|
+
entryId: entry.id,
|
|
344
|
+
};
|
|
345
|
+
default:
|
|
346
|
+
return {
|
|
347
|
+
kind: "system",
|
|
348
|
+
title: `Message · ${String(message.role ?? "unknown")}`,
|
|
349
|
+
body: contentToText(message.content),
|
|
350
|
+
meta: entry.timestamp,
|
|
351
|
+
tone: "muted",
|
|
352
|
+
entryId: entry.id,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
function mapCompactionEntry(entry) {
|
|
357
|
+
return {
|
|
358
|
+
kind: "system",
|
|
359
|
+
title: "Context compacted",
|
|
360
|
+
body: entry.summary,
|
|
361
|
+
meta: `${entry.timestamp} · ${entry.tokensBefore} tokens before compaction`,
|
|
362
|
+
tone: "muted",
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function mapBranchSummaryEntry(entry) {
|
|
366
|
+
return {
|
|
367
|
+
kind: "system",
|
|
368
|
+
title: "Branch summary",
|
|
369
|
+
body: entry.summary,
|
|
370
|
+
meta: entry.timestamp,
|
|
371
|
+
tone: "muted",
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
function assistantContentToText(content) {
|
|
375
|
+
if (typeof content === "string")
|
|
376
|
+
return content;
|
|
377
|
+
if (!Array.isArray(content))
|
|
378
|
+
return "";
|
|
379
|
+
const lines = [];
|
|
380
|
+
for (const block of content) {
|
|
381
|
+
if (!block || typeof block !== "object")
|
|
382
|
+
continue;
|
|
383
|
+
const value = block;
|
|
384
|
+
if (value.type === "text" && typeof value.text === "string") {
|
|
385
|
+
lines.push(value.text);
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
if (value.type === "thinking" && typeof value.thinking === "string") {
|
|
389
|
+
lines.push(`[thinking]\n${value.thinking}`);
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
if (value.type === "toolCall") {
|
|
393
|
+
const name = typeof value.name === "string" ? value.name : "tool";
|
|
394
|
+
const args = value.arguments === undefined ? "" : JSON.stringify(value.arguments, null, 2);
|
|
395
|
+
lines.push([`[toolCall] ${name}`, args].filter(Boolean).join("\n"));
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
if (value.type === "image") {
|
|
399
|
+
lines.push(`[image ${String(value.mimeType ?? "unknown")}]`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return lines.join("\n\n");
|
|
403
|
+
}
|
|
404
|
+
function contentToText(content) {
|
|
405
|
+
if (typeof content === "string")
|
|
406
|
+
return content;
|
|
407
|
+
if (!Array.isArray(content))
|
|
408
|
+
return "";
|
|
409
|
+
const lines = [];
|
|
410
|
+
for (const block of content) {
|
|
411
|
+
if (!block || typeof block !== "object")
|
|
412
|
+
continue;
|
|
413
|
+
const value = block;
|
|
414
|
+
if (value.type === "text" && typeof value.text === "string") {
|
|
415
|
+
lines.push(value.text);
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (value.type === "thinking" && typeof value.thinking === "string") {
|
|
419
|
+
lines.push(`[thinking]\n${value.thinking}`);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (value.type === "toolCall") {
|
|
423
|
+
const name = typeof value.name === "string" ? value.name : "tool";
|
|
424
|
+
const args = value.arguments === undefined ? "" : JSON.stringify(value.arguments, null, 2);
|
|
425
|
+
lines.push([`[toolCall] ${name}`, args].filter(Boolean).join("\n"));
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (value.type === "image") {
|
|
429
|
+
lines.push(`[image ${String(value.mimeType ?? "unknown")}]`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return lines.join("\n\n");
|
|
433
|
+
}
|
|
434
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/session-view/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,EACL,cAAc,GAKf,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AAmCjC,MAAM,UAAU,0BAA0B,CACxC,UAAkB,EAClB,cAAsB,EACtB,UAAkB;IAElB,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACzD,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,uBAAuB,CAAC,oBAAoB,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,yBAAyB,CAAC,eAAe,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;IAC9B,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,WAAW,EAAE,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;IAChE,MAAM,KAAK,GAAG,EAAE,CAAC,cAAc,EAAE,IAAI,WAAW,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAExE,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa;QACjC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC;QAC/D,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,KAAK,GAAG,uBAAuB,CAAC,YAAY,CAAC;SAChD,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,YAAY,CAAC;SACjD,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;SACzE,MAAM,CAAC,CAAC,QAAQ,EAAmC,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC;SACxE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5F,MAAM,cAAc,GAAG,IAAI,GAAG,EAAiC,CAAC;IAChE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,SAAS;QAClC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACtC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,aAAa,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,EAAE;QACpB,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC;QAChC,KAAK;QACL,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS;QACT,UAAU,EAAE,OAAO,CAAC,MAAM;QAC1B,KAAK;QACL,MAAM,EAAE,MAAM,IAAI,SAAS;QAC3B,KAAK;KACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,eAAuB,EACvB,iBAAiC;IAEjC,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9C,IAAI,CAAC,iBAAiB;QAAE,OAAO,YAAY,CAAC;IAE5C,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC;IACzC,IAAI,CAAC,OAAO;QAAE,OAAO,YAAY,CAAC;IAElC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,IAAI,EAAkB,CAAC;IACvB,IAAI,CAAC;QACH,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,8BAA8B,SAAS,KACrC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,EAAE,EACF,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,2CAA2C,SAAS,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,uBAAuB,CAAC,WAAmB;IAClD,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAEhC,OAAO,WAAW,CAAC,GAAG,CAAC;SACpB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;SACzC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,oBAAoB,CAC3B,WAAmB,EACnB,IAAuB,EACvB,cAAuB;IAEvB,IAAI,EAAkB,CAAC;IACvB,IAAI,CAAC;QACH,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,UAAU,CACZ,kDAAkD,IAAI,cAAc,WAAW,EAAE,EACjF,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;IAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,UAAU,CACZ,4DAA4D,IAAI,cAAc,WAAW,EAAE,CAC5F,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QAC1D,IACE,aAAa,KAAK,cAAc;YAChC,CAAC,CACC,cAAc;gBACd,wBAAwB,CAAC,cAAc,CAAC;gBACxC,wBAAwB,CAAC,aAAa,CAAC,CACxC,EACD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;IAChE,MAAM,aAAa,GACjB,IAAI,KAAK,MAAM,IAAI,cAAc;QAC/B,CAAC,CAAC,qBAAqB,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC;QAClF,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO;QACL,IAAI;QACJ,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC;QAC/B,SAAS,EAAE,MAAM,CAAC,EAAE;QACpB,KAAK,EAAE,EAAE,CAAC,cAAc,EAAE,IAAI,WAAW,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QAChE,SAAS;QACT,UAAU,EAAE,OAAO,CAAC,MAAM;QAC1B,OAAO,EAAE,qBAAqB,CAAC,OAAO,CAAC;QACvC,aAAa;KACd,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,aAA6B,EAC7B,YAA4B;IAE5B,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,OACE,WAAW,GAAG,aAAa,CAAC,MAAM;QAClC,WAAW,GAAG,YAAY,CAAC,MAAM;QACjC,aAAa,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,YAAY,CAAC,WAAW,CAAC,EAAE,EAAE,EAChE,CAAC;QACD,WAAW,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,aAAa,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,SAAS,GAAG,yBAAyB,CAAC,YAAY,CAAC,CAAC;IAC1D,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IAEjC,OAAO,6BAA6B,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,6BAA6B,CACpC,aAA6B,EAC7B,SAAgC;IAEhC,IAAI,WAA+B,CAAC;IAEpC,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,CAAC,cAAc;YAAE,SAAS;QACrE,IACE,SAAS,CAAC,gBAAgB,KAAK,SAAS;YACxC,UAAU,CAAC,gBAAgB,KAAK,SAAS;YACzC,UAAU,CAAC,gBAAgB,KAAK,SAAS,CAAC,gBAAgB,EAC1D,CAAC;YACD,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,CAAC;QACD,WAAW,KAAK,KAAK,CAAC,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAOD,SAAS,yBAAyB,CAAC,OAAuB;IACxD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAmB;IACnD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAE3E,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG,2BAA2B,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IAEjC,MAAM,gBAAgB,GACpB,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,2BAA2B,CAAC,IAAY;IAC/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CACnC,iIAAiI,EACjI,EAAE,CACH,CAAC;IACF,OAAO,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5D,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAY;IAC7C,OAAO,IAAI,CAAC,OAAO,CAAC,8DAA8D,EAAE,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAuB;IACpD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACvC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,IAAI;YAAE,SAAS;QAC1B,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,OAAO,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;AAC7E,CAAC;AAED,SAAS,cAAc,CAAC,KAAmB;IACzC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,SAAS;YACZ,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;QAChC,KAAK,cAAc;YACjB,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,eAAe;gBACtB,IAAI,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,KAAK,CAAC,OAAO,EAAE;gBAC5C,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;aACd,CAAC;QACJ,KAAK,uBAAuB;YAC1B,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,wBAAwB;gBAC/B,IAAI,EAAE,KAAK,CAAC,aAAa;gBACzB,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;aACd,CAAC;QACJ,KAAK,YAAY;YACf,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACnC,KAAK,gBAAgB;YACnB,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACtC,KAAK,gBAAgB;YACnB,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,oBAAoB,KAAK,CAAC,UAAU,EAAE;gBAC7C,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC;gBAClC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;aACd,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,iBAAiB,KAAK,CAAC,UAAU,EAAE;gBAC1C,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClF,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;aACd,CAAC;QACJ,KAAK,OAAO;YACV,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,eAAe;gBACtB,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,WAAW;gBAChC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;aACd,CAAC;QACJ,KAAK,cAAc;YACjB,OAAO,KAAK,CAAC,IAAI;gBACf,CAAC,CAAC;oBACE,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,iBAAiB;oBACxB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,IAAI,EAAE,KAAK,CAAC,SAAS;oBACrB,IAAI,EAAE,OAAO;iBACd;gBACH,CAAC,CAAC,IAAI,CAAC;QACX;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAA0B;IACjD,MAAM,OAAO,GAAG,KAAK,CAAC,OAgBrB,CAAC;IAEF,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,MAAM;YACT,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,MAAM;gBACb,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC;gBACpC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;QACJ,KAAK,WAAW,EAAE,CAAC;YACjB,MAAM,aAAa,GACjB,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC;gBACvC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5D,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxF,OAAO;gBACL,IAAI,EAAE,WAAW;gBACjB,KAAK,EAAE,WAAW;gBAClB,IAAI,EAAE,aAAa;gBACnB,IAAI,EACF,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;gBAC1F,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;QACJ,CAAC;QACD,KAAK,YAAY;YACf,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,iBAAiB,MAAM,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC,EAAE;gBAC/D,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC;gBACpC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;gBACpC,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;QACJ,KAAK,eAAe,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACrD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,MAAM,OAAO,GAAG;gBACd,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE;gBAC5E,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE;gBAC3C,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE;aAC5C,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9F,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,gBAAgB;gBACvB,IAAI,EAAE,IAAI,IAAI,aAAa;gBAC3B,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;QACJ,CAAC;QACD,KAAK,QAAQ;YACX,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,oBAAoB,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,QAAQ,CAAC,EAAE;gBACnE,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC;gBACpC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;QACJ,KAAK,eAAe;YAClB,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,gBAAgB;gBACvB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;gBACnC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;QACJ,KAAK,mBAAmB;YACtB,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,oBAAoB;gBAC3B,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;gBACnC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;QACJ;YACE,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,aAAa,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE;gBACvD,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC;gBACpC,IAAI,EAAE,KAAK,CAAC,SAAS;gBACrB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,KAAK,CAAC,EAAE;aAClB,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAsB;IAChD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,KAAK,CAAC,OAAO;QACnB,IAAI,EAAE,GAAG,KAAK,CAAC,SAAS,MAAM,KAAK,CAAC,YAAY,2BAA2B;QAC3E,IAAI,EAAE,OAAO;KACd,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAyB;IACtD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,KAAK,CAAC,OAAO;QACnB,IAAI,EAAE,KAAK,CAAC,SAAS;QACrB,IAAI,EAAE,OAAO;KACd,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAgB;IAC9C,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QAClD,MAAM,KAAK,GAAG,KAAgC,CAAC;QAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACpE,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;YAClE,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3F,KAAK,CAAC,IAAI,CAAC,CAAC,cAAc,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACpE,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB;IACrC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QAClD,MAAM,KAAK,GAAG,KAAgC,CAAC;QAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACpE,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;YAClE,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3F,KAAK,CAAC,IAAI,CAAC,CAAC,cAAc,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACpE,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC","sourcesContent":["import { basename, dirname, join, resolve } from \"path\";\nimport { existsSync, readdirSync } from \"fs\";\nimport {\n SessionManager,\n type BranchSummaryEntry,\n type CompactionEntry,\n type SessionEntry,\n type SessionMessageEntry,\n} from \"@earendil-works/pi-coding-agent\";\nimport {\n getThreadSessionFile,\n resolveChannelSessionFile,\n tryResolveThreadSession,\n} from \"../sessions/store.js\";\nimport { isPlatformHistorySession } from \"../sessions/metadata.js\";\nimport * as log from \"../log.js\";\n\nexport interface SessionViewItem {\n kind: \"user\" | \"assistant\" | \"tool\" | \"system\";\n title: string;\n body?: string;\n meta?: string;\n tone?: \"default\" | \"ok\" | \"err\" | \"muted\";\n entryId?: string;\n forks?: SessionViewRelation[];\n}\n\nexport interface SessionViewRelation {\n kind: \"parent\" | \"fork\";\n fileName: string;\n sessionId: string;\n title: string;\n updatedAt: string;\n entryCount: number;\n summary?: string;\n anchorEntryId?: string;\n}\n\nexport interface SessionViewModel {\n sessionId: string;\n fileName: string;\n title: string;\n createdAt: string;\n updatedAt: string;\n entryCount: number;\n items: SessionViewItem[];\n parent?: SessionViewRelation;\n forks: SessionViewRelation[];\n}\n\nexport function resolveExistingSessionFile(\n workingDir: string,\n conversationId: string,\n sessionKey: string,\n): string | null {\n const conversationDir = join(workingDir, conversationId);\n if (sessionKey.includes(\":\")) {\n return tryResolveThreadSession(getThreadSessionFile(conversationDir, sessionKey));\n }\n return resolveChannelSessionFile(conversationDir);\n}\n\nexport function loadSessionViewModel(sessionFile: string): SessionViewModel {\n const resolvedFile = resolve(sessionFile);\n const sm = SessionManager.open(resolvedFile);\n const header = sm.getHeader();\n if (!header) throw new Error(`No valid session found: ${sessionFile}`);\n\n const entries = sm.getEntries();\n const updatedAt = entries.at(-1)?.timestamp ?? header.timestamp;\n const title = sm.getSessionName() || `Session ${header.id.slice(0, 8)}`;\n\n const parent = header.parentSession\n ? buildSessionRelation(resolve(header.parentSession), \"parent\")\n : undefined;\n const forks = listRelatedSessionFiles(resolvedFile)\n .filter((candidate) => candidate !== resolvedFile)\n .map((candidate) => buildSessionRelation(candidate, \"fork\", resolvedFile))\n .filter((relation): relation is SessionViewRelation => relation !== null)\n .toSorted((a, b) => (a.updatedAt < b.updatedAt ? -1 : a.updatedAt > b.updatedAt ? 1 : 0));\n\n const forksByEntryId = new Map<string, SessionViewRelation[]>();\n for (const fork of forks) {\n if (!fork.anchorEntryId) continue;\n const bucket = forksByEntryId.get(fork.anchorEntryId) ?? [];\n bucket.push(fork);\n forksByEntryId.set(fork.anchorEntryId, bucket);\n }\n\n const items = entries.flatMap((entry) => {\n const item = mapEntryToItem(entry);\n if (!item) return [];\n if (item.entryId) {\n const anchoredForks = forksByEntryId.get(item.entryId);\n if (anchoredForks) {\n item.forks = anchoredForks;\n }\n }\n return [item];\n });\n\n return {\n sessionId: header.id,\n fileName: basename(resolvedFile),\n title,\n createdAt: header.timestamp,\n updatedAt,\n entryCount: entries.length,\n items,\n parent: parent ?? undefined,\n forks,\n };\n}\n\nexport function resolveRequestedSessionFile(\n baseSessionFile: string,\n requestedFileName?: string | null,\n): string | null {\n const resolvedBase = resolve(baseSessionFile);\n if (!requestedFileName) return resolvedBase;\n\n const trimmed = requestedFileName.trim();\n if (!trimmed) return resolvedBase;\n\n const fileName = basename(trimmed);\n if (fileName !== trimmed || !fileName.endsWith(\".jsonl\")) return null;\n\n const candidate = join(dirname(resolvedBase), fileName);\n if (!existsSync(candidate)) return null;\n\n let sm: SessionManager;\n try {\n sm = SessionManager.open(candidate);\n } catch (err) {\n throw new Error(\n `Session file is corrupted: ${candidate}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n { cause: err },\n );\n }\n if (!sm.getHeader()) {\n throw new Error(`Session file is missing a valid header: ${candidate}`);\n }\n return candidate;\n}\n\nfunction listRelatedSessionFiles(sessionFile: string): string[] {\n const dir = dirname(sessionFile);\n if (!existsSync(dir)) return [];\n\n return readdirSync(dir)\n .filter((name) => name.endsWith(\".jsonl\"))\n .map((fileName) => join(dir, fileName));\n}\n\nfunction buildSessionRelation(\n sessionFile: string,\n kind: \"parent\" | \"fork\",\n expectedParent?: string,\n): SessionViewRelation | null {\n let sm: SessionManager;\n try {\n sm = SessionManager.open(sessionFile);\n } catch (err) {\n log.logWarning(\n `Skipping corrupted session file while building ${kind} relation: ${sessionFile}`,\n err instanceof Error ? err.message : String(err),\n );\n return null;\n }\n const header = sm.getHeader();\n if (!header) {\n log.logWarning(\n `Skipping session file with missing header while building ${kind} relation: ${sessionFile}`,\n );\n return null;\n }\n if (kind === \"fork\") {\n const parentSession = resolve(header.parentSession ?? \"\");\n if (\n parentSession !== expectedParent &&\n !(\n expectedParent &&\n isPlatformHistorySession(expectedParent) &&\n isPlatformHistorySession(parentSession)\n )\n ) {\n return null;\n }\n }\n\n const entries = sm.getEntries();\n const updatedAt = entries.at(-1)?.timestamp ?? header.timestamp;\n const anchorEntryId =\n kind === \"fork\" && expectedParent\n ? findForkAnchorEntryId(SessionManager.open(expectedParent).getEntries(), entries)\n : undefined;\n return {\n kind,\n fileName: basename(sessionFile),\n sessionId: header.id,\n title: sm.getSessionName() || `Session ${header.id.slice(0, 8)}`,\n updatedAt,\n entryCount: entries.length,\n summary: extractSessionSummary(entries),\n anchorEntryId,\n };\n}\n\nfunction findForkAnchorEntryId(\n parentEntries: SessionEntry[],\n childEntries: SessionEntry[],\n): string | undefined {\n let sharedCount = 0;\n while (\n sharedCount < parentEntries.length &&\n sharedCount < childEntries.length &&\n parentEntries[sharedCount]?.id === childEntries[sharedCount]?.id\n ) {\n sharedCount += 1;\n }\n\n if (sharedCount > 0) {\n return parentEntries[sharedCount - 1]?.id;\n }\n\n const childRoot = findComparableUserMessage(childEntries);\n if (!childRoot) return undefined;\n\n return findParentAnchorByRootMessage(parentEntries, childRoot);\n}\n\nfunction findParentAnchorByRootMessage(\n parentEntries: SessionEntry[],\n childRoot: ComparableUserMessage,\n): string | undefined {\n let textMatchId: string | undefined;\n\n for (const entry of parentEntries) {\n const comparable = getComparableUserMessage(entry);\n if (!comparable) continue;\n if (comparable.normalizedText !== childRoot.normalizedText) continue;\n if (\n childRoot.messageTimestamp !== undefined &&\n comparable.messageTimestamp !== undefined &&\n comparable.messageTimestamp === childRoot.messageTimestamp\n ) {\n return entry.id;\n }\n textMatchId ??= entry.id;\n }\n\n return textMatchId;\n}\n\ninterface ComparableUserMessage {\n normalizedText: string;\n messageTimestamp?: number;\n}\n\nfunction findComparableUserMessage(entries: SessionEntry[]): ComparableUserMessage | null {\n for (const entry of entries) {\n const comparable = getComparableUserMessage(entry);\n if (comparable) return comparable;\n }\n return null;\n}\n\nfunction getComparableUserMessage(entry: SessionEntry): ComparableUserMessage | null {\n if (entry.type !== \"message\" || entry.message.role !== \"user\") return null;\n\n const body = contentToText(entry.message.content);\n const normalizedText = normalizeComparableUserText(body);\n if (!normalizedText) return null;\n\n const messageTimestamp =\n typeof entry.message.timestamp === \"number\" ? entry.message.timestamp : undefined;\n return { normalizedText, messageTimestamp };\n}\n\nfunction normalizeComparableUserText(text: string): string {\n const withoutTimestamp = text.replace(\n /^\\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{2}:[0-9]{2}\\]\\s+(?=\\[[^\\]]+\\](?:\\s+\\[in-thread:[^\\]]+\\])?:\\s)/,\n \"\",\n );\n return stripSlackAttachmentBlock(withoutTimestamp).trim();\n}\n\nfunction stripSlackAttachmentBlock(text: string): string {\n return text.replace(/\\n*<slack_attachments>\\n[\\s\\S]*?\\n<\\/slack_attachments>\\s*$/g, \"\");\n}\n\nfunction extractSessionSummary(entries: SessionEntry[]): string | undefined {\n for (const entry of entries) {\n if (entry.type !== \"message\") continue;\n const item = mapEntryToItem(entry);\n if (!item?.body) continue;\n return collapseSummary(item.body);\n }\n return undefined;\n}\n\nfunction collapseSummary(text: string): string {\n const singleLine = text.replace(/\\s+/g, \" \").trim();\n return singleLine.length > 96 ? `${singleLine.slice(0, 93)}…` : singleLine;\n}\n\nfunction mapEntryToItem(entry: SessionEntry): SessionViewItem | null {\n switch (entry.type) {\n case \"message\":\n return mapMessageEntry(entry);\n case \"model_change\":\n return {\n kind: \"system\",\n title: \"Model changed\",\n body: `${entry.provider} / ${entry.modelId}`,\n meta: entry.timestamp,\n tone: \"muted\",\n };\n case \"thinking_level_change\":\n return {\n kind: \"system\",\n title: \"Thinking level changed\",\n body: entry.thinkingLevel,\n meta: entry.timestamp,\n tone: \"muted\",\n };\n case \"compaction\":\n return mapCompactionEntry(entry);\n case \"branch_summary\":\n return mapBranchSummaryEntry(entry);\n case \"custom_message\":\n return {\n kind: \"system\",\n title: `Custom message · ${entry.customType}`,\n body: contentToText(entry.content),\n meta: entry.timestamp,\n tone: \"muted\",\n };\n case \"custom\":\n return {\n kind: \"system\",\n title: `Custom data · ${entry.customType}`,\n body: entry.data === undefined ? \"(no data)\" : JSON.stringify(entry.data, null, 2),\n meta: entry.timestamp,\n tone: \"muted\",\n };\n case \"label\":\n return {\n kind: \"system\",\n title: \"Label updated\",\n body: entry.label || \"(cleared)\",\n meta: entry.timestamp,\n tone: \"muted\",\n };\n case \"session_info\":\n return entry.name\n ? {\n kind: \"system\",\n title: \"Session renamed\",\n body: entry.name,\n meta: entry.timestamp,\n tone: \"muted\",\n }\n : null;\n default:\n return null;\n }\n}\n\nfunction mapMessageEntry(entry: SessionMessageEntry): SessionViewItem {\n const message = entry.message as unknown as Record<string, unknown> & {\n role?: string;\n content?: unknown;\n provider?: string;\n model?: string;\n toolName?: string;\n isError?: boolean;\n command?: string;\n output?: string;\n exitCode?: number;\n cancelled?: boolean;\n truncated?: boolean;\n stopReason?: string;\n errorMessage?: string;\n customType?: string;\n summary?: string;\n };\n\n switch (message.role) {\n case \"user\":\n return {\n kind: \"user\",\n title: \"User\",\n body: contentToText(message.content),\n meta: entry.timestamp,\n entryId: entry.id,\n };\n case \"assistant\": {\n const assistantBody =\n assistantContentToText(message.content) ||\n (message.errorMessage ? `_${message.errorMessage}_` : \"\");\n const metaParts = [message.provider, message.model, message.stopReason].filter(Boolean);\n return {\n kind: \"assistant\",\n title: \"Assistant\",\n body: assistantBody,\n meta:\n metaParts.length > 0 ? `${entry.timestamp} · ${metaParts.join(\" · \")}` : entry.timestamp,\n entryId: entry.id,\n };\n }\n case \"toolResult\":\n return {\n kind: \"tool\",\n title: `Tool result · ${String(message.toolName ?? \"unknown\")}`,\n body: contentToText(message.content),\n meta: entry.timestamp,\n tone: message.isError ? \"err\" : \"ok\",\n entryId: entry.id,\n };\n case \"bashExecution\": {\n const command = String(message.command ?? \"\").trim();\n const output = String(message.output ?? \"\").trim();\n const details = [\n typeof message.exitCode === \"number\" ? `[exitCode] ${message.exitCode}` : \"\",\n message.cancelled ? `[cancelled] true` : \"\",\n message.truncated ? `[truncated] true` : \"\",\n ].filter(Boolean);\n const body = [command ? `$ ${command}` : \"\", output, ...details].filter(Boolean).join(\"\\n\\n\");\n return {\n kind: \"tool\",\n title: \"Bash execution\",\n body: body || \"(no output)\",\n meta: entry.timestamp,\n entryId: entry.id,\n };\n }\n case \"custom\":\n return {\n kind: \"system\",\n title: `Custom message · ${String(message.customType ?? \"custom\")}`,\n body: contentToText(message.content),\n meta: entry.timestamp,\n tone: \"muted\",\n entryId: entry.id,\n };\n case \"branchSummary\":\n return {\n kind: \"system\",\n title: \"Branch summary\",\n body: String(message.summary ?? \"\"),\n meta: entry.timestamp,\n tone: \"muted\",\n entryId: entry.id,\n };\n case \"compactionSummary\":\n return {\n kind: \"system\",\n title: \"Compaction summary\",\n body: String(message.summary ?? \"\"),\n meta: entry.timestamp,\n tone: \"muted\",\n entryId: entry.id,\n };\n default:\n return {\n kind: \"system\",\n title: `Message · ${String(message.role ?? \"unknown\")}`,\n body: contentToText(message.content),\n meta: entry.timestamp,\n tone: \"muted\",\n entryId: entry.id,\n };\n }\n}\n\nfunction mapCompactionEntry(entry: CompactionEntry): SessionViewItem {\n return {\n kind: \"system\",\n title: \"Context compacted\",\n body: entry.summary,\n meta: `${entry.timestamp} · ${entry.tokensBefore} tokens before compaction`,\n tone: \"muted\",\n };\n}\n\nfunction mapBranchSummaryEntry(entry: BranchSummaryEntry): SessionViewItem {\n return {\n kind: \"system\",\n title: \"Branch summary\",\n body: entry.summary,\n meta: entry.timestamp,\n tone: \"muted\",\n };\n}\n\nfunction assistantContentToText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n\n const lines: string[] = [];\n\n for (const block of content) {\n if (!block || typeof block !== \"object\") continue;\n const value = block as Record<string, unknown>;\n if (value.type === \"text\" && typeof value.text === \"string\") {\n lines.push(value.text);\n continue;\n }\n if (value.type === \"thinking\" && typeof value.thinking === \"string\") {\n lines.push(`[thinking]\\n${value.thinking}`);\n continue;\n }\n if (value.type === \"toolCall\") {\n const name = typeof value.name === \"string\" ? value.name : \"tool\";\n const args = value.arguments === undefined ? \"\" : JSON.stringify(value.arguments, null, 2);\n lines.push([`[toolCall] ${name}`, args].filter(Boolean).join(\"\\n\"));\n continue;\n }\n if (value.type === \"image\") {\n lines.push(`[image ${String(value.mimeType ?? \"unknown\")}]`);\n }\n }\n\n return lines.join(\"\\n\\n\");\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n\n const lines: string[] = [];\n for (const block of content) {\n if (!block || typeof block !== \"object\") continue;\n const value = block as Record<string, unknown>;\n if (value.type === \"text\" && typeof value.text === \"string\") {\n lines.push(value.text);\n continue;\n }\n if (value.type === \"thinking\" && typeof value.thinking === \"string\") {\n lines.push(`[thinking]\\n${value.thinking}`);\n continue;\n }\n if (value.type === \"toolCall\") {\n const name = typeof value.name === \"string\" ? value.name : \"tool\";\n const args = value.arguments === undefined ? \"\" : JSON.stringify(value.arguments, null, 2);\n lines.push([`[toolCall] ${name}`, args].filter(Boolean).join(\"\\n\"));\n continue;\n }\n if (value.type === \"image\") {\n lines.push(`[image ${String(value.mimeType ?? \"unknown\")}]`);\n }\n }\n\n return lines.join(\"\\n\\n\");\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PlatformName } from "../adapter.js";
|
|
2
|
+
export interface SessionViewToken {
|
|
3
|
+
token: string;
|
|
4
|
+
platform: PlatformName;
|
|
5
|
+
platformUserId: string;
|
|
6
|
+
platformUserName?: string;
|
|
7
|
+
conversationId: string;
|
|
8
|
+
sessionKey: string;
|
|
9
|
+
sessionFile: string;
|
|
10
|
+
expiresAt: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class InMemorySessionViewTokenStore {
|
|
13
|
+
private tokens;
|
|
14
|
+
create(platform: PlatformName, platformUserId: string, conversationId: string, sessionKey: string, sessionFile: string, platformUserName?: string): SessionViewToken;
|
|
15
|
+
peek(rawToken: string): SessionViewToken | undefined;
|
|
16
|
+
purge(): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/session-view/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,qBAAa,6BAA6B;IACxC,OAAO,CAAC,MAAM,CAAuC;IAErD,MAAM,CACJ,QAAQ,EAAE,YAAY,EACtB,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,gBAAgB,CAAC,EAAE,MAAM,GACxB,gBAAgB,CAalB;IAED,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAInD;IAED,KAAK,IAAI,IAAI,CAOZ;CACF","sourcesContent":["import { randomBytes } from \"crypto\";\nimport type { PlatformName } from \"../adapter.js\";\n\nexport interface SessionViewToken {\n token: string;\n platform: PlatformName;\n platformUserId: string;\n platformUserName?: string;\n conversationId: string;\n sessionKey: string;\n sessionFile: string;\n expiresAt: number;\n}\n\nconst TTL_MS = 24 * 60 * 60 * 1000;\n\nexport class InMemorySessionViewTokenStore {\n private tokens = new Map<string, SessionViewToken>();\n\n create(\n platform: PlatformName,\n platformUserId: string,\n conversationId: string,\n sessionKey: string,\n sessionFile: string,\n platformUserName?: string,\n ): SessionViewToken {\n const token: SessionViewToken = {\n token: randomBytes(16).toString(\"hex\"),\n platform,\n platformUserId,\n ...(platformUserName ? { platformUserName } : {}),\n conversationId,\n sessionKey,\n sessionFile,\n expiresAt: Date.now() + TTL_MS,\n };\n this.tokens.set(token.token, token);\n return token;\n }\n\n peek(rawToken: string): SessionViewToken | undefined {\n const entry = this.tokens.get(rawToken);\n if (!entry || Date.now() > entry.expiresAt) return undefined;\n return entry;\n }\n\n purge(): void {\n const now = Date.now();\n for (const [key, value] of this.tokens) {\n if (now > value.expiresAt) {\n this.tokens.delete(key);\n }\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { randomBytes } from "crypto";
|
|
2
|
+
const TTL_MS = 24 * 60 * 60 * 1000;
|
|
3
|
+
export class InMemorySessionViewTokenStore {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.tokens = new Map();
|
|
6
|
+
}
|
|
7
|
+
create(platform, platformUserId, conversationId, sessionKey, sessionFile, platformUserName) {
|
|
8
|
+
const token = {
|
|
9
|
+
token: randomBytes(16).toString("hex"),
|
|
10
|
+
platform,
|
|
11
|
+
platformUserId,
|
|
12
|
+
...(platformUserName ? { platformUserName } : {}),
|
|
13
|
+
conversationId,
|
|
14
|
+
sessionKey,
|
|
15
|
+
sessionFile,
|
|
16
|
+
expiresAt: Date.now() + TTL_MS,
|
|
17
|
+
};
|
|
18
|
+
this.tokens.set(token.token, token);
|
|
19
|
+
return token;
|
|
20
|
+
}
|
|
21
|
+
peek(rawToken) {
|
|
22
|
+
const entry = this.tokens.get(rawToken);
|
|
23
|
+
if (!entry || Date.now() > entry.expiresAt)
|
|
24
|
+
return undefined;
|
|
25
|
+
return entry;
|
|
26
|
+
}
|
|
27
|
+
purge() {
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
for (const [key, value] of this.tokens) {
|
|
30
|
+
if (now > value.expiresAt) {
|
|
31
|
+
this.tokens.delete(key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session-view/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAcrC,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnC,MAAM,OAAO,6BAA6B;IAA1C;QACU,WAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;IAsCvD,CAAC;IApCC,MAAM,CACJ,QAAsB,EACtB,cAAsB,EACtB,cAAsB,EACtB,UAAkB,EAClB,WAAmB,EACnB,gBAAyB;QAEzB,MAAM,KAAK,GAAqB;YAC9B,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YACtC,QAAQ;YACR,cAAc;YACd,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,cAAc;YACd,UAAU;YACV,WAAW;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM;SAC/B,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,QAAgB;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACvC,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["import { randomBytes } from \"crypto\";\nimport type { PlatformName } from \"../adapter.js\";\n\nexport interface SessionViewToken {\n token: string;\n platform: PlatformName;\n platformUserId: string;\n platformUserName?: string;\n conversationId: string;\n sessionKey: string;\n sessionFile: string;\n expiresAt: number;\n}\n\nconst TTL_MS = 24 * 60 * 60 * 1000;\n\nexport class InMemorySessionViewTokenStore {\n private tokens = new Map<string, SessionViewToken>();\n\n create(\n platform: PlatformName,\n platformUserId: string,\n conversationId: string,\n sessionKey: string,\n sessionFile: string,\n platformUserName?: string,\n ): SessionViewToken {\n const token: SessionViewToken = {\n token: randomBytes(16).toString(\"hex\"),\n platform,\n platformUserId,\n ...(platformUserName ? { platformUserName } : {}),\n conversationId,\n sessionKey,\n sessionFile,\n expiresAt: Date.now() + TTL_MS,\n };\n this.tokens.set(token.token, token);\n return token;\n }\n\n peek(rawToken: string): SessionViewToken | undefined {\n const entry = this.tokens.get(rawToken);\n if (!entry || Date.now() > entry.expiresAt) return undefined;\n return entry;\n }\n\n purge(): void {\n const now = Date.now();\n for (const [key, value] of this.tokens) {\n if (now > value.expiresAt) {\n this.tokens.delete(key);\n }\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface MikanSessionHeader {
|
|
2
|
+
type?: string;
|
|
3
|
+
version?: number;
|
|
4
|
+
id?: string;
|
|
5
|
+
timestamp?: string;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
parentSession?: string;
|
|
8
|
+
source?: {
|
|
9
|
+
kind?: string;
|
|
10
|
+
file?: string;
|
|
11
|
+
recentDays?: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function isPlatformHistorySession(sessionFile: string): boolean;
|
|
15
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/sessions/metadata.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAOrE","sourcesContent":["import { SessionManager } from \"@earendil-works/pi-coding-agent\";\n\nexport interface MikanSessionHeader {\n type?: string;\n version?: number;\n id?: string;\n timestamp?: string;\n cwd?: string;\n parentSession?: string;\n source?: {\n kind?: string;\n file?: string;\n recentDays?: number;\n };\n}\n\nexport function isPlatformHistorySession(sessionFile: string): boolean {\n try {\n const header = SessionManager.open(sessionFile).getHeader() as MikanSessionHeader | null;\n return header?.source?.kind === \"platform-history\";\n } catch {\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export function isPlatformHistorySession(sessionFile) {
|
|
3
|
+
try {
|
|
4
|
+
const header = SessionManager.open(sessionFile).getHeader();
|
|
5
|
+
return header?.source?.kind === "platform-history";
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/sessions/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAgBjE,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,SAAS,EAA+B,CAAC;QACzF,OAAO,MAAM,EAAE,MAAM,EAAE,IAAI,KAAK,kBAAkB,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC","sourcesContent":["import { SessionManager } from \"@earendil-works/pi-coding-agent\";\n\nexport interface MikanSessionHeader {\n type?: string;\n version?: number;\n id?: string;\n timestamp?: string;\n cwd?: string;\n parentSession?: string;\n source?: {\n kind?: string;\n file?: string;\n recentDays?: number;\n };\n}\n\nexport function isPlatformHistorySession(sessionFile: string): boolean {\n try {\n const header = SessionManager.open(sessionFile).getHeader() as MikanSessionHeader | null;\n return header?.source?.kind === \"platform-history\";\n } catch {\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ConversationKind } from "../adapter.js";
|
|
2
|
+
export type ChatPlatform = "slack" | "telegram" | "discord" | string;
|
|
3
|
+
export interface ResolveSessionKeyOptions {
|
|
4
|
+
conversationId: string;
|
|
5
|
+
conversationKind: ConversationKind;
|
|
6
|
+
messageId: string;
|
|
7
|
+
threadTs?: string;
|
|
8
|
+
persistentTopLevel?: boolean;
|
|
9
|
+
scopeDirectThreads?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function resolveChatSessionKey(options: ResolveSessionKeyOptions): string;
|
|
12
|
+
export declare function inferConversationKind(platform: ChatPlatform, conversationId: string): ConversationKind;
|
|
13
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/sessions/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAErE,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAgB/E;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,YAAY,EACtB,cAAc,EAAE,MAAM,GACrB,gBAAgB,CAclB","sourcesContent":["import type { ConversationKind } from \"../adapter.js\";\n\nexport type ChatPlatform = \"slack\" | \"telegram\" | \"discord\" | string;\n\nexport interface ResolveSessionKeyOptions {\n conversationId: string;\n conversationKind: ConversationKind;\n messageId: string;\n threadTs?: string;\n persistentTopLevel?: boolean;\n scopeDirectThreads?: boolean;\n}\n\nexport function resolveChatSessionKey(options: ResolveSessionKeyOptions): string {\n const {\n conversationId,\n conversationKind,\n messageId,\n persistentTopLevel,\n scopeDirectThreads,\n threadTs,\n } = options;\n if (conversationKind === \"direct\" && (!threadTs || !scopeDirectThreads)) {\n return conversationId;\n }\n if (!threadTs && persistentTopLevel) {\n return conversationId;\n }\n return `${conversationId}:${threadTs || messageId}`;\n}\n\nexport function inferConversationKind(\n platform: ChatPlatform,\n conversationId: string,\n): ConversationKind {\n if (platform === \"slack\") {\n return conversationId.startsWith(\"D\") ? \"direct\" : \"shared\";\n }\n\n if (platform === \"telegram\") {\n return conversationId.startsWith(\"-\") ? \"shared\" : \"direct\";\n }\n\n if (platform === \"discord\") {\n return conversationId.startsWith(\"DM\") ? \"direct\" : \"shared\";\n }\n\n return \"shared\";\n}\n"]}
|