@rexvane/piweb 0.3.10 → 0.3.12
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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +7 -6
- package/.next/build-manifest.json +6 -6
- package/.next/prerender-manifest.json +7 -7
- package/.next/react-loadable-manifest.json +7 -7
- package/.next/routes-manifest.json +6 -0
- package/.next/server/app/_global-error/page.js +2 -2
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/agent/[id]/events/route.js +2 -2
- package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/route.js +1 -1
- package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
- package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/new/route.js +1 -1
- package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js +1 -1
- package/.next/server/app/api/files/route.js +1 -1
- package/.next/server/app/api/git/route.js +2 -2
- package/.next/server/app/api/growth/route.js +1 -1
- package/.next/server/app/api/growth/route.js.nft.json +1 -1
- package/.next/server/app/api/health/route.js +1 -1
- package/.next/server/app/api/models/route.js +1 -1
- package/.next/server/app/api/models/route.js.nft.json +1 -1
- package/.next/server/app/api/pi-settings/route.js +1 -1
- package/.next/server/app/api/plugins/route.js +1 -1
- package/.next/server/app/api/plugins/route.js.nft.json +1 -1
- package/.next/server/app/api/prompts/route.js +1 -0
- package/.next/server/app/api/prompts/route.js.nft.json +1 -0
- package/.next/server/app/api/prompts/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/security/route.js +1 -1
- package/.next/server/app/api/security/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/route.js +1 -1
- package/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/route.js +2 -2
- package/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/update/route.js +2 -2
- package/.next/server/app/api/update/route.js.nft.json +1 -1
- package/.next/server/app/api/version/route.js +1 -1
- package/.next/server/app/api/web-auth/route.js +1 -1
- package/.next/server/app/api/workspaces/route.js +1 -1
- package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
- package/.next/server/app/icon.svg/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +4 -4
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +1 -1
- package/.next/server/app/login.rsc +3 -3
- package/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +7 -6
- package/.next/server/chunks/229.js +1 -0
- package/.next/server/chunks/496.js +1 -1
- package/.next/server/chunks/686.js +2 -2
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/2kt2UiWjv_viXpNlfjvBT/_buildManifest.js +1 -0
- package/.next/static/chunks/2155.2f27fe7098987699.js +1 -0
- package/.next/static/chunks/2608.ec8ff1f5767c9056.js +1 -0
- package/.next/static/chunks/2716.a9e808190a4e2424.js +1 -0
- package/.next/static/chunks/{794-d1a40dcf24d651d9.js → 3794-3679f1c05160977c.js} +1 -1
- package/.next/static/chunks/4127.dff5c3b33c6bfd1b.js +1 -0
- package/.next/static/chunks/4673.d3d0a7f2599080fb.js +1 -0
- package/.next/static/chunks/4686-5bbee099126af797.js +1 -0
- package/.next/static/chunks/4bd1b696-93bf506b236d6248.js +1 -0
- package/.next/static/chunks/app/_global-error/page-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/_not-found/page-2d40d1d7d916666a.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/tree/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/config/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/files/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/git/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/growth/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/health/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/models/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/pi-settings/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/plugins/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/prompts/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/security/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/export/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/skills/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/update/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/version/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/web-auth/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/api/workspaces/route-961c055baebb3872.js +1 -0
- package/.next/static/chunks/app/layout-50d06e2078d6ce76.js +1 -0
- package/.next/static/chunks/app/login/page-52ef4841cbd199a8.js +1 -0
- package/.next/static/chunks/app/page-00c8ebf40ec5eaca.js +1 -0
- package/.next/static/chunks/framework-c4e651fe89edfa91.js +1 -0
- package/.next/static/chunks/{main-a315d7c58b599962.js → main-6159b22a8cb0b7c5.js} +2 -2
- package/.next/static/chunks/main-app-e9b53f0e1c6591b2.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-961c055baebb3872.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-961c055baebb3872.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-a7e260f8cc2582d7.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-961c055baebb3872.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-961c055baebb3872.js +1 -0
- package/.next/static/chunks/webpack-05a9e85529a18b93.js +1 -0
- package/.next/static/css/b2d35abc828d4713.css +1 -0
- package/.next/types/app/api/prompts/route.ts +353 -0
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/package.json +1 -1
- package/src/app/api/prompts/route.ts +51 -0
- package/src/components/AppShell.tsx +42 -19
- package/src/components/ChatWindow.tsx +63 -36
- package/src/components/PromptPanel.tsx +257 -0
- package/src/components/SettingsPanel.tsx +183 -55
- package/src/hooks/usePiWeb.ts +13 -1
- package/src/i18n.tsx +80 -2
- package/src/lib/agent-manager.ts +47 -8
- package/src/lib/clipboard.ts +27 -0
- package/src/lib/command-validation.ts +1 -0
- package/src/lib/event-batcher.ts +62 -0
- package/src/lib/models-service.ts +430 -19
- package/src/lib/prompt-sources.ts +201 -0
- package/src/lib/provider-usage.ts +91 -0
- package/src/lib/session-retention.ts +119 -0
- package/src/lib/types.ts +1 -0
- package/.next/server/chunks/780.js +0 -1
- package/.next/static/CLy0QZWDpEExcItT1yudl/_buildManifest.js +0 -1
- package/.next/static/chunks/155.a3c40ae481da1358.js +0 -1
- package/.next/static/chunks/18.8b025ee3303c3dc7.js +0 -1
- package/.next/static/chunks/4bd1b696-92152b0f5947070d.js +0 -1
- package/.next/static/chunks/608.5b8aae42a9998ee7.js +0 -1
- package/.next/static/chunks/673.93445c8600bc1dd9.js +0 -1
- package/.next/static/chunks/686-97c833615d1565c5.js +0 -1
- package/.next/static/chunks/716.5266fe10b5578591.js +0 -1
- package/.next/static/chunks/app/_global-error/page-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/_not-found/page-9de30f6f614fce02.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/events/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/tree/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/agent/new/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/config/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/files/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/git/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/growth/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/health/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/models/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/pi-settings/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/plugins/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/security/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/export/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/sessions/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/skills/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/update/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/version/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/web-auth/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/api/workspaces/route-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/app/layout-eb62bcd99abe79f9.js +0 -1
- package/.next/static/chunks/app/login/page-d2308b48d013d1a6.js +0 -1
- package/.next/static/chunks/app/page-19e37fe240ae3e20.js +0 -1
- package/.next/static/chunks/framework-0f597d6e68ffafed.js +0 -1
- package/.next/static/chunks/main-app-1a92e20ec190a32b.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-7bb5c4afcbc1772b.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-1dac1b3ca8adb975.js +0 -1
- package/.next/static/chunks/webpack-eebc3d300017fa47.js +0 -1
- package/.next/static/css/080ec3dba8907e83.css +0 -1
- /package/.next/static/{CLy0QZWDpEExcItT1yudl → 2kt2UiWjv_viXpNlfjvBT}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prompt-sources:集中列出所有承载提示词的来源,供界面上"点开即看"。
|
|
3
|
+
*
|
|
4
|
+
* 覆盖:系统提示词覆盖文件(SYSTEM.md)、追加提示词(APPEND_SYSTEM.md)、项目记忆(AGENTS.md)、
|
|
5
|
+
* 技能提示词(SKILL.md)、提示模板(prompts/*.md)、以及来自扩展与 npm 包的同类资源;
|
|
6
|
+
* 热会话还额外给出"组装后真正发给模型的系统提示词"和每个工具的定义(名称/描述/参数 schema)。
|
|
7
|
+
*
|
|
8
|
+
* 只读:不改动任何提示词内容,也不影响发给模型的东西。
|
|
9
|
+
*/
|
|
10
|
+
import fs from "node:fs/promises";
|
|
11
|
+
import os from "node:os";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { getAgentDir, getResourceLoader, resourceLoaderReady } from "./pi";
|
|
14
|
+
import { resolveDiscoveredPath } from "./path-security";
|
|
15
|
+
|
|
16
|
+
/** 提示词来源类别:界面按这个分组 */
|
|
17
|
+
export type PromptSourceKind = "system" | "append" | "agents" | "skill" | "template" | "tool" | "assembled";
|
|
18
|
+
|
|
19
|
+
/** 来源出处:界面据此显示徽标(项目 / 个人 / 某个包 / 某个扩展) */
|
|
20
|
+
export interface PromptSourceOrigin {
|
|
21
|
+
scope: "project" | "agent" | "package" | "extension";
|
|
22
|
+
/** scope 为 package/extension 时的名字 */
|
|
23
|
+
name?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface PromptSource {
|
|
27
|
+
kind: PromptSourceKind;
|
|
28
|
+
/** 展示名:文件名(不含目录)或工具名 */
|
|
29
|
+
name: string;
|
|
30
|
+
/** 绝对路径;合成项(assembled)没有路径 */
|
|
31
|
+
path?: string;
|
|
32
|
+
origin: PromptSourceOrigin;
|
|
33
|
+
/** 文件字节数(有路径且能 stat 到时) */
|
|
34
|
+
bytes?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface PromptToolView {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
/** 参数 JSON schema,原样透出由界面格式化 */
|
|
41
|
+
parameters?: unknown;
|
|
42
|
+
promptGuidelines?: string[];
|
|
43
|
+
source: "builtin" | "extension";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface PromptSourcesResult {
|
|
47
|
+
sources: PromptSource[];
|
|
48
|
+
/** 热会话才有:组装后发给模型的完整系统提示词 */
|
|
49
|
+
assembledSystemPrompt?: string;
|
|
50
|
+
/** 热会话才有:每个工具的定义 */
|
|
51
|
+
tools?: PromptToolView[];
|
|
52
|
+
/** 冷会话(agent 未启动)时为 false,界面据此说明为什么缺少合成项 */
|
|
53
|
+
sessionReady: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** 只看这几个字段:够用且便于用假对象测试 */
|
|
57
|
+
export interface PromptSessionLike {
|
|
58
|
+
systemPrompt: string;
|
|
59
|
+
getAllTools(): Array<{
|
|
60
|
+
name: string;
|
|
61
|
+
description?: string;
|
|
62
|
+
parameters?: unknown;
|
|
63
|
+
promptGuidelines?: string[];
|
|
64
|
+
sourceInfo?: { source?: string; origin?: string; scope?: string };
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface SourceInfoLike {
|
|
69
|
+
source?: string;
|
|
70
|
+
scope?: string;
|
|
71
|
+
origin?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const normalize = (value: string) => value.replace(/\\/g, "/").toLowerCase();
|
|
75
|
+
|
|
76
|
+
/** 从 node_modules 路径里取包名(含 scope) */
|
|
77
|
+
function packageNameFromPath(filePath: string): string | undefined {
|
|
78
|
+
const parts = filePath.replace(/\\/g, "/").split("/");
|
|
79
|
+
const index = parts.lastIndexOf("node_modules");
|
|
80
|
+
if (index < 0 || index + 1 >= parts.length) return undefined;
|
|
81
|
+
const first = parts[index + 1];
|
|
82
|
+
return first.startsWith("@") ? `${first}/${parts[index + 2] ?? ""}`.replace(/\/$/, "") : first;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** 扩展目录名(<任意>/extensions/<name>/...) */
|
|
86
|
+
function extensionNameFromPath(filePath: string): string | undefined {
|
|
87
|
+
const parts = filePath.replace(/\\/g, "/").split("/");
|
|
88
|
+
const index = parts.lastIndexOf("extensions");
|
|
89
|
+
if (index < 0 || index + 1 >= parts.length) return undefined;
|
|
90
|
+
return parts[index + 1] || undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 判断一个提示词文件来自哪里。优先用 SDK 的 SourceInfo(有 scope/origin),
|
|
95
|
+
* 没有时按路径归类:工作区内 = project,个人目录 = agent,node_modules = 某个包,
|
|
96
|
+
* extensions 目录 = 某个扩展。
|
|
97
|
+
*/
|
|
98
|
+
export function classifyPromptOrigin(filePath: string, cwd: string, sourceInfo?: SourceInfoLike): PromptSourceOrigin {
|
|
99
|
+
const normalized = normalize(filePath);
|
|
100
|
+
const packageName = packageNameFromPath(filePath);
|
|
101
|
+
if (packageName || sourceInfo?.origin === "package") {
|
|
102
|
+
return { scope: "package", ...(packageName ?? sourceInfo?.source ? { name: packageName ?? sourceInfo?.source } : {}) };
|
|
103
|
+
}
|
|
104
|
+
const resolvedCwd = normalize(path.resolve(cwd));
|
|
105
|
+
if (normalized === resolvedCwd || normalized.startsWith(`${resolvedCwd}/`)) return { scope: "project" };
|
|
106
|
+
const agentDir = normalize(getAgentDir());
|
|
107
|
+
if (normalized.startsWith(`${agentDir}/`)) {
|
|
108
|
+
// 个人目录里的扩展也算扩展,便于区分"我自己装的那个扩展"
|
|
109
|
+
const extension = extensionNameFromPath(filePath);
|
|
110
|
+
return extension ? { scope: "extension", name: extension } : { scope: "agent" };
|
|
111
|
+
}
|
|
112
|
+
const extension = extensionNameFromPath(filePath);
|
|
113
|
+
if (extension) return { scope: "extension", name: extension };
|
|
114
|
+
if (sourceInfo?.scope === "project") return { scope: "project" };
|
|
115
|
+
return { scope: "agent" };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const KIND_ORDER: PromptSourceKind[] = ["system", "append", "agents", "skill", "template", "tool", "assembled"];
|
|
119
|
+
|
|
120
|
+
/** 纯函数:把各来源整理成界面要的列表(按类别、再按名字排序) */
|
|
121
|
+
export function buildPromptSources(entries: Array<Omit<PromptSource, "origin"> & { origin?: PromptSourceOrigin; cwd: string; sourceInfo?: SourceInfoLike }>): PromptSource[] {
|
|
122
|
+
return entries
|
|
123
|
+
.map(({ cwd, sourceInfo, origin, ...rest }) => ({
|
|
124
|
+
...rest,
|
|
125
|
+
origin: origin ?? classifyPromptOrigin(rest.path ?? "", cwd, sourceInfo),
|
|
126
|
+
}))
|
|
127
|
+
.sort((a, b) => {
|
|
128
|
+
const byKind = KIND_ORDER.indexOf(a.kind) - KIND_ORDER.indexOf(b.kind);
|
|
129
|
+
return byKind !== 0 ? byKind : a.name.localeCompare(b.name);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function fileSize(filePath: string | undefined): Promise<number | undefined> {
|
|
134
|
+
if (!filePath) return undefined;
|
|
135
|
+
try {
|
|
136
|
+
const stat = await fs.stat(filePath);
|
|
137
|
+
return stat.isFile() ? stat.size : undefined;
|
|
138
|
+
} catch {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** 列出当前工作区的全部提示词来源(冷会话也能列全文件类来源) */
|
|
144
|
+
export async function listPromptSources({
|
|
145
|
+
cwd,
|
|
146
|
+
session,
|
|
147
|
+
}: {
|
|
148
|
+
cwd: string;
|
|
149
|
+
session?: PromptSessionLike | null;
|
|
150
|
+
}): Promise<PromptSourcesResult> {
|
|
151
|
+
const resolvedCwd = path.resolve(cwd);
|
|
152
|
+
await resourceLoaderReady(resolvedCwd);
|
|
153
|
+
const loader = getResourceLoader(resolvedCwd);
|
|
154
|
+
|
|
155
|
+
const raw: Array<Omit<PromptSource, "origin"> & { cwd: string; sourceInfo?: SourceInfoLike; baseName?: string }> = [];
|
|
156
|
+
const push = (kind: PromptSourceKind, filePath: string | undefined, name: string | undefined, sourceInfo?: SourceInfoLike) => {
|
|
157
|
+
if (!filePath) return;
|
|
158
|
+
raw.push({ kind, path: filePath, name: name || path.basename(filePath), cwd: resolvedCwd, ...(sourceInfo ? { sourceInfo } : {}) });
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const systemSource = loader.getSystemPromptSource();
|
|
162
|
+
push("system", systemSource?.path, systemSource ? path.basename(systemSource.path) : undefined);
|
|
163
|
+
|
|
164
|
+
for (const source of loader.getAppendSystemPromptSources()) push("append", source.path, source ? path.basename(source.path) : undefined);
|
|
165
|
+
for (const file of loader.getAgentsFiles().agentsFiles) push("agents", file.path, path.basename(file.path));
|
|
166
|
+
for (const skill of loader.getSkills().skills) push("skill", skill.filePath, skill.name || path.basename(skill.filePath), skill.sourceInfo as SourceInfoLike | undefined);
|
|
167
|
+
for (const template of loader.getPrompts().prompts) push("template", template.filePath, template.name || path.basename(template.filePath), template.sourceInfo as SourceInfoLike | undefined);
|
|
168
|
+
|
|
169
|
+
const withSizes = await Promise.all(raw.map(async (entry) => ({ ...entry, bytes: await fileSize(entry.path) })));
|
|
170
|
+
const sources = buildPromptSources(withSizes);
|
|
171
|
+
|
|
172
|
+
const tools = session
|
|
173
|
+
? session.getAllTools().map((tool) => ({
|
|
174
|
+
name: tool.name,
|
|
175
|
+
...(tool.description === undefined ? {} : { description: tool.description }),
|
|
176
|
+
...(tool.parameters === undefined ? {} : { parameters: tool.parameters }),
|
|
177
|
+
...(tool.promptGuidelines?.length ? { promptGuidelines: tool.promptGuidelines } : {}),
|
|
178
|
+
source: tool.sourceInfo?.source === "builtin" ? ("builtin" as const) : ("extension" as const),
|
|
179
|
+
}))
|
|
180
|
+
: undefined;
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
sources,
|
|
184
|
+
...(session?.systemPrompt ? { assembledSystemPrompt: session.systemPrompt } : {}),
|
|
185
|
+
...(tools ? { tools } : {}),
|
|
186
|
+
sessionReady: Boolean(session),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** 读取单个来源的内容:只允许读取"本次发现列表里出现过"的路径(与技能读取同一套校验) */
|
|
191
|
+
export async function readPromptSource(filePath: string, cwd: string): Promise<string> {
|
|
192
|
+
const { sources } = await listPromptSources({ cwd });
|
|
193
|
+
const allowed = sources.map((source) => source.path).filter((value): value is string => typeof value === "string");
|
|
194
|
+
const authorized = await resolveDiscoveredPath(filePath, allowed);
|
|
195
|
+
return fs.readFile(authorized, "utf8");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** 给测试与诊断用:个人目录(提示词文件可能在 ~/.pi/agent 或 ~/.agents 下) */
|
|
199
|
+
export function promptHomeDirs(): string[] {
|
|
200
|
+
return [getAgentDir(), path.join(os.homedir(), ".agents")];
|
|
201
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 提供商用量的纯类型与纯函数(客户端安全)。
|
|
3
|
+
*
|
|
4
|
+
* 这份文件绝不能引入 SDK 或任何 Node 专用模块:设置面板(客户端组件)按值导入
|
|
5
|
+
* `quotaWindowKind` / `supportsUsageProbe`,一旦这里带上 SDK,webpack 会把
|
|
6
|
+
* `fs` / `child_process` 打进浏览器 bundle,生产构建直接失败(踩过)。
|
|
7
|
+
* 探测逻辑与缓存留在 models-service(服务端)。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** 一个用量窗口:窗口长度、剩余百分比、下次重置时刻(缺省表示服务端未给)。 */
|
|
11
|
+
export interface QuotaWindow {
|
|
12
|
+
/** 窗口时长;服务端不暴露周期时缺省,界面就只显示剩余与重置,不编造周期。 */
|
|
13
|
+
limitWindowSeconds?: number;
|
|
14
|
+
remainingPercent: number;
|
|
15
|
+
resetAt?: string;
|
|
16
|
+
/** 同类周期的窗口需要互相区分时使用(如 Claude 的 Opus 专用周限、Kimi 的月度代码额度)。 */
|
|
17
|
+
variant?: string;
|
|
18
|
+
/** 没有固定周期时的窗口名(如 opencode 的 rolling、Copilot 的额度类别),界面负责翻译。 */
|
|
19
|
+
name?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** 窗口制订阅额度(Codex / Claude 订阅):按窗口给出剩余百分比与重置时刻。 */
|
|
23
|
+
export interface QuotaUsage {
|
|
24
|
+
kind: "quota";
|
|
25
|
+
planType?: string;
|
|
26
|
+
/** 账户实际给出的全部窗口,按时长升序。 */
|
|
27
|
+
windows: QuotaWindow[];
|
|
28
|
+
probedAt: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** 余额明细项的语义,标签由界面翻译,服务端只给 key。 */
|
|
32
|
+
export type BalanceDetailKey = "granted" | "toppedUp" | "voucher" | "cash" | "used" | "limit";
|
|
33
|
+
|
|
34
|
+
export interface BalanceAmount {
|
|
35
|
+
amount: string;
|
|
36
|
+
currency?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 金额制余额(DeepSeek / OpenRouter / Moonshot):一个主余额加若干明细。 */
|
|
40
|
+
export interface BalanceUsage {
|
|
41
|
+
kind: "balance";
|
|
42
|
+
/** 主余额的语义;默认按「剩余额度」渲染。 */
|
|
43
|
+
primaryKey?: "remaining" | BalanceDetailKey;
|
|
44
|
+
primary?: BalanceAmount;
|
|
45
|
+
details: Array<{ key: BalanceDetailKey } & BalanceAmount>;
|
|
46
|
+
probedAt: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** xAI 订阅配额(响应头 x-ratelimit-*,需要一次可能计费的请求)。 */
|
|
50
|
+
export interface XaiUsage {
|
|
51
|
+
kind: "xai";
|
|
52
|
+
model: string;
|
|
53
|
+
requestLimit: number;
|
|
54
|
+
requestRemaining: number;
|
|
55
|
+
tokenLimit: number;
|
|
56
|
+
tokenRemaining: number;
|
|
57
|
+
probedAt: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type ProviderUsage = XaiUsage | QuotaUsage | BalanceUsage;
|
|
61
|
+
|
|
62
|
+
export const WEEKLY_WINDOW_SECONDS = 7 * 24 * 60 * 60;
|
|
63
|
+
export const MONTHLY_WINDOW_SECONDS = 30 * 24 * 60 * 60;
|
|
64
|
+
|
|
65
|
+
/** 窗口时长归类,供界面选标签:7 天即常说的「周限」,30 天为月限,更短的按小时/天。 */
|
|
66
|
+
export type QuotaWindowKind = "weekly" | "monthly" | "hours" | "days";
|
|
67
|
+
|
|
68
|
+
export function quotaWindowKind(seconds: number): QuotaWindowKind {
|
|
69
|
+
if (seconds === WEEKLY_WINDOW_SECONDS) return "weekly";
|
|
70
|
+
if (seconds === MONTHLY_WINDOW_SECONDS) return "monthly";
|
|
71
|
+
return seconds < 24 * 60 * 60 ? "hours" : "days";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** 提供只读用量端点的提供商(models-service 的 usageProbeFor 按同一份名单分派)。 */
|
|
75
|
+
export const USAGE_PROBE_PROVIDER_IDS = [
|
|
76
|
+
"xai",
|
|
77
|
+
"openai-codex",
|
|
78
|
+
"anthropic",
|
|
79
|
+
"deepseek",
|
|
80
|
+
"openrouter",
|
|
81
|
+
"moonshotai",
|
|
82
|
+
"moonshotai-cn",
|
|
83
|
+
"kimi-coding",
|
|
84
|
+
"github-copilot",
|
|
85
|
+
"vercel-ai-gateway",
|
|
86
|
+
"opencode-go",
|
|
87
|
+
] as const;
|
|
88
|
+
|
|
89
|
+
export function supportsUsageProbe(providerId: string): boolean {
|
|
90
|
+
return (USAGE_PROBE_PROVIDER_IDS as readonly string[]).includes(providerId);
|
|
91
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 归档会话保留期:归档后超过 N 天没有活动(以会话文件 mtime 为准)就自动删除。
|
|
3
|
+
*
|
|
4
|
+
* 只会碰「在归档列表里」的会话:没归档的会话即使很久没动也不会被动。
|
|
5
|
+
* 正在被本进程管理的会话(打开中/运行中)一律跳过——交给它自己空闲回收。
|
|
6
|
+
* 每一次删除都会打印日志,便于事后核对。
|
|
7
|
+
*/
|
|
8
|
+
import fs from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { forgetSession, getWorkspaceRegistry } from "./workspace-store";
|
|
11
|
+
|
|
12
|
+
/** 归档会话多久没有活动就删除(天) */
|
|
13
|
+
export const ARCHIVED_RETENTION_DAYS = 30;
|
|
14
|
+
/** 两次清理之间的间隔 */
|
|
15
|
+
export const SWEEP_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
16
|
+
|
|
17
|
+
export interface RetentionReport {
|
|
18
|
+
scanned: number;
|
|
19
|
+
deleted: { path: string; idleDays: number }[];
|
|
20
|
+
/** 文件已不在磁盘上:只清掉归档列表里的记录 */
|
|
21
|
+
missing: string[];
|
|
22
|
+
/** 正在使用(打开中/运行中)而跳过 */
|
|
23
|
+
skippedActive: string[];
|
|
24
|
+
kept: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 扫一遍归档列表并删除超期会话。
|
|
29
|
+
* @param options.isActive 判断某会话是否正在使用(由调用方注入,避免与 agent-manager 相互依赖)
|
|
30
|
+
*/
|
|
31
|
+
export async function sweepArchivedSessions({
|
|
32
|
+
now = Date.now(),
|
|
33
|
+
retentionDays = ARCHIVED_RETENTION_DAYS,
|
|
34
|
+
isActive = () => false,
|
|
35
|
+
log = console.log,
|
|
36
|
+
dryRun = false,
|
|
37
|
+
}: {
|
|
38
|
+
now?: number;
|
|
39
|
+
retentionDays?: number;
|
|
40
|
+
isActive?: (sessionPath: string) => boolean;
|
|
41
|
+
log?: (message: string) => void;
|
|
42
|
+
dryRun?: boolean;
|
|
43
|
+
} = {}): Promise<RetentionReport> {
|
|
44
|
+
const report: RetentionReport = { scanned: 0, deleted: [], missing: [], skippedActive: [], kept: 0 };
|
|
45
|
+
if (!Number.isFinite(retentionDays) || retentionDays <= 0) return report;
|
|
46
|
+
const cutoff = now - retentionDays * 24 * 60 * 60 * 1000;
|
|
47
|
+
const { archivedSessions } = await getWorkspaceRegistry();
|
|
48
|
+
|
|
49
|
+
for (const sessionPath of archivedSessions) {
|
|
50
|
+
report.scanned += 1;
|
|
51
|
+
const target = path.resolve(sessionPath);
|
|
52
|
+
if (isActive(target)) {
|
|
53
|
+
report.skippedActive.push(target);
|
|
54
|
+
report.kept += 1;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
let mtimeMs: number;
|
|
58
|
+
try {
|
|
59
|
+
const stat = await fs.stat(target);
|
|
60
|
+
if (!stat.isFile()) throw Object.assign(new Error("not a file"), { code: "ENOENT" });
|
|
61
|
+
mtimeMs = stat.mtimeMs;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
|
64
|
+
// 文件没了(手动删过等):只清理归档记录
|
|
65
|
+
report.missing.push(target);
|
|
66
|
+
if (!dryRun) await forgetSession(target);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (mtimeMs > cutoff) {
|
|
70
|
+
report.kept += 1;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const idleDays = Math.floor((now - mtimeMs) / (24 * 60 * 60 * 1000));
|
|
74
|
+
report.deleted.push({ path: target, idleDays });
|
|
75
|
+
if (dryRun) continue;
|
|
76
|
+
// 运行时再取:session-reader → agent-manager → 本模块 构成环,静态导入会在初始化期踩空
|
|
77
|
+
const { deleteSession } = await import("./session-reader");
|
|
78
|
+
await deleteSession(target);
|
|
79
|
+
await forgetSession(target);
|
|
80
|
+
log(`[piweb] 归档会话已超过 ${retentionDays} 天没有活动(${idleDays} 天),已删除:${target}`);
|
|
81
|
+
}
|
|
82
|
+
return report;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let started = false;
|
|
86
|
+
let lastSweep = 0;
|
|
87
|
+
|
|
88
|
+
/** 起一个后台清理器:启动后不久跑一次,之后按间隔重复(幂等,重复调用无副作用) */
|
|
89
|
+
export function startArchivedSessionRetention({
|
|
90
|
+
intervalMs = SWEEP_INTERVAL_MS,
|
|
91
|
+
delayMs = 5_000,
|
|
92
|
+
log = console.log,
|
|
93
|
+
isActive,
|
|
94
|
+
}: { intervalMs?: number; delayMs?: number; log?: (message: string) => void; isActive?: (sessionPath: string) => boolean } = {}): void {
|
|
95
|
+
if (started) return;
|
|
96
|
+
started = true;
|
|
97
|
+
const run = async () => {
|
|
98
|
+
lastSweep = Date.now();
|
|
99
|
+
try {
|
|
100
|
+
const report = await sweepArchivedSessions({ log, isActive });
|
|
101
|
+
if (report.deleted.length || report.missing.length) {
|
|
102
|
+
log(`[piweb] 归档清理:删除 ${report.deleted.length} 个,清理失效记录 ${report.missing.length} 个,保留 ${report.kept} 个`);
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
log(`[piweb] 归档清理失败:${error instanceof Error ? error.message : error}`);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const timer = setTimeout(() => {
|
|
109
|
+
void run();
|
|
110
|
+
const repeat = setInterval(() => void run(), intervalMs);
|
|
111
|
+
repeat.unref?.();
|
|
112
|
+
}, delayMs);
|
|
113
|
+
timer.unref?.();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** 距上次清理是否已经超过一个间隔(供复用现有定时器时判断) */
|
|
117
|
+
export function shouldSweep(now = Date.now(), intervalMs = SWEEP_INTERVAL_MS): boolean {
|
|
118
|
+
return now - lastSweep >= intervalMs;
|
|
119
|
+
}
|
package/src/lib/types.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";exports.id=780,exports.ids=[780],exports.modules={6896:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{Iz:()=>B,JZ:()=>A,PY:()=>x,Tp:()=>y,XG:()=>D,X_:()=>G,qh:()=>E,r7:()=>C,vQ:()=>z});var e=c(51455),f=c.n(e),g=c(48161),h=c.n(g),i=c(76760),j=c.n(i),k=c(92584),l=c(31421),m=c(46193),n=c(87982),o=c(77598),p=c(49904),q=a([n]);function r(){return j().join((0,n.$M)(),"web-workspaces.json")}async function s(a=r()){try{let b=JSON.parse(await f().readFile(a,"utf8"));if(!b||"object"!=typeof b||Array.isArray(b))throw Error("invalid workspace registry");let c=Object.fromEntries(Object.entries("object"==typeof b.aliases&&null!==b.aliases?b.aliases:{}).filter(a=>"string"==typeof a[1]));return{workspaces:Array.isArray(b.workspaces)?b.workspaces.filter(a=>"string"==typeof a):[],aliases:c,archivedSessions:Array.isArray(b.archivedSessions)?b.archivedSessions.filter(a=>"string"==typeof a):[],removedWorkspaces:Array.isArray(b.removedWorkspaces)?b.removedWorkspaces.filter(a=>"string"==typeof a):[]}}catch(a){if("ENOENT"!==a.code)throw a}return{workspaces:[],aliases:{},archivedSessions:[],removedWorkspaces:[]}}function t(a){let b=j().resolve(a);return"win32"===process.platform?b.toLowerCase():b}async function u(a,b){await f().mkdir(j().dirname(b),{recursive:!0});let c=`${b}.${(0,o.randomUUID)()}.tmp`;try{await f().writeFile(c,JSON.stringify(a,null,2),{encoding:"utf8",flag:"wx",mode:384}),await f().rename(c,b)}finally{await f().unlink(c).catch(()=>void 0)}}async function v(){let a=r();return(0,p.Ax)(a,()=>s(a))}async function w(a){let b=r();return(0,p.Ax)(b,()=>(0,p._i)(b,async()=>a(await s(b),b)))}async function x(){return(await v()).removedWorkspaces??[]}async function y(a,b){let c=t(j().resolve(a));return w(async(a,d)=>{for(let b of(a.aliases||(a.aliases={}),Object.keys(a.aliases)))b!==c&&t(b)===c&&delete a.aliases[b];return b.trim()?a.aliases[c]=b.trim():delete a.aliases[c],await u(a,d),a.aliases})}async function z(){let a=await v();return{workspaces:a.workspaces,aliases:a.aliases??{},archivedSessions:a.archivedSessions??[],removedWorkspaces:a.removedWorkspaces??[]}}async function A(a){let b=j().resolve(a),c=t(b);return w(async(a,d)=>(a.archivedSessions||(a.archivedSessions=[]),a.archivedSessions.some(a=>t(a)===c)||(a.archivedSessions.push(b),await u(a,d)),a.archivedSessions))}async function B(a){let b=j().resolve(a),c=t(b);return w(async(a,b)=>{let d=a.archivedSessions??[],e=d.filter(a=>t(a)!==c);return e.length!==d.length&&(a.archivedSessions=e,await u(a,b)),e})}async function C(a){let b=j().resolve(a),c=t(b);return w(async(a,d)=>{let e=!1;if(a.workspaces.some(a=>t(a)===c)||(a.workspaces.push(b),e=!0),a.removedWorkspaces){let b=a.removedWorkspaces.filter(a=>t(a)!==c);e||=b.length!==a.removedWorkspaces.length,a.removedWorkspaces=b}return e&&await u(a,d),{workspaces:a.workspaces,removedWorkspaces:a.removedWorkspaces??[]}})}async function D(a){return w(async(b,c)=>{let d=!1,e=new Set((b.removedWorkspaces??[]).map(t)),f=new Set(b.workspaces.map(t));for(let c of a){if(!c||"string"!=typeof c)continue;let a=j().resolve(c),g=t(a);e.has(g)||f.has(g)||(b.workspaces.push(a),f.add(g),d=!0)}return d&&await u(b,c),b.workspaces})}async function E(a){let b=j().resolve(a),c=t(b);return w(async(a,d)=>{if(a.workspaces=a.workspaces.filter(a=>t(a)!==c),a.removedWorkspaces||(a.removedWorkspaces=[]),a.removedWorkspaces.some(a=>t(a)===c)||a.removedWorkspaces.push(b),a.aliases)for(let b of Object.keys(a.aliases))t(b)===c&&delete a.aliases[b];return await u(a,d),{workspaces:a.workspaces,removedWorkspaces:a.removedWorkspaces,aliases:a.aliases??{}}})}n=(q.then?(await q)():q)[0];let H=!1;function F(a,b={}){let{timeoutMs:c=3e5,windowsHide:d=!1}=b;return new Promise((b,e)=>{let f,g=(0,l.spawn)(a[0],a.slice(1),{stdio:["ignore","pipe","pipe"],windowsHide:d}),h=new m.StringDecoder("utf8"),i="",j="",k=!1;g.stdout.on("data",a=>{i+=h.write(a)}),g.stderr.on("data",a=>{j=(j+a.toString("utf8")).slice(-1e3)});let n=!1,o=a=>{n||(n=!0,clearTimeout(f),k||(k=!0,i+=h.end()),a?e(a):b(i.trim()))};g.on("error",a=>o(a)),g.on("close",a=>o(0===a?void 0:Error(j||`folder picker exited with code ${a}`))),f=setTimeout(()=>{try{g.kill()}catch{}o(Error("folder picker timed out"))},c)})}async function G(){if(H)return{path:null,canceled:!0};H=!0;try{if("win32"===process.platform){let a=j().join(k.V,"scripts","pick-folder.ps1"),b=await F(["powershell.exe","-NoProfile","-STA","-ExecutionPolicy","Bypass","-File",a,"选择工作区文件夹"],{windowsHide:!0});return b?{path:b,canceled:!1}:{path:null,canceled:!0}}if("darwin"===process.platform){let a=await F(["osascript","-e",'POSIX path of (choose folder with prompt "选择工作区文件夹")']),b=function(a){let b=a.trim();if((b=b.replace(/^alias\s+/i,"").replace(/^"(.*)"$/s,"$1")).startsWith("/"))return b.replace(/\\(.)/g,"$1");if(/^[A-Za-z][A-Za-z0-9 ]*:(.+)$/.test(b)){let a=b.slice(b.indexOf(":")+1);return`/${a.split(":").filter(Boolean).join("/")}`}return b}(a);return b?{path:b,canceled:!1}:{path:null,canceled:!0}}for(let a of[["zenity","--file-selection","--directory","--title=选择工作区文件夹"],["kdialog","--getexistingdirectory",`${h().homedir()}`,"--title","选择工作区文件夹"]])try{let b=await F(a);return b?{path:b,canceled:!1}:{path:null,canceled:!0}}catch(a){if(a instanceof Error&&/ENOENT|not found|not recognized/i.test(a.message))continue;if(/exited with code (1|5)$/.test(a instanceof Error?a.message:String(a)))return{path:null,canceled:!0};throw a}throw Error("no folder picker available: install zenity or kdialog, or type the path manually")}finally{H=!1}}d()}catch(a){d(a)}})},66229:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{GW:()=>r,ME:()=>s,lx:()=>t});var e=c(73024),f=c(51455),g=c.n(f),h=c(76760),i=c.n(h),j=c(80481),k=c(75430),l=c(28686),m=c(87982),n=c(62433),o=a([k,l,m,n]);async function p(a,b){try{var c;let d,f,g=null,h=0,i="";for await(let b of(0,j.createInterface)({input:(0,e.createReadStream)(a,{encoding:"utf8"}),crlfDelay:1/0})){let a;if(!b.trim())continue;try{a=JSON.parse(b)}catch{continue}if(!g){if(a?.type!=="session")return null;g=a;continue}if(a?.type==="session_info"&&(d="string"==typeof a.name&&a.name.trim()?a.name.trim():void 0),a?.type!=="message")continue;h+=1;let c=a.message;if(!c||"string"!=typeof c.role||!("content"in c)||"user"!==c.role&&"assistant"!==c.role)continue;let e="number"==typeof c.timestamp?c.timestamp:new Date(a.timestamp).getTime();if(Number.isFinite(e)&&(f=Math.max(f??0,e)),!i&&"user"===c.role){let a=c.content;i="string"==typeof a?a:Array.isArray(a)?a.filter(a=>a?.type==="text").map(a=>a.text).join(" "):""}}if(!g)return null;let k="string"==typeof g.timestamp?new Date(g.timestamp).getTime():NaN,l=f&&f>0?new Date(f):Number.isNaN(k)?b.mtime:new Date(k);return{path:(c={path:a,name:d,cwd:"string"==typeof g.cwd?g.cwd:"",created:new Date(String(g.timestamp)),modified:l,messageCount:h,firstMessage:i||"(no messages)"}).path,name:c.name,cwd:c.cwd,created:c.created.toISOString(),modified:c.modified.toISOString(),messageCount:c.messageCount,firstMessage:c.firstMessage}}catch{return null}}[k,l,m,n]=o.then?(await o)():o;let u=new Map,v=null;async function q(){let a=i().join((0,m.$M)(),"sessions"),b=[],c=[];try{c=await g().readdir(a,{withFileTypes:!0})}catch{return[]}await Promise.all(c.filter(a=>a.isDirectory()||a.isSymbolicLink()).map(async c=>{try{for(let d of(await g().readdir(i().join(a,c.name))))d.endsWith(".jsonl")&&b.push(i().join(a,c.name,d))}catch{}}));let d=new Set,e=[];for(let a=0;a<b.length;a+=16)await Promise.all(b.slice(a,a+16).map(async a=>{d.add(a);let b=await g().stat(a).catch(()=>null);if(!b?.isFile())return;let c=u.get(a);if(c&&c.mtimeMs===b.mtimeMs&&c.size===b.size){c.summary&&e.push(c.summary);return}let f=await p(a,b);u.set(a,{mtimeMs:b.mtimeMs,size:b.size,summary:f}),f&&e.push(f)}));for(let a of u.keys())d.has(a)||u.delete(a);return e}let w=null;async function r(a){let b;if(w&&Date.now()-w.at<1200?b=w.list:(v??=q().finally(()=>{v=null}),b=await v,w={at:Date.now(),list:b}),a?.trim()){let c=a.trim().toLowerCase();b=b.filter(a=>a.name?.toLowerCase().includes(c)||a.firstMessage.toLowerCase().includes(c)||a.cwd.toLowerCase().includes(c))}return b.sort((a,b)=>b.modified.localeCompare(a.modified)||a.path.localeCompare(b.path)),b}async function s(a){let b=i().join((0,m.$M)(),"sessions"),c=await g().realpath(b).catch(()=>i().resolve(b)),d=i().resolve(a);if(".jsonl"!==i().extname(d).toLowerCase()||!(0,n.CN)(i().resolve(b),d))throw new n.BV("session path is outside the Pi session store");let e=await g().realpath(d).catch(a=>{if("ENOENT"===a.code)return d;throw a});if(e!==d&&!(0,n.CN)(c,e))throw new n.BV("session path escapes the Pi session store");try{await g().unlink(d)}catch(a){if("ENOENT"!==a.code)throw a}}async function t(a){let b=k.SessionManager.open(a),c=[];try{c=b.buildContextEntries().filter(a=>"message"===a.type&&a.message).map(a=>(0,l.H$)(a.message,a.id))}catch{c=[]}let d="";try{d=b.getSessionName?.()??""}catch{d=""}return{cwd:b.getCwd(),name:d,messages:c}}d()}catch(a){d(a)}})},92584:(a,b,c)=>{c.d(b,{V:()=>e});var d=c(76760);let e=c.n(d)().resolve(process.env.PI_WEB_ROOT??process.cwd())}};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:21,errorRate:1e-4,numBits:403,numHashes:14,bitArray:[0,1,1,0,1,1,0,0,0,0,0,0,1,1,1,0,1,1,0,0,0,0,1,1,0,0,0,1,0,1,1,1,1,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,1,1,0,1,1,0,0,0,0,1,0,1,1,0,1,1,1,1,1,0,0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,0,1,1,1,0,1,0,1,0,1,0,1,1,0,1,1,0,0,1,1,0,0,0,0,1,0,1,0,0,1,1,1,0,0,1,1,0,1,1,1,0,0,1,0,1,0,0,1,1,1,0,1,0,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,1,0,0,1,1,0,0,0,1,0,1,0,0,1,0,1,1,0,1,1,1,0,0,1,1,1,0,0,1,1,0,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,1,1,1,0,0,1,1,0,1,0,1,0,1,1,0,0,1,1,0,1,1,1,1,1,1,0,0,0,0,1,1,0,1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,1,1,0,1,0,0,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,0,0,0,1,1,1,1,0,0,0]},__routerFilterDynamic:{numItems:2,errorRate:1e-4,numBits:39,numHashes:14,bitArray:[1,0,1,0,0,0,0,0,1,1,0,1,1,1,1,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,1,1,0,0]},sortedPages:["/_app"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[155],{2155:(e,o,r)=>{r.d(o,{Q:()=>a});var l=r(5155),t=r(2115),s=r(9992),d=r(1859),n=r(2253),i=r(1135);let a=(0,t.memo)(function({tree:e,expanded:o,fresh:r,filter:s="",onlyChanges:n=!1,selectedPath:a,onToggleDir:f,onExpandLazy:p,onOpenFile:m,onReference:u,onOpenEditor:g,revealPath:h,revealKey:v,emptyText:b}){let{t:k}=(0,d.s)(),y=(0,t.useMemo)(()=>(0,i.dG)(e,o,{onlyChanges:n,filter:s}),[e,o,n,s]),j=(0,t.useRef)(null),[x,w]=(0,t.useState)({top:0,height:600}),[z,_]=(0,t.useState)(null);(0,t.useEffect)(()=>{let e=j.current;if(!e)return;let o=()=>w({top:e.scrollTop,height:e.clientHeight});o(),e.addEventListener("scroll",o,{passive:!0});let r=new ResizeObserver(o);return r.observe(e),()=>{e.removeEventListener("scroll",o),r.disconnect()}},[]),(0,t.useEffect)(()=>{if(!h)return;let e=y.findIndex(e=>e.node.path===h);if(e<0)return;_((0,i.SG)(y[e].node));let o=j.current;if(!o)return;let r=22*e;(r<o.scrollTop||r+22>o.scrollTop+o.clientHeight)&&o.scrollTo({top:Math.max(0,r-o.clientHeight/2)})},[h,v,y]);let q=(0,t.useCallback)(e=>{let o=e.node;"dir"===o.kind?(o.lazy&&!e.expanded&&p&&p(o.path),f(o.path)):m(o)},[p,f,m]),N=Math.max(0,Math.floor(x.top/22)-12),D=Math.min(y.length,Math.ceil((x.top+x.height)/22)+12),M=y.slice(N,D);return(0,l.jsx)("div",{ref:j,className:"pw-tree min-h-0 flex-1 overflow-auto outline-none",tabIndex:0,role:"tree",onKeyDown:e=>{if(!y.length)return;let o=Math.max(0,y.findIndex(e=>(0,i.SG)(e.node)===z)),r=y[o],l=e=>{let o=y[Math.max(0,Math.min(y.length-1,e))];_((0,i.SG)(o.node));let r=j.current;if(!r)return;let l=22*Math.max(0,Math.min(y.length-1,e));l<r.scrollTop?r.scrollTop=l:l+22>r.scrollTop+r.clientHeight&&(r.scrollTop=l+22-r.clientHeight)};if("ArrowDown"===e.key)e.preventDefault(),l(null===z?0:o+1);else if("ArrowUp"===e.key)e.preventDefault(),l(o-1);else if("ArrowRight"===e.key&&r)e.preventDefault(),"dir"!==r.node.kind||r.expanded?l(o+1):q(r);else if("ArrowLeft"===e.key&&r)if(e.preventDefault(),"dir"===r.node.kind&&r.expanded)f(r.node.path);else{let e=r.node.path.includes("/")?r.node.path.slice(0,r.node.path.lastIndexOf("/")):"",o=y.findIndex(o=>"dir"===o.node.kind&&o.node.path===e);o>=0&&l(o)}else("Enter"===e.key||" "===e.key)&&r?(e.preventDefault(),q(r)):"Home"===e.key?(e.preventDefault(),l(0)):"End"===e.key&&(e.preventDefault(),l(y.length-1))},onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||_(null)},children:0===y.length?(0,l.jsx)("div",{style:{fontSize:12.5,color:"var(--dsw-label-caption)",padding:"10px 12px"},children:b??k.filesEmpty}):(0,l.jsx)("div",{style:{height:22*y.length,position:"relative"},children:M.map((e,o)=>(0,l.jsx)(c,{row:e,top:(N+o)*22,fresh:"file"===e.node.kind&&!!r?.has(e.node.path),selected:"file"===e.node.kind&&a===e.node.path,focused:z===(0,i.SG)(e.node),onActivate:q,onFocusRow:_,onReference:u,onOpenEditor:g,pendingLabel:k.growthPending,lazyLabel:k.growthLazyDir,deletedLabel:k.growthStatD,referenceLabel:k.fileReference,editorLabel:k.fileOpenEditor},(0,i.SG)(e.node)))})})}),c=(0,t.memo)(function({row:e,top:o,fresh:r,selected:t,focused:d,onActivate:a,onFocusRow:c,onReference:f,onOpenEditor:p,pendingLabel:m,lazyLabel:u,deletedLabel:g,referenceLabel:h,editorLabel:v}){var b;let{node:k,depth:y,expanded:j}=e,x="dir"===k.kind,w="A"===(b=k.status)?"var(--dsw-success)":"M"===b?"var(--dsw-warn)":"D"===b?"var(--dsw-danger)":"R"===b?"var(--dsw-accent)":void 0,z=x?function(e){let o=e.counts;if(!o)return null;let r=o.added+o.modified+o.deleted+o.renamed;if(o.pending&&!r)return{text:"…",color:"var(--dsw-label-caption)"};if(!r)return null;let l=o.deleted>=o.added&&o.deleted>=o.modified?"var(--dsw-danger)":o.added>=o.modified?"var(--dsw-success)":"var(--dsw-warn)";return{text:String(r),color:l}}(k):null,_=!!(k.lazy&&!k.counts),q=[x?`${k.path}/`:k.path,"D"===k.status?g:"","R"===k.status&&k.from?`← ${k.from}`:"",k.pending?m:"",_?u:""].filter(Boolean).join("\n");return(0,l.jsxs)("div",{className:"pw-tree-row group/row",role:"treeitem","aria-expanded":x?j:void 0,"aria-selected":t,"data-selected":t||void 0,"data-focused":d||void 0,"data-fresh":r?k.status??"M":void 0,"data-status":k.status,"data-pending":k.pending||void 0,"data-lazy":_?"1":void 0,style:{top:o,paddingLeft:12*y+6},title:q,onClick:()=>{c((0,i.SG)(k)),a(e)},children:[(0,l.jsx)("span",{className:"pw-tree-chevron","aria-hidden":!0,children:x&&(0,l.jsx)(s.Yq,{size:10,style:{transform:j?"rotate(90deg)":void 0,transition:"transform var(--ds-duration-fast)"}})}),(0,l.jsx)("img",{className:"pw-tree-icon","data-kind":k.kind,src:x?(0,n.Q)(k.name,j):(0,n.s)(k.name),alt:"",draggable:!1}),(0,l.jsxs)("span",{className:"pw-tree-name",style:{color:w,textDecoration:"D"===k.status?"line-through":void 0},children:[k.name,x?"/":"","D"===k.status&&(0,l.jsxs)("span",{className:"pw-tree-from",children:["(",g,")"]}),"R"===k.status&&k.from&&(0,l.jsxs)("span",{className:"pw-tree-from",children:["← ",k.from.split("/").pop()]})]}),k.pending&&(0,l.jsx)("span",{className:"pw-tree-pulse","aria-label":m}),!x&&(f||p)&&!k.lazy&&(0,l.jsxs)("span",{className:"pw-tree-actions",children:[f&&(0,l.jsx)("button",{type:"button",className:"icon-btn",style:{width:18,height:18,borderRadius:5},title:h,onClick:e=>{e.stopPropagation(),f(k.path)},children:(0,l.jsx)(s.PT,{size:11})}),p&&(0,l.jsx)("button",{type:"button",className:"icon-btn",style:{width:18,height:18,borderRadius:5},title:v,onClick:e=>{e.stopPropagation(),p(k.path)},children:(0,l.jsx)(s.lx,{size:11})})]}),!x&&k.status&&(k.add||k.del)?(0,l.jsxs)("span",{className:"pw-tree-stat",children:[k.add?(0,l.jsxs)("span",{style:{color:"var(--dsw-success)"},children:["+",k.add]}):null,k.del?(0,l.jsxs)("span",{style:{color:"var(--dsw-danger)"},children:["−",k.del]}):null]}):null,!x&&k.status&&(0,l.jsx)("span",{className:"pw-tree-badge",style:{color:w,borderColor:w},children:k.status}),z&&(0,l.jsx)("span",{className:"pw-tree-badge",style:{color:z.color,borderColor:z.color},children:z.text})]})})},2253:(e,o,r)=>{r.d(o,{s:()=>s,Q:()=>d});let l=JSON.parse('{"defaults":{"file":"file","folder":"folder","folderOpen":"folder-open"},"ext":{"7z":"zip","adoc":"asciidoc","ai":"adobe-illustrator","asc":"key","asm":"assembly","astro":"astro","avi":"video","avif":"image","bash":"console","bat":"console","bib":"bibliography","bicep":"bicep","blend":"blender","bmp":"image","bz2":"zip","c":"c","cc":"cpp","cer":"certificate","cfg":"settings","cjs":"javascript","clj":"clojure","cmake":"cmake","cmd":"console","conf":"settings","cpp":"cpp","crt":"certificate","cs":"csharp","cshtml":"razor","css":"css","csv":"table","d.ts":"typescript-def","dart":"dart","db":"database","diff":"diff","doc":"word","docx":"word","ejs":"ejs","elm":"elm","env":"tune","eot":"font","erl":"erlang","ex":"elixir","exs":"elixir","fbx":"3d","fish":"console","flac":"audio","fs":"fsharp","gif":"image","glsl":"shader","gltf":"3d","go":"go","gpg":"key","gql":"graphql","gradle":"gradle","graphql":"graphql","groovy":"groovy","gz":"zip","h":"h","hbs":"handlebars","hcl":"hcl","hlsl":"shader","hpp":"hpp","hs":"haskell","htm":"html","html":"html","ico":"image","ics":"email","ini":"settings","ipynb":"jupyter","java":"java","jl":"julia","jpeg":"image","jpg":"image","js":"javascript","json":"json","json5":"json","jsonc":"json","jsonl":"json","jsx":"react","key":"key","kt":"kotlin","kts":"kotlin","less":"less","liquid":"liquid","lock":"lock","log":"log","lua":"lua","m":"objective-c","markdown":"markdown","md":"markdown","mdx":"mdx","mjs":"javascript","mk":"makefile","mkv":"video","ml":"ocaml","mm":"objective-cpp","mo":"i18n","mov":"video","mp3":"audio","mp4":"video","nim":"nim","nix":"nix","obj":"3d","ogg":"video","otf":"font","owl":"xml","patch":"git","pdf":"pdf","pem":"key","php":"php","pl":"prolog","plist":"xml","png":"image","po":"i18n","pot":"i18n","ppt":"powerpoint","pptx":"powerpoint","prisma":"prisma","properties":"settings","proto":"proto","ps1":"powershell","psd":"adobe-photoshop","psm1":"powershell","pub":"key","pug":"pug","py":"python","pyc":"python-misc","pyi":"python","r":"r","rar":"zip","razor":"razor","rb":"ruby","rdf":"xml","rs":"rust","rst":"markdown","rtf":"word","s":"assembly","sass":"sass","scala":"scala","scss":"sass","sh":"console","shader":"shader","sig":"sml","sol":"solidity","spec.js":"test-js","spec.ts":"test-ts","sql":"database","sqlite":"database","sqlite3":"database","stl":"3d","styl":"stylus","svelte":"svelte","svg":"svg","swift":"swift","tar":"zip","test.js":"test-js","test.ts":"test-ts","test.tsx":"test-jsx","tex":"tex","tf":"terraform","tfvars":"terraform","tgz":"zip","toml":"toml","ts":"typescript","tsv":"table","tsx":"react_ts","ttf":"font","txt":"document","unity":"unity","v":"vlang","vala":"vala","vim":"vim","vue":"vue","wasm":"webassembly","wat":"webassembly","wav":"audio","webm":"video","webp":"image","woff":"font","woff2":"font","xls":"table","xlsx":"table","xml":"xml","xz":"zip","yaml":"yaml","yml":"yaml","zig":"zig","zip":"zip","zsh":"console"},"name":{".babelrc":"babel",".cursorrules":"cursor",".editorconfig":"editorconfig",".env.development":"tune",".env.example":"tune",".env.local":"tune",".env.production":"tune",".env.test":"tune",".eslintrc":"eslint",".eslintrc.js":"eslint",".eslintrc.json":"eslint",".gitattributes":"git",".gitignore":"git",".gitkeep":"git",".gitmodules":"git",".huskyrc":"husky",".lintstagedrc":"lintstaged",".npmrc":"npm",".nvmrc":"nodejs",".prettierignore":"prettier",".prettierrc":"prettier",".releaserc":"semantic-release",".travis.yml":"travis","agents.md":"agent","authors":"authors","babel.config.js":"babel","bun.lock":"bun","bun.lockb":"bun","changelog":"changelog","changelog.md":"changelog","cmakelists.txt":"cmake","code_of_conduct.md":"conduct","codeowners":"codeowners","commitlint.config.js":"commitlint","compose.yaml":"docker","compose.yml":"docker","composer.lock":"json","contributing.md":"contributing","deno.json":"deno","deno.jsonc":"deno","docker-compose.yaml":"docker","docker-compose.yml":"docker","dockerfile":"docker","ecosystem.config.js":"pm2-ecosystem","eslint.config.js":"eslint","eslint.config.mjs":"eslint","favicon.ico":"favicon","gemfile":"gemfile","go.mod":"go-mod","go.sum":"go-mod","jenkinsfile":"jenkins","jest.config.js":"jest","jest.config.ts":"jest","jsconfig.json":"jsconfig","justfile":"just","lerna.json":"lerna","license":"license","license.md":"license","license.txt":"license","makefile":"makefile","netlify.toml":"netlify","next.config.js":"next","next.config.mjs":"next","next.config.ts":"next","nodemon.json":"nodemon","now.json":"vercel","nx.json":"nx","package-lock.json":"nodejs","package.json":"nodejs","pipfile":"python-misc","pnpm-lock.yaml":"pnpm","poetry.lock":"poetry","pom.xml":"maven","postcss.config.js":"postcss","postcss.config.mjs":"postcss","procfile":"heroku","pyproject.toml":"python-misc","rakefile":"ruby","readme":"readme","readme.md":"readme","renovate.json":"renovate","requirements.txt":"python-misc","robots.txt":"robots","rollup.config.js":"rollup","rollup.config.mjs":"rollup","security.md":"lock","tailwind.config.js":"tailwindcss","tailwind.config.ts":"tailwindcss","taskfile.yml":"taskfile","tsconfig.base.json":"tsconfig","tsconfig.json":"tsconfig","turbo.json":"turborepo","uv.lock":"uv","vercel.json":"vercel","vite.config.js":"vite","vite.config.ts":"vite","vitest.config.mts":"vitest","vitest.config.ts":"vitest","webpack.config.js":"webpack","yarn.lock":"yarn"},"folder":{"__mocks__":"folder-mock","__pycache__":"folder-python","__tests__":"folder-test",".cache":"folder-temp",".circleci":"folder-circleci",".git":"folder-git",".github":"folder-github",".gitlab":"folder-gitlab",".husky":"folder-husky",".idea":"folder-intellij",".next":"folder-next",".nuxt":"folder-nuxt",".pytest_cache":"folder-python",".svelte-kit":"folder-svelte",".turbo":"folder-turborepo",".venv":"folder-environment",".vscode":"folder-vscode","@types":"folder-typescript","admin":"folder-admin","agent":"folder-robot","agents":"folder-robot","android":"folder-android","api":"folder-api","apis":"folder-api","app":"folder-app","apps":"folder-app","archive":"folder-archive","archives":"folder-archive","assets":"folder-resource","atoms":"folder-atom","audio":"folder-audio","auth":"folder-secure","aws":"folder-aws","azure":"folder-aws","backend":"folder-server","backup":"folder-backup","backups":"folder-backup","benchmark":"folder-benchmark","benchmarks":"folder-benchmark","bin":"folder-dist","blog":"folder-docs","build":"folder-dist","cache":"folder-temp","cart":"folder-cart","certificates":"folder-secure","certs":"folder-secure","chat":"folder-messages","ci":"folder-ci","cli":"folder-command","client":"folder-client","command":"folder-command","commands":"folder-command","common":"folder-shared","components":"folder-components","config":"folder-config","configs":"folder-config","configuration":"folder-config","console":"folder-console","content":"folder-content","context":"folder-context","contexts":"folder-context","contract":"folder-contract","contracts":"folder-contract","controller":"folder-controller","controllers":"folder-controller","core":"folder-core","coverage":"folder-coverage","css":"folder-css","data":"folder-database","database":"folder-database","db":"folder-database","debug":"folder-debug","demo":"folder-examples","demos":"folder-examples","deprecated":"folder-deprecated","design":"folder-theme","designs":"folder-theme","desktop":"folder-desktop","dist":"folder-dist","doc":"folder-docs","docker":"folder-docker","docs":"folder-docs","documentation":"folder-docs","draft":"folder-mock","drafts":"folder-mock","e2e":"folder-coverage","element":"folder-element","elements":"folder-element","env":"folder-environment","environment":"folder-environment","environments":"folder-environment","event":"folder-event","events":"folder-event","example":"folder-examples","examples":"folder-examples","extension":"folder-plugin","extensions":"folder-plugin","feature":"folder-features","features":"folder-features","fixture":"folder-mock","fixtures":"folder-mock","font":"folder-font","fonts":"folder-font","frontend":"folder-client","functions":"folder-functions","gcp":"folder-aws","gen":"folder-generator","generated":"folder-generator","gql":"folder-graphql","graphql":"folder-graphql","helper":"folder-helper","helpers":"folder-helper","history":"folder-backup","hooks":"folder-hook","i18n":"folder-i18n","icon":"folder-images","icons":"folder-images","image":"folder-images","images":"folder-images","img":"folder-images","include":"folder-include","includes":"folder-include","infra":"folder-server","infrastructure":"folder-server","interfaces":"folder-interface","ios":"folder-ios","java":"folder-java","job":"folder-job","jobs":"folder-job","k8s":"folder-kubernetes","keys":"folder-keys","kubernetes":"folder-kubernetes","lambda":"folder-functions","lang":"folder-i18n","langs":"folder-i18n","layout":"folder-layout","layouts":"folder-layout","less":"folder-less","lib":"folder-lib","libraries":"folder-lib","library":"folder-lib","libs":"folder-lib","locale":"folder-i18n","locales":"folder-i18n","log":"folder-log","logs":"folder-log","media":"folder-video","messages":"folder-messages","meta":"folder-meta","metadata":"folder-meta","middleware":"folder-middleware","middlewares":"folder-middleware","migration":"folder-migrations","migrations":"folder-migrations","mobile":"folder-mobile","mock":"folder-mock","mocks":"folder-mock","model":"folder-class","models":"folder-class","module":"folder-plugin","modules":"folder-plugin","molecules":"folder-molecule","node_modules":"folder-node","notebook":"folder-jupyter","notebooks":"folder-jupyter","organisms":"folder-organism","out":"folder-dist","output":"folder-dist","package":"folder-packages","packages":"folder-packages","pages":"folder-views","plugin":"folder-plugin","plugins":"folder-plugin","posts":"folder-docs","prisma":"folder-prisma","prompt":"folder-prompts","prompts":"folder-prompts","proto":"folder-proto","provider":"folder-controller","providers":"folder-controller","public":"folder-public","python":"folder-python","queue":"folder-queue","release":"folder-dist","res":"folder-resource","resource":"folder-resource","resources":"folder-resource","review":"folder-review","reviews":"folder-review","router":"folder-routes","routers":"folder-routes","routes":"folder-routes","rust":"folder-rust","sample":"folder-examples","samples":"folder-examples","sass":"folder-sass","schema":"folder-class","schemas":"folder-class","script":"folder-scripts","scripts":"folder-scripts","scss":"folder-sass","secrets":"folder-keys","seed":"folder-seeders","seeds":"folder-seeders","server":"folder-server","service":"folder-controller","services":"folder-controller","settings":"folder-config","shared":"folder-shared","site":"folder-public","skill":"folder-skills","skills":"folder-skills","sounds":"folder-audio","source":"folder-src","spec":"folder-test","specs":"folder-test","src":"folder-src","static":"folder-resource","store":"folder-store","stores":"folder-store","stories":"folder-storybook","style":"folder-css","styles":"folder-css","supabase":"folder-supabase","target":"folder-target","tasks":"folder-tasks","temp":"folder-temp","template":"folder-template","templates":"folder-template","terraform":"folder-terraform","test":"folder-test","tests":"folder-test","theme":"folder-theme","themes":"folder-theme","third-party":"folder-lib","tmp":"folder-temp","tooling":"folder-tools","tools":"folder-tools","translations":"folder-i18n","types":"folder-typescript","typings":"folder-typescript","ui":"folder-ui","util":"folder-utils","utils":"folder-utils","vendor":"folder-lib","vendors":"folder-lib","venv":"folder-environment","video":"folder-video","videos":"folder-video","view":"folder-views","views":"folder-views","web":"folder-public","website":"folder-public","widget":"folder-components","widgets":"folder-components"}}');function t(e){return`/file-icons/${e}.svg`}function s(e){let o=e.toLowerCase(),r=l.name[o];if(r)return t(r);let s=o.split(".");for(let e=1;e<s.length;e+=1){let o=s.slice(e).join("."),r=l.ext[o];if(r)return t(r)}return t(l.defaults.file)}function d(e,o){let r=l.folder[e.toLowerCase()];return r?t(o?`${r}-open`:r):t(o?l.defaults.folderOpen:l.defaults.folder)}}}]);
|