@evandu/super-pi 0.1.58 → 0.1.60
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/agents/super-pi-task/core.ts +105 -34
- package/agents/super-pi-task/index.ts +31 -0
- package/dist/client/assets/{index-CY8_xzn3.js → index-BYgM1GQA.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/server/http-server.js +7 -3
- package/dist/server/runtime.js +2 -2
- package/dist/server/store.js +5 -4
- package/dist/server/task-tool.d.ts +9 -0
- package/dist/server/task-tool.js +9 -0
- package/package.json +1 -1
|
@@ -43,6 +43,11 @@ export const TASK_ROSTER_ENV = "SUPER_PI_TASK_ROSTER";
|
|
|
43
43
|
export const TASK_CONVERSATION_ENV = "SUPER_PI_TASK_CONVERSATION";
|
|
44
44
|
export const TASK_DEPTH_ENV = "SUPER_PI_TASK_DEPTH";
|
|
45
45
|
|
|
46
|
+
/** The independent background-command tool. NOT a sub-agent dispatch: a shell command run asynchronously. */
|
|
47
|
+
export const RUN_ASYNC_TOOL_NAME = "run_async";
|
|
48
|
+
/** Capability env name reused for `run_async` - same per-turn credential, same wire, same server check. */
|
|
49
|
+
export const RUN_ASYNC_CAPABILITY_ENV = "SUPER_PI_TASK_CAPABILITY";
|
|
50
|
+
|
|
46
51
|
/**
|
|
47
52
|
* The `todowrite` extension's half of the same environment contract, declared here for the reason the
|
|
48
53
|
* four above are. `src/server/task-tool.ts` is the other end; `scripts/todo-tool.test.mjs` asserts they
|
|
@@ -72,6 +77,43 @@ export type TodoEntry = { content: string; status: "pending" | "in_progress" | "
|
|
|
72
77
|
/** The three statuses Super Pi renders, as the model writes them. */
|
|
73
78
|
const TODO_STATUSES = new Set(["pending", "in_progress", "completed"]);
|
|
74
79
|
|
|
80
|
+
/** Parameters for the `run_async` tool. Plain shell command, no subagent plumbing. */
|
|
81
|
+
export type RunAsyncParams = { command: string; description?: string };
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The model-facing description for the `run_async` tool.
|
|
85
|
+
*
|
|
86
|
+
* THIS IS A SHELL COMMAND, NOT A SUB-AGENT. The tool runs the command via the platform's shell
|
|
87
|
+
* (bash on Unix, PowerShell on Windows) in the conversation's workspace, returns immediately with
|
|
88
|
+
* state="running", and delivers stdout, stderr and exit code as a follow-up turn when the command
|
|
89
|
+
* settles. Use it whenever the user says "in the background", "async", "without blocking me",
|
|
90
|
+
* "run this and tell me later", or "kick off a build" - any work measured in seconds to minutes
|
|
91
|
+
* that they would otherwise be waiting on.
|
|
92
|
+
*
|
|
93
|
+
* Do NOT use `task` with `background: true` for this: `task` dispatches a sub-agent, and a
|
|
94
|
+
* sub-agent for a one-shot shell command is minutes of process startup to do what `run_async`
|
|
95
|
+
* does in tens of milliseconds.
|
|
96
|
+
*/
|
|
97
|
+
export const RUN_ASYNC_DESCRIPTION = `Run a shell command asynchronously in the current workspace and deliver its output as a follow-up message when it finishes.
|
|
98
|
+
|
|
99
|
+
When to use this:
|
|
100
|
+
- The user says "in the background", "async", "kick off", "start a build and tell me when it's done", or anything else that means "do not block me on this".
|
|
101
|
+
- A command is expected to take seconds to minutes (a long build, a test suite, a download, a file watcher).
|
|
102
|
+
- You want to start several independent commands and let them all run in parallel.
|
|
103
|
+
|
|
104
|
+
How it works:
|
|
105
|
+
1. The command runs in the conversation's workspace under the platform's shell (bash on Linux/macOS, PowerShell on Windows).
|
|
106
|
+
2. The call returns immediately. You will see <task id state="running"> in the result.
|
|
107
|
+
3. When the command finishes, its stdout, stderr and exit code arrive in a new turn wrapped in a <task> envelope.
|
|
108
|
+
|
|
109
|
+
Usage notes:
|
|
110
|
+
1. The "command" field is the shell command verbatim - do not wrap it in JSON.
|
|
111
|
+
2. "description" is optional and only labels the row in the right-rail "background tasks" panel.
|
|
112
|
+
3. Do NOT poll, sleep, or call this tool repeatedly to check on the same command. The result arrives on its own.
|
|
113
|
+
4. For commands that should run in the FOREGROUND and whose output you need before the next step, use the bash tool instead.
|
|
114
|
+
5. For delegating a multi-step task to a specialist sub-agent, use the task tool. This tool is for plain shell commands.
|
|
115
|
+
6. The result envelope looks like <task id="..." state="completed|error"><task_result>stdout</task_result></task> or with <task_error> for failures. Read it the same way you would read a sub-agent's result.`;
|
|
116
|
+
|
|
75
117
|
/** The parameters, exactly OpenCode's (`tool/task.ts:43-52`) minus the ones this step does not do. */
|
|
76
118
|
export type TaskParams = {
|
|
77
119
|
description: string;
|
|
@@ -143,8 +185,9 @@ Usage notes:
|
|
|
143
185
|
6. If a subagent's description says it should be used proactively, use it without being asked.
|
|
144
186
|
7. BY DEFAULT A DISPATCH BLOCKS: the call does not return until that subagent has finished, and its answer comes back to you in this same turn. So you CAN dispatch several in one turn and use each answer before writing the next prompt - which is the normal way to chain specialists.
|
|
145
187
|
8. A LATER DISPATCH MUST CARRY THE EARLIER ONE'S ANSWER IN ITS PROMPT, because the next subagent starts with a fresh context and cannot see what the first one found. The tool does not do this for you. Write the findings you need into the next prompt yourself.
|
|
146
|
-
9. Pass background: true
|
|
147
|
-
10.
|
|
188
|
+
9. Pass background: true to run this sub-agent ASYNCHRONOUSLY. The dispatch returns immediately with state="running" and the answer arrives as a follow-up turn when the sub-agent finishes. Do NOT use this for a plain shell command - use the run_async tool instead, which is much faster for a one-shot command and does not spin up an entire sub-agent.
|
|
189
|
+
10. To run a SHELL COMMAND in the background (a long build, a test suite, a watcher, anything measured in seconds to minutes), use the run_async tool. Do NOT pass background: true to the task tool for this.
|
|
190
|
+
11. For three or more steps where each depends on the previous one, prefer the workflow tool: it runs the chain server-side and hands each step the previous step's output without you copying it through your context.`;
|
|
148
191
|
|
|
149
192
|
/**
|
|
150
193
|
* The roster block, OpenCode's `describeTask()` reduced to its two jobs: the ids that are legal, and
|
|
@@ -259,10 +302,9 @@ export function refuseTask(config: TaskToolConfig, params: TaskParams): string |
|
|
|
259
302
|
if (!config.endpoint) return `The task tool is not available in this session: ${TASK_ENDPOINT_ENV} is not set, so there is no Super Pi server to dispatch to. Do the work yourself with your other tools.`;
|
|
260
303
|
if (!config.conversationId) return `The task tool is not available in this session: ${TASK_CONVERSATION_ENV} is not set, so this run cannot be attributed to a conversation. Do the work yourself with your other tools.`;
|
|
261
304
|
if (!config.roster.length) return "This install has no dispatchable sub-agents (no agents/*.md with `mode: subagent`), so there is nobody to delegate to. Do the work yourself with your other tools.";
|
|
262
|
-
if (!params.subagent_type.trim()) return `subagent_type is required. Available: ${config.roster.map((entry) => entry.id).join(", ")}.`;
|
|
305
|
+
if (!params.subagent_type.trim()) return `subagent_type is required. Available: ${config.roster.map((entry) => entry.id).join(", ")}. If you wanted to run a SHELL COMMAND in the background instead of dispatching a sub-agent, use the run_async tool.`;
|
|
263
306
|
if (!config.roster.some((entry) => entry.id === params.subagent_type)) return `${JSON.stringify(params.subagent_type)} is not a dispatchable subagent_type. Available: ${config.roster.map((entry) => entry.id).join(", ")}. Pick one of those, or do the work yourself.`;
|
|
264
307
|
if (!params.prompt.trim()) return "prompt is required and must not be empty: the sub-agent starts with a fresh context and your prompt is everything it will know.";
|
|
265
|
-
if (params.background === true && !config.execEndpoint) return `Background tasks are not available: ${TASK_EXEC_ENDPOINT_ENV} is not set. Do the work yourself with your other tools.`;
|
|
266
308
|
return undefined;
|
|
267
309
|
}
|
|
268
310
|
|
|
@@ -289,36 +331,6 @@ export async function executeTask(
|
|
|
289
331
|
const refusal = refuseTask(config, params);
|
|
290
332
|
if (refusal) return text(renderTaskResult({ id: "refused", state: "error", text: refusal }), true);
|
|
291
333
|
|
|
292
|
-
// Background: true uses the lightweight exec endpoint instead of the subagent dispatcher.
|
|
293
|
-
// This avoids spawning a full Pi agent process for a plain shell command.
|
|
294
|
-
if (params.background === true && config.execEndpoint) {
|
|
295
|
-
const send = deps.fetch ?? globalFetch;
|
|
296
|
-
let response: Awaited<ReturnType<TaskFetch>>;
|
|
297
|
-
try {
|
|
298
|
-
response = await send(config.execEndpoint, {
|
|
299
|
-
method: "POST",
|
|
300
|
-
headers: { "content-type": "application/json", ...(config.token ? { authorization: `Bearer ${config.token}` } : {}) },
|
|
301
|
-
body: JSON.stringify({
|
|
302
|
-
cmd: params.prompt,
|
|
303
|
-
cwd: context.cwd,
|
|
304
|
-
conversationId: config.conversationId,
|
|
305
|
-
capability: config.capability,
|
|
306
|
-
}),
|
|
307
|
-
...(deps.signal ? { signal: deps.signal } : {}),
|
|
308
|
-
});
|
|
309
|
-
} catch (error) {
|
|
310
|
-
return text(renderTaskResult({ id: "unreachable", state: "error", text: `Could not reach the Super Pi server at ${config.execEndpoint}: ${error instanceof Error ? error.message : "unknown error"}` }), true);
|
|
311
|
-
}
|
|
312
|
-
let payload: { sessionId?: string; status?: string; error?: string };
|
|
313
|
-
try { payload = JSON.parse(await response.text()) as typeof payload; }
|
|
314
|
-
catch { return text(renderTaskResult({ id: "unreadable", state: "error", text: `The exec endpoint answered ${response.status} with something that is not JSON.` }), true); }
|
|
315
|
-
const id = payload.sessionId ?? "refused";
|
|
316
|
-
if (payload.status === "running") {
|
|
317
|
-
return text(`<task id="${id}" state="running">\n<summary>${params.description.trim() || params.prompt.slice(0, 60)}</summary>\n<task_result>The command is running in the background. You will be notified automatically when it finishes. Do not sleep, poll for progress, or duplicate this work. Continue with non-overlapping work.</task_result>\n</task>`);
|
|
318
|
-
}
|
|
319
|
-
return text(renderTaskResult({ id, state: "error", text: payload.error ?? `Exec endpoint returned status ${payload.status}` }), true);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
334
|
const send = deps.fetch ?? globalFetch;
|
|
323
335
|
let response: Awaited<ReturnType<TaskFetch>>;
|
|
324
336
|
try {
|
|
@@ -503,6 +515,65 @@ export function refuseTodo(config: TodoToolConfig, params: TodoParams): string |
|
|
|
503
515
|
return undefined;
|
|
504
516
|
}
|
|
505
517
|
|
|
518
|
+
/**
|
|
519
|
+
* Refuses a `run_async` call that cannot work.
|
|
520
|
+
*
|
|
521
|
+
* Two checks, for the same three-case shape `refuseTask` and `refuseTodo` use: the call must reach the
|
|
522
|
+
* server, and the server must be able to attribute it to a conversation. The roster is not consulted
|
|
523
|
+
* because this tool is not a dispatch.
|
|
524
|
+
*/
|
|
525
|
+
export function refuseRunAsync(config: TaskToolConfig, params: RunAsyncParams): string | undefined {
|
|
526
|
+
if (!config.execEndpoint) return `The run_async tool is not available in this session: ${TASK_EXEC_ENDPOINT_ENV} is not set, so there is no Super Pi server to run commands on. Do the work yourself with your other tools.`;
|
|
527
|
+
if (!config.conversationId) return `The run_async tool is not available in this session: ${TASK_CONVERSATION_ENV} is not set, so this run cannot be attributed to a conversation. Do the work yourself with your other tools.`;
|
|
528
|
+
if (typeof params.command !== "string" || !params.command.trim()) return "command is required and must not be empty.";
|
|
529
|
+
return undefined;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Runs one shell command asynchronously and returns the envelope the model reads.
|
|
534
|
+
*
|
|
535
|
+
* Independent of `executeTask` even though both post JSON to the same server: the model reaches for
|
|
536
|
+
* `run_async` when the user wants a background shell command, and reaches for `task` when they want
|
|
537
|
+
* a sub-agent. Routing them through one function would mean sharing a refuse-list, a description,
|
|
538
|
+
* and a wire that a model can never get wrong by accident.
|
|
539
|
+
*/
|
|
540
|
+
export async function executeAsync(
|
|
541
|
+
params: RunAsyncParams,
|
|
542
|
+
context: TaskToolContext,
|
|
543
|
+
config: TaskToolConfig,
|
|
544
|
+
deps: { signal?: AbortSignal; fetch?: TaskFetch } = {},
|
|
545
|
+
): Promise<TaskToolResult> {
|
|
546
|
+
const text = (body: string, isError?: boolean): TaskToolResult => ({ content: [{ type: "text", text: body }], details: undefined, ...(isError ? { isError: true } : {}) });
|
|
547
|
+
const refusal = refuseRunAsync(config, params);
|
|
548
|
+
if (refusal) return text(renderTaskResult({ id: "refused", state: "error", text: refusal }), true);
|
|
549
|
+
|
|
550
|
+
const send = deps.fetch ?? globalFetch;
|
|
551
|
+
let response: Awaited<ReturnType<TaskFetch>>;
|
|
552
|
+
try {
|
|
553
|
+
response = await send(config.execEndpoint, {
|
|
554
|
+
method: "POST",
|
|
555
|
+
headers: { "content-type": "application/json", ...(config.token ? { authorization: `Bearer ${config.token}` } : {}) },
|
|
556
|
+
body: JSON.stringify({
|
|
557
|
+
cmd: params.command,
|
|
558
|
+
cwd: context.cwd,
|
|
559
|
+
conversationId: config.conversationId,
|
|
560
|
+
capability: config.capability,
|
|
561
|
+
}),
|
|
562
|
+
...(deps.signal ? { signal: deps.signal } : {}),
|
|
563
|
+
});
|
|
564
|
+
} catch (error) {
|
|
565
|
+
return text(renderTaskResult({ id: "unreachable", state: "error", text: `Could not reach the Super Pi server at ${config.execEndpoint}: ${error instanceof Error ? error.message : "unknown error"}` }), true);
|
|
566
|
+
}
|
|
567
|
+
let payload: { sessionId?: string; status?: string; error?: string };
|
|
568
|
+
try { payload = JSON.parse(await response.text()) as typeof payload; }
|
|
569
|
+
catch { return text(renderTaskResult({ id: "unreadable", state: "error", text: `The exec endpoint answered ${response.status} with something that is not JSON.` }), true); }
|
|
570
|
+
const id = payload.sessionId ?? "refused";
|
|
571
|
+
if (payload.status === "running") {
|
|
572
|
+
return text(`<task id="${id}" state="running">\n<summary>${(params.description ?? "").trim() || params.command.slice(0, 60)}</summary>\n<task_result>The command is running in the background. You will be notified automatically when it finishes. Do not sleep, poll for progress, or duplicate this work. Continue with non-overlapping work.</task_result>\n</task>`);
|
|
573
|
+
}
|
|
574
|
+
return text(renderTaskResult({ id, state: "error", text: payload.error ?? `Exec endpoint returned status ${payload.status}` }), true);
|
|
575
|
+
}
|
|
576
|
+
|
|
506
577
|
/** One HTTP seam, injected so a test can drive the tool without a socket and production uses global fetch. */
|
|
507
578
|
export type TodoFetch = (url: string, init: { method: string; headers: Record<string, string>; body: string; signal?: AbortSignal }) => Promise<{ ok: boolean; status: number; text(): Promise<string> }>;
|
|
508
579
|
|
|
@@ -21,6 +21,12 @@ import {
|
|
|
21
21
|
readTodoConfig,
|
|
22
22
|
type TodoParams,
|
|
23
23
|
} from "./core.ts";
|
|
24
|
+
import {
|
|
25
|
+
RUN_ASYNC_DESCRIPTION,
|
|
26
|
+
RUN_ASYNC_TOOL_NAME,
|
|
27
|
+
executeAsync,
|
|
28
|
+
type RunAsyncParams,
|
|
29
|
+
} from "./core.ts";
|
|
24
30
|
|
|
25
31
|
/**
|
|
26
32
|
* The Pi adapter for the `task` and `todowrite` tools. Everything with a decision in it is in
|
|
@@ -225,6 +231,31 @@ const extension = (pi: ExtensionApi): void => {
|
|
|
225
231
|
execute: async (_toolCallId, params, signal) =>
|
|
226
232
|
await executeWorkflow(params as WorkflowParams, workflowConfig, { signal: signal ?? undefined }),
|
|
227
233
|
});
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* `run_async` - asynchronous shell command execution. NOT a sub-agent dispatch.
|
|
237
|
+
*
|
|
238
|
+
* Registered LAST so a model scanning the tool list reads `task` (the more powerful delegation
|
|
239
|
+
* primitive) before the more specialised background-command tool. A model reaching for the wrong
|
|
240
|
+
* one is the failure this ordering tries to prevent.
|
|
241
|
+
*
|
|
242
|
+
* SHARES THE EXEC ENDPOINT with `task` when it had `background: true`, but is its OWN tool so the
|
|
243
|
+
* description can say "shell command" rather than "sub-agent with a flag" and refuse-task does not
|
|
244
|
+
* have to make the subagent_type optional in a way that confused a model reading the description.
|
|
245
|
+
*/
|
|
246
|
+
const RunAsyncParameters = Type.Object({
|
|
247
|
+
command: Type.String({ description: "The shell command to run in the workspace. Runs under bash on Linux/macOS and PowerShell on Windows." }),
|
|
248
|
+
description: Type.Optional(Type.String({ description: "3-5 word label shown in the background tasks panel." })),
|
|
249
|
+
});
|
|
250
|
+
pi.registerTool({
|
|
251
|
+
name: RUN_ASYNC_TOOL_NAME,
|
|
252
|
+
label: "Run Async",
|
|
253
|
+
description: RUN_ASYNC_DESCRIPTION,
|
|
254
|
+
promptSnippet: "run a shell command in the background and deliver its output as a follow-up message",
|
|
255
|
+
parameters: RunAsyncParameters,
|
|
256
|
+
execute: async (_toolCallId, params, signal, _onUpdate, context) =>
|
|
257
|
+
await executeAsync(params as RunAsyncParams, context, config, { signal: signal ?? undefined }),
|
|
258
|
+
});
|
|
228
259
|
};
|
|
229
260
|
|
|
230
261
|
export default extension;
|
|
@@ -48,6 +48,6 @@ pi update npm:@evandu/super-pi
|
|
|
48
48
|
npx @evandu/super-pi`})})]}),(0,m.jsxs)(`div`,{className:`help-card`,children:[(0,m.jsx)(`h4`,{children:`🎯 键盘快捷键`}),(0,m.jsxs)(`div`,{className:`help-command-table`,children:[(0,m.jsxs)(`div`,{className:`cmd-row`,children:[(0,m.jsx)(`code`,{children:`Enter`}),(0,m.jsx)(`span`,{children:`发送对话消息`})]}),(0,m.jsxs)(`div`,{className:`cmd-row`,children:[(0,m.jsx)(`code`,{children:`Shift + Enter`}),(0,m.jsx)(`span`,{children:`输入框内换行`})]}),(0,m.jsxs)(`div`,{className:`cmd-row`,children:[(0,m.jsx)(`code`,{children:`Esc`}),(0,m.jsx)(`span`,{children:`快速关闭当前顶层弹窗(使用指南、设置、工作区选择器等)`})]})]})]})]})}function Kt(){return(0,m.jsx)(`div`,{className:`help-section-group`,children:(0,m.jsxs)(`div`,{className:`help-card`,children:[(0,m.jsx)(`h4`,{children:`🎨 4 款主题,来自 VSCode 流行主题`}),(0,m.jsxs)(`div`,{className:`help-theme-list`,children:[(0,m.jsxs)(`div`,{className:`help-theme-item`,children:[(0,m.jsx)(`strong`,{children:`🟣 Dracula`}),(0,m.jsx)(`p`,{children:`紫调暗色,饱满对比,适合夜间专注编程。`})]}),(0,m.jsxs)(`div`,{className:`help-theme-item`,children:[(0,m.jsx)(`strong`,{children:`🟠 Monokai`}),(0,m.jsx)(`p`,{children:`暖调暗色,橙红点缀,经典编辑器风格。`})]}),(0,m.jsxs)(`div`,{className:`help-theme-item`,children:[(0,m.jsx)(`strong`,{children:`🟡 Solarized Light`}),(0,m.jsx)(`p`,{children:`暖黄米色调,柔和护眼,适合长时间阅读。`})]}),(0,m.jsxs)(`div`,{className:`help-theme-item`,children:[(0,m.jsx)(`strong`,{children:`🔵 GitHub Light`}),(0,m.jsx)(`p`,{children:`冷调浅色,中性清晰,日常办公首选。`})]})]}),(0,m.jsxs)(`p`,{className:`help-hint`,children:[`可在左侧栏底部的 `,(0,m.jsx)(`strong`,{children:`⚙ 设置`}),` 中一键切换主题,设置会自动持久化保存在本地。`]})]})})}function qt({workspaceId:e,onClose:t}){let[n,r]=(0,p.useState)(),[i,a]=(0,p.useState)(``),[o,s]=(0,p.useState)(!1),[c,l]=(0,p.useState)(`memory`),[u,d]=(0,p.useState)(``),[f,h]=(0,p.useState)(),g=(0,p.useRef)(e);g.current=e;let _=(0,p.useRef)(0);async function v(t){if(!e)return;let n=++_.current;s(!0),a(``);try{let i=await fetch(`/api/memory?workspaceId=${encodeURIComponent(e)}`,{method:t?`POST`:`GET`,headers:{"Content-Type":`application/json`},...t?{body:JSON.stringify(t)}:{}}),a=await i.json();if(!i.ok)throw Error(a.error);return g.current!==e||n!==_.current?!1:(r(a),!0)}catch(t){return g.current===e&&n===_.current&&a(String(t)),!1}finally{g.current===e&&n===_.current&&s(!1)}}return(0,p.useEffect)(()=>{r(void 0),h(void 0),d(``),v()},[e]),e?(0,m.jsxs)(`section`,{"data-memory-panel":`1`,className:`settings-panel-container`,children:[(0,m.jsx)(`div`,{className:`settings-agents-header`,children:(0,m.jsxs)(`p`,{className:`settings-agents-desc`,children:[(0,m.jsx)(`strong`,{children:`长期知识与经验复盘。`}),` 用户档案跨工作区共享;工作区事实、技能和历史召回按当前工作区隔离。后台复盘不会静默删除旧记忆。`]})}),i&&(0,m.jsx)(`div`,{className:`settings-dir-error`,role:`alert`,children:i}),n&&(0,m.jsxs)(`fieldset`,{disabled:o,className:`settings-memory-fieldset`,children:[(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsx)(`h4`,{className:`settings-section-title`,children:`主动记忆机制配置`}),(0,m.jsxs)(`div`,{className:`settings-memory-switches`,children:[(0,m.jsxs)(`label`,{className:`settings-checkbox-label`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:n.settings.enabled,onChange:e=>void v({action:`configure`,settings:{...n.settings,enabled:e.target.checked}})}),`启用主动记忆`]}),(0,m.jsxs)(`label`,{className:`settings-checkbox-label`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:n.settings.writeApproval,onChange:e=>void v({action:`configure`,settings:{...n.settings,writeApproval:e.target.checked}})}),`Agent 写入均需审批`]})]}),(0,m.jsxs)(`div`,{className:`settings-memory-interval-row`,style:{marginTop:10},children:[(0,m.jsxs)(`label`,{className:`settings-memory-interval-label`,children:[`复盘间隔(用户回合,0 为关闭):`,(0,m.jsx)(`input`,{"aria-label":`复盘间隔`,type:`number`,min:`0`,className:`settings-dir-input settings-interval-input`,value:n.settings.reviewInterval,onChange:e=>r({...n,settings:{...n.settings,reviewInterval:Number(e.target.value)}})})]}),(0,m.jsx)(`button`,{type:`button`,className:`settings-dir-add-btn`,onClick:()=>void v({action:`configure`,settings:n.settings}),children:`保存间隔`})]})]}),(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsxs)(`div`,{className:`settings-memory-category-header`,children:[(0,m.jsx)(`h4`,{className:`settings-section-title`,children:`记忆条目管理`}),(0,m.jsxs)(`select`,{"aria-label":`记忆类别`,className:`settings-memory-select`,value:c,onChange:e=>{l(e.target.value),h(void 0),d(``)},children:[(0,m.jsx)(`option`,{value:`user`,children:`用户档案(全局共享)`}),(0,m.jsx)(`option`,{value:`memory`,children:`工作区事实(当前工作区)`}),(0,m.jsx)(`option`,{value:`skills`,children:`技能与经验(当前工作区)`})]})]}),(n.entries[c]??[]).length===0?(0,m.jsx)(`div`,{className:`settings-empty-hint`,children:`当前类别暂无条目。在下方输入内容即可添加。`}):(0,m.jsx)(`div`,{className:`settings-memory-entries-list`,children:(n.entries[c]??[]).map(e=>(0,m.jsxs)(`article`,{"data-memory-entry":e.id,className:`settings-memory-card`,children:[(0,m.jsx)(`pre`,{className:`settings-memory-content`,children:e.content}),(0,m.jsxs)(`div`,{className:`settings-memory-card-actions`,children:[(0,m.jsx)(`button`,{type:`button`,className:`settings-rule-edit-btn`,onClick:()=>{h(e.id),d(e.content)},children:`编辑`}),(0,m.jsx)(`button`,{type:`button`,className:`settings-dir-remove-btn`,onClick:()=>void v({action:`write`,operation:{target:c,action:`remove`,id:e.id}}),children:`删除`})]})]},e.id))}),(0,m.jsxs)(`div`,{className:`settings-memory-editor`,style:{marginTop:12},children:[(0,m.jsx)(`h5`,{className:`settings-memory-editor-title`,children:f?`编辑条目`:`添加新条目`}),(0,m.jsx)(`textarea`,{"aria-label":`记忆内容`,className:`settings-memory-textarea`,placeholder:c===`skills`?`# 技能名称
|
|
49
49
|
已验证的步骤、命令和注意事项`:`输入长期有效的事实或偏好`,value:u,onChange:e=>d(e.target.value)}),(0,m.jsxs)(`div`,{className:`settings-rule-form-buttons`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`settings-dir-add-btn`,disabled:!u.trim(),onClick:async()=>{await v({action:`write`,operation:{target:c,action:f?`replace`:`add`,id:f,content:u}})&&(h(void 0),d(``))},children:[`保存`,f?`修改`:`新条目`]}),f&&(0,m.jsx)(`button`,{type:`button`,className:`settings-rule-cancel-btn`,onClick:()=>{h(void 0),d(``)},children:`取消编辑`})]})]})]}),(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsxs)(`h4`,{className:`settings-section-title`,children:[`待审批提案(共 `,n.pending.length,` 个)`]}),n.pending.length===0?(0,m.jsx)(`div`,{className:`settings-empty-hint`,children:`暂无待审批提案。`}):(0,m.jsx)(`div`,{className:`settings-dirs-list`,children:n.pending.map(e=>(0,m.jsxs)(`article`,{"data-memory-proposal":e.id,className:`settings-proposal-card`,children:[(0,m.jsxs)(`div`,{className:`settings-proposal-header`,children:[(0,m.jsx)(`span`,{className:`settings-proposal-badge`,children:e.operation.target}),(0,m.jsx)(`span`,{className:`settings-proposal-action`,children:e.operation.action})]}),e.previous&&(0,m.jsxs)(`pre`,{className:`settings-proposal-diff old`,children:[`原内容:`,e.previous]}),(0,m.jsx)(`pre`,{className:`settings-proposal-diff new`,children:e.operation.content}),(0,m.jsxs)(`div`,{className:`settings-proposal-actions`,children:[(0,m.jsx)(`button`,{type:`button`,className:`settings-rule-edit-btn`,onClick:()=>void v({action:`approve`,proposalId:e.id}),children:`批准`}),(0,m.jsx)(`button`,{type:`button`,className:`settings-dir-remove-btn`,onClick:()=>void v({action:`discard`,proposalId:e.id}),children:`拒绝`})]})]},e.id))})]})]}),t&&(0,m.jsx)(`div`,{className:`picker-actions`,children:(0,m.jsx)(`button`,{type:`button`,className:`picker-cancel`,onClick:t,children:`完成`})})]}):(0,m.jsx)(`div`,{className:`settings-empty-hint`,children:`请先在主界面选择工作区以管理其专属记忆与技能。`})}var Jt=[{kind:`calculator`,name:`计算器`,glyph:`∑`,blurb:`算术表达式,四则运算与乘方。除零会明确报错。`},{kind:`timestamp`,name:`时间戳`,glyph:`◷`,blurb:`Unix 时间戳与日期互转,本地计算,不联网。`}],Yt=[{id:`preset_calculator`,kind:`calculator`,name:`计算器`,glyph:`∑`}],Xt=40,P=2048,Zt=`super-pi:tools:v1`;function Qt(e){return typeof e==`string`?e.replace(/\s+/g,` `).trim().slice(0,Xt):``}function $t(e){let t=e.trim();if(!t)return{ok:!1,reason:`请填写网址。`};if(t.length>P)return{ok:!1,reason:`网址太长了,请控制在 ${P} 个字符以内。`};let n=se(t);return n?{ok:!0,url:n}:{ok:!1,reason:`这个网址不是允许的协议。只支持 http / https / mailto 开头的网址。`}}function en(e){if(!e)return[];let t;try{t=JSON.parse(e)}catch{return[]}if(!Array.isArray(t))return[];let n=[],r=new Set;for(let e of t){if(typeof e!=`object`||!e)continue;let t=e,i=t.kind;if(typeof i!=`string`||i!==`calculator`&&i!==`timestamp`&&i!==`link`)continue;let a=Qt(t.name);if(!a)continue;let o=typeof t.glyph==`string`&&t.glyph.trim()?t.glyph.trim().slice(0,4):``;if(!o)continue;let s=typeof t.id==`string`&&t.id.trim()?t.id.trim().slice(0,64):``;if(s&&!r.has(s)){if(i===`link`){let e=se(typeof t.url==`string`?t.url:``);if(!e)continue;r.add(s),n.push({id:s,kind:`link`,name:a,glyph:o,url:e})}else if(r.add(s),n.push({id:s,kind:i,name:a,glyph:o}),n.length>=32)break}}return n}function F(e){return JSON.stringify(e.map(e=>e.kind===`link`?{...e}:{id:e.id,kind:e.kind,name:e.name,glyph:e.glyph}))}function tn(){let e=typeof globalThis<`u`?globalThis.crypto:void 0;return typeof e?.randomUUID==`function`?e.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function nn(e,t){let n=e===`link`?`link`:`preset_${e}`,r=tn().replace(/-/g,``).slice(0,8),i=`${n}_${r}`,a=1;for(;t.includes(i);)i=`${n}_${r}_${a}`,a+=1;return i}function I(e,t){if(e.some(e=>e.kind===t))return e.slice();let n=Jt.find(e=>e.kind===t);return n?[...e,{id:nn(t,e.map(e=>e.id)),kind:t,name:n.name,glyph:n.glyph}]:e.slice()}function rn(e,t){return e.filter(e=>e.id!==t)}var an=e=>({ok:!1,reason:e}),on=`除数不能为 0:除以零没有结果,请换一个非零的除数。`,sn=new Set([`/`,`%`]),cn=e=>e!==void 0&&e>=`0`&&e<=`9`,L=e=>e!==void 0&&/\s/.test(e);function ln(e){for(;L(e.source[e.at]);)e.at+=1}function un(e){let t=e.at,n=0;for(;cn(e.source[e.at]);)e.at+=1,n+=1;if(e.source[e.at]===`.`)for(e.at+=1;cn(e.source[e.at]);)e.at+=1,n+=1;if(!n)return e.at=t,an(`「${e.source[t]}」不是有效的数字。`);let r=Number(e.source.slice(t,e.at));return Number.isFinite(r)?{ok:!0,value:r}:an(`数字太长了,无法表示。`)}function dn(e){ln(e);let t=e.source[e.at];if(t===void 0)return an(`算式不完整:末尾还缺一个数字或右括号。`);if(t===`(`){e.at+=1;let t=hn(e);return t.ok?(ln(e),e.source[e.at]===`)`?(e.at+=1,t):an(`括号不匹配:少了一个右括号「)」。`)):t}return cn(t)||t===`.`?un(e):an(`无法识别的字符「${t}」。`)}function fn(e){let t=dn(e);if(!t.ok||(ln(e),e.source[e.at]!==`^`))return t;e.at+=1;let n=pn(e);if(!n.ok)return n;let r=t.value**n.value;return Number.isFinite(r)?{ok:!0,value:r}:an(`结果超出了可计算的数值范围。`)}function pn(e){ln(e);let t=e.source[e.at];if(t!==`+`&&t!==`-`)return fn(e);e.at+=1;let n=pn(e);if(!n.ok)return n;let r=t===`-`?-n.value:n.value;return Number.isFinite(r)?{ok:!0,value:r}:an(`结果超出了可计算的数值范围。`)}function mn(e){let t=pn(e);if(!t.ok)return t;for(;;){ln(e);let n=e.source[e.at];if(n!==`*`&&!sn.has(n))return t;e.at+=1;let r=pn(e);if(!r.ok)return r;if(sn.has(n)&&r.value===0)return an(on);let i=n===`*`?t.value*r.value:n===`%`?t.value%r.value:t.value/r.value;if(!Number.isFinite(i))return an(`结果超出了可计算的数值范围。`);t={ok:!0,value:i}}}function hn(e){let t=mn(e);if(!t.ok)return t;for(;;){ln(e);let n=e.source[e.at];if(n!==`+`&&n!==`-`)return t;e.at+=1;let r=mn(e);if(!r.ok)return r;let i=n===`+`?t.value+r.value:t.value-r.value;if(!Number.isFinite(i))return an(`结果超出了可计算的数值范围。`);t={ok:!0,value:i}}}function gn(e){let t=e.trim();if(!t)return an(`请输入算式。`);if(t.length>200)return an(`算式太长了,请控制在 200 个字符以内。`);let n={source:t,at:0},r=hn(n);return r.ok?(ln(n),n.at===t.length?Number.isFinite(r.value)?r:an(`结果不是有限数字。`):an(`「${t[n.at]}」后面的内容无法识别,请检查是否漏了运算符。`)):r}function _n(e){return String(!Number.isFinite(e)||Number.isInteger(e)&&Math.abs(e)<1e21?e:Number(e.toPrecision(12)))}function vn(e){let t=e.trim();if(!t)return{ok:!1,reason:`请输入时间戳或日期。`};if(/^\d+$/.test(t)){let e=Number(t);if(!Number.isFinite(e))return{ok:!1,reason:`这个数字太大,无法表示。`};let n=t.length<=11?e*1e3:e;return!Number.isFinite(n)||Math.abs(n)>864e13?{ok:!1,reason:`这个时间戳超出了日期能表示的范围。`}:{ok:!0,ms:n}}let n=Date.parse(t);return Number.isNaN(n)?{ok:!1,reason:`看不懂这个日期。试试 1757000000、2026-10-08 或 2026-10-08T09:00:00。`}:{ok:!0,ms:n}}var yn=e=>String(Math.abs(e)).padStart(2,`0`);function bn(e){let t=new Date(e);return Number.isNaN(t.getTime())?null:{local:`${t.getFullYear()}-${yn(t.getMonth()+1)}-${yn(t.getDate())} ${yn(t.getHours())}:${yn(t.getMinutes())}:${yn(t.getSeconds())}`,iso:t.toISOString(),seconds:String(Math.floor(e/1e3)),milliseconds:String(e)}}var xn=e=>e.nativeEvent.isComposing||e.keyCode===229,Sn=`super-pi.theme`,Cn=[{id:`dracula`,name:`Dracula`,blurb:`紫调暗色,饱满对比,适合夜间专注。`},{id:`monokai`,name:`Monokai`,blurb:`暖调暗色,橙红点缀,经典编辑器风格。`},{id:`solarized-light`,name:`Solarized Light`,blurb:`暖黄米色调,柔和护眼,适合长时间阅读。`},{id:`github-light`,name:`GitHub Light`,blurb:`冷调浅色,中性清晰,日常办公首选。`}],wn=`dracula`,Tn=e=>typeof e==`string`&&Cn.some(t=>t.id===e);function En(){try{let e=window.localStorage.getItem(Sn);if(!e)return wn;let t=JSON.parse(e),n=typeof t==`string`?t:t?.id;return Tn(n)?n:wn}catch{return wn}}function Dn(e){document.documentElement.setAttribute(`data-theme`,e);try{window.localStorage.setItem(Sn,JSON.stringify({id:e,version:1}))}catch{}}function On(){let[e,t]=(0,p.useState)(wn);return(0,p.useEffect)(()=>{t(En());let e=e=>{if(e.key===`super-pi.theme`&&e.newValue)try{let n=JSON.parse(e.newValue),r=typeof n==`string`?n:n?.id;Tn(r)&&(document.documentElement.setAttribute(`data-theme`,r),t(r))}catch{}};return window.addEventListener(`storage`,e),()=>window.removeEventListener(`storage`,e)},[]),{theme:e,setTheme:(0,p.useCallback)(e=>{Dn(e),t(e)},[])}}function kn({theme:e,onChooseTheme:t,onClose:n}){let r=Cn.find(t=>t.id===e);return(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`div`,{className:`settings-scope`,children:`主题只影响这台设备的显示,不改变任何内容;切换立即生效。`}),Cn.length===0?(0,m.jsx)(`div`,{className:`theme-empty`,"data-theme-empty":`1`,children:`没有可用的主题。界面将继续使用默认配色,你可以在主题文件恢复后重试。`}):(0,m.jsx)(`div`,{className:`theme-options`,role:`radiogroup`,"aria-label":`主题`,children:Cn.map(n=>{let r=n.id===e;return(0,m.jsxs)(`button`,{type:`button`,className:`theme-option`,role:`radio`,"aria-checked":r,"aria-pressed":r,"data-theme-option":n.id,"data-theme-current":r?`1`:`0`,onClick:()=>t(n.id),children:[(0,m.jsx)(`span`,{className:`theme-preview-strip`,"data-preview":n.id,"aria-hidden":`true`}),(0,m.jsxs)(`span`,{className:`theme-option-name`,children:[n.name,r&&(0,m.jsx)(`span`,{className:`theme-option-current`,children:`当前 ✓`})]}),(0,m.jsx)(`span`,{className:`theme-option-blurb`,children:n.blurb})]},n.id)})}),(0,m.jsx)(`div`,{className:`picker-actions`,children:(0,m.jsx)(`button`,{type:`button`,className:`picker-cancel`,"data-theme-close":`1`,onClick:n,children:`完成`})}),(0,m.jsxs)(`div`,{className:`settings-scope theme-current-line`,children:[`当前:`,r?`${r.name}(${r.id})`:`默认`]})]})}function An({context:e}){let[t,n]=(0,p.useState)(``),[r,i]=(0,p.useState)(``),[a,o]=(0,p.useState)(!1),s=e.agentCatalog,c=e.subagentCatalog,l=s?.agents??[],u=c?.agents??[],d=[...l,...u],f=[...s?.problems??[],...c?.problems??[]],h=[...new Set([...s?.directories??(s?.directory?[s.directory]:[]),...e.customAgentDirs??[]])],g=e.customAgentDirs??[],_=r=>{if(r.preventDefault(),e.pendingSettings)return;let a=t.trim();a&&(g.includes(a)?i(`该路径已存在于自定义目录列表中`):(e.onSetCustomAgentDirs?.([...g,a]),n(``),i(``)))},v=t=>{let n=g.filter(e=>e!==t);e.onSetCustomAgentDirs?.(n)};return(0,m.jsxs)(`div`,{className:`settings-agents-container`,children:[(0,m.jsxs)(`div`,{className:`settings-agents-header`,children:[(0,m.jsx)(`p`,{className:`settings-agents-desc`,children:`Super Pi 支持多目录发现智能体。系统会按优先级自上而下合并扫描目录;若存在同名配置,高优先级目录的文件将覆盖低优先级目录。`}),(0,m.jsx)(`button`,{type:`button`,className:`settings-agent-rescan-btn`,onClick:()=>{o(!0),e.onRescanAgents?.(),setTimeout(()=>o(!1),600)},disabled:a,title:`重新扫描所有目录中的智能体定义文件`,children:a?`正在扫描…`:`🔄 立即重新扫描`})]}),(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsx)(`h4`,{className:`settings-section-title`,children:`发现路径清单(按优先级自高到低)`}),(0,m.jsx)(`div`,{className:`settings-dirs-list`,children:h.length===0?(0,m.jsx)(`div`,{className:`settings-empty-hint`,children:`暂无活跃的发现路径`}):h.map((t,n)=>{let r=g.includes(t),i=t.includes(`.super_pi`)||t.includes(`.super-pi`)||t.includes(`.pi`),a=!r&&!i,o=d.filter(e=>e.sourceDir===t).length;return(0,m.jsxs)(`div`,{className:`settings-dir-row`,children:[(0,m.jsxs)(`div`,{className:`settings-dir-info`,children:[(0,m.jsxs)(`span`,{className:`settings-dir-priority`,children:[`#`,n+1]}),(0,m.jsx)(`span`,{className:`settings-dir-path`,title:t,children:t}),(0,m.jsx)(`span`,{className:`settings-dir-tag`,children:r?`自定义`:i?`用户全局`:a?`内置`:`环境`}),(0,m.jsxs)(`span`,{className:`settings-dir-count`,children:[`(发现 `,o,` 个智能体)`]})]}),r&&(0,m.jsx)(`button`,{type:`button`,className:`settings-dir-remove-btn`,disabled:e.pendingSettings,onClick:()=>v(t),title:`移除此自定义扫描路径`,children:`移除`})]},t)})})]}),(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsx)(`h4`,{className:`settings-section-title`,children:`添加自定义路径`}),(0,m.jsxs)(`form`,{onSubmit:_,className:`settings-add-dir-form`,children:[(0,m.jsx)(`input`,{type:`text`,className:`settings-dir-input`,value:t,onChange:e=>{n(e.target.value),r&&i(``)},onKeyDown:e=>{e.key===`Enter`&&xn(e)&&e.preventDefault()},placeholder:`输入本地目录绝对路径或 ~/ 开头路径,如 D:\\agents 或 ~/.super_pi/agents`}),(0,m.jsx)(`button`,{type:`submit`,className:`settings-dir-add-btn`,disabled:e.pendingSettings||!t.trim(),children:`添加目录`})]}),r&&(0,m.jsx)(`div`,{className:`settings-dir-error`,children:r})]}),f.length>0&&(0,m.jsxs)(`section`,{className:`settings-section settings-problems-section`,children:[(0,m.jsxs)(`h4`,{className:`settings-problems-title`,children:[`⚠️ 发现 `,f.length,` 个文件解析问题`]}),(0,m.jsx)(`div`,{className:`settings-problems-list`,children:f.map((e,t)=>(0,m.jsxs)(`div`,{className:`settings-problem-row`,children:[(0,m.jsx)(`span`,{className:`settings-problem-file`,children:e.file}),`: `,e.message]},t))})]}),(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsxs)(`h4`,{className:`settings-section-title`,children:[`已发现的智能体(共 `,d.length,` 个)`]}),d.length===0?(0,m.jsxs)(`div`,{className:`settings-empty-hint`,children:[`当前未发现任何智能体。请在上述目录中添加 `,(0,m.jsx)(`code`,{children:`.md`}),` 文件(需包含 YAML frontmatter)。`]}):(0,m.jsx)(`div`,{className:`settings-agent-grid`,children:d.map(e=>(0,m.jsxs)(`div`,{className:`settings-agent-card`,children:[(0,m.jsxs)(`div`,{className:`settings-agent-card-header`,children:[(0,m.jsx)(`span`,{className:`settings-agent-name`,children:e.name}),(0,m.jsxs)(`span`,{className:`settings-agent-id`,children:[`(`,e.id,`)`]}),(0,m.jsx)(`span`,{className:`settings-agent-mode-badge ${e.mode}`,children:e.mode===`primary`?`主智能体`:`子智能体`})]}),e.sourceDir&&(0,m.jsxs)(`div`,{className:`settings-agent-source`,title:e.sourceDir,children:[`来源:`,e.sourceDir]}),e.description&&(0,m.jsx)(`div`,{className:`settings-agent-desc`,children:e.description}),(0,m.jsxs)(`div`,{className:`settings-agent-footer`,children:[(0,m.jsx)(`span`,{className:`settings-agent-tools`,children:e.toolSummary}),e.model&&(0,m.jsxs)(`span`,{className:`settings-agent-model`,children:[e.model.provider,`/`,e.model.modelId]})]})]},`${e.sourceDir}-${e.id}`))})]}),(0,m.jsx)(`div`,{className:`picker-actions`,children:(0,m.jsx)(`button`,{type:`button`,className:`picker-cancel`,onClick:e.onClose,children:`完成`})})]})}function jn(e){return(0,m.jsx)(An,{context:e})}function Mn({context:e}){let[t,n]=(0,p.useState)(``),[r,i]=(0,p.useState)(``),[a,o]=(0,p.useState)(),s=e=>{try{return new RegExp(e,`i`),!1}catch{return!0}},c=s(t),l=s(r),u=e.modelFilterRules??[];return(0,m.jsxs)(`section`,{"data-model-rules":`1`,className:`settings-panel-container`,children:[(0,m.jsx)(`div`,{className:`settings-agents-header`,children:(0,m.jsxs)(`p`,{className:`settings-agents-desc`,children:[(0,m.jsx)(`strong`,{children:`按工作区约束可用模型。`}),`当工作区名称匹配指定正则表达式时,会话中仅可选择符合模型正则的模型(匹配模型名称或 `,(0,m.jsx)(`code`,{children:`provider/modelId`}),`)。多条命中规则必须全部满足。`]})}),(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsxs)(`h4`,{className:`settings-section-title`,children:[`已配置的过滤规则(共 `,u.length,` 条)`]}),u.length===0?(0,m.jsx)(`div`,{className:`settings-empty-hint`,children:`暂无模型过滤规则。所有工作区默认可使用全部已配置模型。`}):(0,m.jsx)(`div`,{className:`settings-dirs-list`,children:u.map(t=>{let r=a===t.id;return(0,m.jsxs)(`div`,{className:`settings-rule-card ${r?`editing`:``}`,children:[(0,m.jsx)(`div`,{className:`settings-rule-info`,children:(0,m.jsxs)(`div`,{className:`settings-rule-patterns`,children:[(0,m.jsxs)(`span`,{className:`settings-rule-pill`,children:[(0,m.jsx)(`span`,{className:`settings-rule-pill-tag`,children:`工作区`}),(0,m.jsx)(`code`,{className:`settings-rule-code`,title:t.workspacePattern,children:t.workspacePattern})]}),(0,m.jsx)(`span`,{className:`settings-rule-arrow`,"aria-hidden":`true`,children:`→`}),(0,m.jsxs)(`span`,{className:`settings-rule-pill`,children:[(0,m.jsx)(`span`,{className:`settings-rule-pill-tag`,children:`允许模型`}),(0,m.jsx)(`code`,{className:`settings-rule-code`,title:t.modelPattern,children:t.modelPattern})]})]})}),(0,m.jsxs)(`div`,{className:`settings-rule-actions`,children:[(0,m.jsx)(`button`,{type:`button`,className:`settings-rule-edit-btn`,onClick:()=>{o(t.id),n(t.workspacePattern),i(t.modelPattern)},children:r?`编辑中`:`编辑`}),(0,m.jsx)(`button`,{type:`button`,className:`settings-dir-remove-btn`,onClick:()=>{a===t.id&&(o(void 0),n(``),i(``)),e.onSetModelRules?.(u.filter(e=>e.id!==t.id))},children:`删除`})]})]},t.id)})})]}),(0,m.jsxs)(`section`,{className:`settings-section`,children:[(0,m.jsx)(`h4`,{className:`settings-section-title`,children:a?`编辑过滤规则`:`添加新规则`}),(0,m.jsxs)(`fieldset`,{disabled:e.pendingSettings,className:`model-rules-fields settings-rule-fieldset`,children:[(0,m.jsxs)(`div`,{className:`settings-rule-form-grid`,children:[(0,m.jsxs)(`label`,{className:`settings-rule-input-group`,children:[(0,m.jsx)(`span`,{className:`settings-rule-label-text`,children:`工作区名正则表达式`}),(0,m.jsx)(`input`,{type:`text`,"data-rule-workspace":`1`,className:`settings-dir-input`,value:t,"aria-invalid":c,placeholder:`如 ^proj- 或 my-workspace`,onChange:e=>n(e.target.value)})]}),(0,m.jsxs)(`label`,{className:`settings-rule-input-group`,children:[(0,m.jsx)(`span`,{className:`settings-rule-label-text`,children:`允许的模型名正则表达式`}),(0,m.jsx)(`input`,{type:`text`,"data-rule-model":`1`,className:`settings-dir-input`,value:r,"aria-invalid":l,placeholder:`如 anthropic/.* 或 gpt-4o|claude`,onChange:e=>i(e.target.value)})]})]}),(c||l)&&(0,m.jsx)(`div`,{className:`settings-dir-error`,role:`alert`,children:`⚠️ 正则表达式语法不合法,请检查后修正。`}),(0,m.jsxs)(`div`,{className:`settings-rule-form-buttons`,children:[(0,m.jsx)(`button`,{type:`button`,"data-rule-save":`1`,className:`settings-dir-add-btn`,disabled:!t.trim()||!r.trim()||c||l,onClick:()=>{let s={id:a??tn(),workspacePattern:t.trim(),modelPattern:r.trim()};e.onSetModelRules?.([...u.filter(e=>e.id!==s.id),s]),n(``),i(``),o(void 0)},children:a?`保存修改`:`添加规则`}),a&&(0,m.jsx)(`button`,{type:`button`,className:`settings-rule-cancel-btn`,onClick:()=>{o(void 0),n(``),i(``)},children:`取消编辑`})]})]})]}),(0,m.jsx)(`div`,{className:`picker-actions`,children:(0,m.jsx)(`button`,{type:`button`,className:`picker-cancel`,onClick:e.onClose,children:`完成`})})]})}var Nn=[{id:`appearance`,label:`外观`,render:kn},{id:`memory`,label:`主动记忆`,render:e=>(0,m.jsx)(qt,{workspaceId:e.workspaceId,onClose:e.onClose})},{id:`agents`,label:`智能体`,render:jn},{id:`model-rules`,label:`模型过滤`,render:e=>(0,m.jsx)(Mn,{context:e})}],Pn=Nn[0]?.id;function Fn({workspaceId:e,theme:t,onChooseTheme:n,onClose:r,agentCatalog:i,subagentCatalog:a,modelFilterRules:o,onSetModelRules:s,customAgentDirs:c,pendingSettings:l,onSetCustomAgentDirs:u,onRescanAgents:d}){let[f,h]=(0,p.useState)(Pn);(0,p.useEffect)(()=>{let e=e=>{e.key===`Escape`&&!e.defaultPrevented&&r()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[r]);let g=Nn.find(e=>e.id===f)??Nn[0];return(0,m.jsx)(`div`,{className:`overlay`,onClick:r,children:(0,m.jsxs)(`div`,{className:`picker settings-window`,"data-theme-dialog":`1`,"data-settings-window":`1`,onClick:e=>e.stopPropagation(),children:[(0,m.jsx)(`div`,{className:`settings-window-head`,children:(0,m.jsx)(`h2`,{children:`设置`})}),(0,m.jsxs)(`div`,{className:`settings-window-body`,children:[(0,m.jsxs)(`nav`,{className:`settings-nav`,role:`tablist`,"aria-orientation":`vertical`,"aria-label":`设置分类`,"data-settings-nav":`1`,children:[(0,m.jsx)(`div`,{className:`settings-nav-label`,children:`分类`}),Nn.map(e=>(0,m.jsx)(`button`,{type:`button`,id:`settings-tab-${e.id}`,className:`settings-category`,role:`tab`,"aria-selected":e.id===g?.id,"aria-controls":`settings-panel`,tabIndex:e.id===g?.id?0:-1,"data-settings-category":e.id,onClick:()=>h(e.id),children:e.label},e.id))]}),g&&(0,m.jsxs)(`div`,{className:`settings-panel`,id:`settings-panel`,role:`tabpanel`,"aria-labelledby":`settings-tab-${g.id}`,"data-settings-panel":g.id,children:[(0,m.jsx)(`h3`,{className:`settings-panel-title`,"data-settings-panel-title":g.id,children:g.label}),g.render({workspaceId:e,theme:t,onChooseTheme:n,onClose:r,agentCatalog:i,subagentCatalog:a,modelFilterRules:o,onSetModelRules:s,customAgentDirs:c,pendingSettings:l,onSetCustomAgentDirs:u,onRescanAgents:d})]})]})]})})}var In={char:` `,fg:null,bg:null,bold:!1,dim:!1,underline:!1,inverse:!1},Ln=[0,95,135,175,215,255];function Rn(e){if(e<16)return`var(--term-ansi-${e})`;if(e<232){let t=e-16;return`rgb(${Ln[Math.floor(t/36)%6]},${Ln[Math.floor(t/6)%6]},${Ln[t%6]})`}let t=8+(e-232)*10;return`rgb(${t},${t},${t})`}var zn=class{cols;rows;utf8;last;state=`ground`;params=``;intermediates=``;oscBuffer=``;screen;alt=null;cursorRow=0;cursorCol=0;savedRow=0;savedCol=0;fg=null;bg=null;bold=!1;dim=!1;underline=!1;inverse=!1;scrollTop=0;scrollBottom;autowrap=!0;wrapPending=!1;dirty=!0;constructor(e,t){this.cols=e,this.rows=t,this.cols=Un(e,20,500,80),this.rows=Un(t,5,200,24),this.scrollBottom=this.rows-1,this.screen=Vn(this.cols,this.rows),this.utf8=new Uint8Array,this.last=this.screen}write(e){let t=this.utf8.length?Hn(this.utf8,e):e,n=this.pendingByteCount(t);this.utf8=n?t.slice(t.length-n):new Uint8Array;let r=n?t.subarray(0,t.length-n):t,i=new TextDecoder(`utf-8`,{fatal:!1}).decode(r);for(let e of i)this.step(e);return this.dirty?this.snapshot():this.last}pendingByteCount(e){for(let t=1;t<=3&&t<=e.length;t++){let n=e[e.length-t];if((n&192)!=128)return(n<128?1:(n&224)==192?2:(n&240)==224?3:4)>t?t:0}return 0}snapshot(){return this.dirty=!1,this.last=this.screen.map(e=>e.map(e=>({...e}))),this.last}cell(e,t){let n=this.screen[e];if(!n)return{...In};let r=n[t];if(r)return r;for(;n.length<=t;)n.push({...In});return n[t]}put(e){this.wrapPending&&this.autowrap&&(this.cursorCol=0,this.lineFeed(),this.wrapPending=!1);let t=this.cell(this.cursorRow,this.cursorCol);t.char=e,t.fg=this.fg,t.bg=this.bg,t.bold=this.bold,t.dim=this.dim,t.underline=this.underline,t.inverse=this.inverse,this.cursorCol+1>=this.cols?this.wrapPending=!0:this.cursorCol+=1}lineFeed(){this.wrapPending=!1,this.cursorRow===this.scrollBottom?(this.screen.splice(this.scrollTop,1),this.screen.splice(this.scrollBottom,0,Bn(this.cols))):this.cursorRow<this.rows-1&&(this.cursorRow+=1),this.dirty=!0}carriageReturn(){this.cursorCol=0,this.wrapPending=!1,this.dirty=!0}clampCursor(){this.cursorRow=Math.max(0,Math.min(this.rows-1,this.cursorRow)),this.cursorCol=Math.max(0,Math.min(Math.max(0,this.cols-1),this.cursorCol))}resize(e,t){let n=Un(e,20,500,this.cols),r=Un(t,5,200,this.rows);if(n===this.cols&&r===this.rows)return;let i=[];for(let e=0;e<r;e++){let t=this.screen[e]??[],r=[];for(let e=0;e<n;e++)r.push(t[e]?{...t[e]}:{...In});i.push(r)}this.cols=n,this.rows=r,this.screen=i,this.alt=this.alt?this.alt.slice(0,r).map(e=>e.slice(0,n)):null,this.scrollTop=0,this.scrollBottom=r-1,this.cursorRow=Math.min(this.cursorRow,r-1),this.cursorCol=Math.min(this.cursorCol,n-1),this.dirty=!0}step(e){switch(this.state){case`ground`:return this.stepGround(e);case`escape`:return this.stepEscape(e);case`csi`:return this.stepCsi(e);case`osc`:return this.stepOsc(e);case`oscEscape`:return this.stepOscEscape(e)}}stepGround(e){let t=e.charCodeAt(0);if(e===`\x1B`)this.state=`escape`,this.params=``,this.intermediates=``;else switch(e){case`\r`:return this.carriageReturn();case`
|
|
50
50
|
`:case`\v`:case`\f`:return this.lineFeed();case`\b`:this.cursorCol=Math.max(0,this.cursorCol-1),this.wrapPending=!1,this.dirty=!0;return;case` `:{let e=Math.min(this.cols-1,(Math.floor(this.cursorCol/8)+1)*8);this.cursorCol=e,this.dirty=!0;return}case`\x07`:return;default:if(t<32||t===127)return;this.put(e),this.dirty=!0;return}}stepEscape(e){e===`\x1B`?(this.params=``,this.intermediates=``):e===`[`?(this.state=`csi`,this.params=``,this.intermediates=``):e===`]`||e===`P`||e===`^`||e===`_`||e===`X`?(this.state=`osc`,this.oscBuffer=``):e===`7`?(this.savedRow=this.cursorRow,this.savedCol=this.cursorCol,this.state=`ground`):e===`8`?(this.cursorRow=this.savedRow,this.cursorCol=this.savedCol,this.clampCursor(),this.state=`ground`):e===`c`?(this.screen=Vn(this.cols,this.rows),this.cursorRow=0,this.cursorCol=0,this.dirty=!0,this.state=`ground`):e===`D`?(this.lineFeed(),this.state=`ground`):e===`E`?(this.carriageReturn(),this.lineFeed(),this.state=`ground`):(e===`M`&&(this.cursorRow===this.scrollTop?(this.screen.splice(this.scrollBottom,1),this.screen.splice(this.scrollTop,0,Bn(this.cols))):this.cursorRow=Math.max(0,this.cursorRow-1),this.dirty=!0),this.state=`ground`)}stepCsi(e){let t=e.charCodeAt(0);t>=48&&t<=63?this.params+=e:t>=32&&t<=47?this.intermediates+=e:(this.state=`ground`,this.dispatchCsi(e,this.params,this.intermediates))}dispatchCsi(e,t,n){let r=t.startsWith(`?`),i=r?t.slice(1):t,a=i.length?i.split(`;`).map(e=>Number.parseInt(e===``?`0`:e,10)):[],o=(e,t)=>{let n=a[e];return typeof n==`number`&&Number.isFinite(n)?n:t},s=e=>a[e]===0?1:o(e,1);if(r){let t=o(0,0),n=e===`h`;if(t===1049||t===47||t===1047){this.switchAlternateScreen(n);return}if(t===25)return;if(t===7){this.autowrap=n;return}}else{switch(e){case`A`:this.cursorRow=Math.max(0,this.cursorRow-s(0)),this.wrapPending=!1;break;case`B`:this.cursorRow=Math.min(this.rows-1,this.cursorRow+s(0)),this.wrapPending=!1;break;case`C`:this.cursorCol=Math.min(this.cols-1,this.cursorCol+s(0)),this.wrapPending=!1;break;case`D`:this.cursorCol=Math.max(0,this.cursorCol-s(0)),this.wrapPending=!1;break;case`G`:this.cursorCol=Math.max(0,Math.min(this.cols-1,s(0)-1)),this.wrapPending=!1;break;case`H`:case`f`:this.cursorRow=Math.max(0,Math.min(this.rows-1,s(0)-1)),this.cursorCol=Math.max(0,Math.min(this.cols-1,s(1)-1)),this.wrapPending=!1;break;case`J`:this.eraseInDisplay(o(0,0));break;case`K`:this.eraseInLine(o(0,0));break;case`L`:this.insertLines(s(0));break;case`M`:this.deleteLines(s(0));break;case`P`:this.deleteCharacters(s(0));break;case`@`:this.insertCharacters(s(0));break;case`X`:{let e=Math.min(s(0),this.cols-this.cursorCol);for(let t=0;t<e;t++)this.cell(this.cursorRow,this.cursorCol+t).char=` `;break}case`d`:this.cursorRow=Math.max(0,Math.min(this.rows-1,s(0)-1));break;case`r`:{let e=Math.max(0,s(0)-1),t=Math.min(this.rows-1,o(1,this.rows)-1);e<t&&(this.scrollTop=e,this.scrollBottom=t),this.cursorRow=0,this.cursorCol=0;break}case`s`:this.savedRow=this.cursorRow,this.savedCol=this.cursorCol;break;case`u`:this.cursorRow=this.savedRow,this.cursorCol=this.savedCol;break;case`m`:this.selectGraphicRendition(a);return;default:return}this.clampCursor(),this.dirty=!0}}switchAlternateScreen(e){e&&!this.alt?(this.alt=this.screen,this.screen=Vn(this.cols,this.rows),this.cursorRow=0,this.cursorCol=0):!e&&this.alt&&(this.screen=this.alt,this.alt=null,this.cursorRow=this.savedRow,this.cursorCol=this.savedCol),this.clampCursor(),this.dirty=!0}eraseInDisplay(e){if(e===0){this.eraseInLine(0);for(let e=this.cursorRow+1;e<this.rows;e++)this.screen[e]=Bn(this.cols)}else if(e===1){this.eraseInLine(1);for(let e=0;e<this.cursorRow;e++)this.screen[e]=Bn(this.cols)}else this.screen=Vn(this.cols,this.rows);this.dirty=!0}eraseInLine(e){let t=this.screen[this.cursorRow];if(!t)return;let n=e===0?this.cursorCol:0,r=e===1?this.cursorCol:this.cols-1;for(let e=n;e<=r;e++)t[e]&&(t[e].char=` `);this.dirty=!0}insertLines(e){if(!(this.cursorRow<this.scrollTop||this.cursorRow>this.scrollBottom)){for(let t=0;t<e;t++)this.screen.splice(this.scrollBottom,1),this.screen.splice(this.cursorRow,0,Bn(this.cols));this.dirty=!0}}deleteLines(e){if(!(this.cursorRow<this.scrollTop||this.cursorRow>this.scrollBottom)){for(let t=0;t<e;t++)this.screen.splice(this.cursorRow,1),this.screen.splice(this.scrollBottom,0,Bn(this.cols));this.dirty=!0}}deleteCharacters(e){let t=this.screen[this.cursorRow];if(t){for(t.splice(this.cursorCol,e);t.length<this.cols;)t.push({...In});this.dirty=!0}}insertCharacters(e){let t=this.screen[this.cursorRow];if(t){for(let n=0;n<e;n++)t.splice(this.cursorCol,0,{...In});t.length=this.cols,this.dirty=!0}}selectGraphicRendition(e){if(!e.length)this.fg=null,this.bg=null,this.bold=!1,this.dim=!1,this.underline=!1,this.inverse=!1;else{for(let t=0;t<e.length;t++){let n=e[t];if(n===0)this.fg=null,this.bg=null,this.bold=!1,this.dim=!1,this.underline=!1,this.inverse=!1;else if(n===1)this.bold=!0;else if(n===2)this.dim=!0;else if(n===4)this.underline=!0;else if(n===7)this.inverse=!0;else if(n===22)this.bold=!1,this.dim=!1;else if(n===24)this.underline=!1;else if(n===27)this.inverse=!1;else if(n>=30&&n<=37)this.fg=`var(--term-ansi-${n-30})`;else if(n===39)this.fg=null;else if(n>=40&&n<=47)this.bg=`var(--term-ansi-${n-40})`;else if(n===49)this.bg=null;else if(n>=90&&n<=97)this.fg=`var(--term-ansi-${n-90+8})`;else if(n>=100&&n<=107)this.bg=`var(--term-ansi-${n-100+8})`;else if(n===38||n===48){let r=n===38?`fg`:`bg`;e[t+1]===5?(this[r]=Rn(e[t+2]??0),t+=2):e[t+1]===2&&(this[r]=`rgb(${e[t+2]??0},${e[t+3]??0},${e[t+4]??0})`,t+=4)}}this.dirty=!0}}stepOsc(e){e===`\x07`?this.state=`ground`:e===`\x1B`?this.state=`oscEscape`:this.oscBuffer.length<4096&&(this.oscBuffer+=e)}stepOscEscape(e){this.state=e===`\\`?`ground`:`osc`}cursor(){return{row:this.cursorRow,col:this.cursorCol}}toLines(){return this.screen.map(e=>e.slice(0,this.cols).map(e=>e.char).join(``).replace(/\s+$/,``))}};function Bn(e){let t=Array(e);for(let n=0;n<e;n++)t[n]={...In};return t}function Vn(e,t){let n=Array(t);for(let r=0;r<t;r++)n[r]=Bn(e);return n}function Hn(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}function Un(e,t,n,r){return Number.isFinite(e)?Math.min(n,Math.max(t,Math.floor(e))):r}var Wn=`terminal-right-rail`,Gn={checking:`检查中`,unavailable:`未启用`,starting:`启动中`,running:`运行中`,exited:`已结束`},Kn=5,qn=e=>`${Wn}-${e}`,Jn=e=>({id:qn(e),title:String(e),phase:`checking`});function Yn(e){let{key:t,ctrlKey:n,altKey:r,metaKey:i}=e;if(!i){if(n&&!r&&t.length===1){let e=t.toLowerCase().charCodeAt(0);if(e>=96&&e<=122)return String.fromCharCode(e-96);if(t===` `)return`\0`}if(r&&t.length===1)return`\x1b${t}`;switch(t){case`Enter`:return`\r`;case`Backspace`:return``;case`Tab`:return` `;case`Escape`:return`\x1B`;case`ArrowUp`:return`\x1B[A`;case`ArrowDown`:return`\x1B[B`;case`ArrowRight`:return`\x1B[C`;case`ArrowLeft`:return`\x1B[D`;case`Home`:return`\x1B[H`;case`End`:return`\x1B[F`;case`PageUp`:return`\x1B[5~`;case`PageDown`:return`\x1B[6~`;case`Delete`:return`\x1B[3~`;case`Insert`:return`\x1B[2~`;case`F1`:return`\x1BOP`;case`F2`:return`\x1BOQ`;case`F3`:return`\x1BOR`;case`F4`:return`\x1BOS`;case`F5`:return`\x1B[15~`;case`F6`:return`\x1B[17~`;case`F7`:return`\x1B[18~`;case`F8`:return`\x1B[19~`;case`F9`:return`\x1B[20~`;case`F10`:return`\x1B[21~`;case`F11`:return`\x1B[23~`;case`F12`:return`\x1B[24~`;default:return}}}function Xn(e){let t=[];for(let n of e){let e=t[t.length-1];e&&Zn(e.cell,n)?e.text+=n.char:t.push({text:n.char,cell:n})}return t}function Zn(e,t){return e.fg===t.fg&&e.bg===t.bg&&e.bold===t.bold&&e.dim===t.dim&&e.underline===t.underline&&e.inverse===t.inverse}function Qn({workspaceId:e,workspaceLabel:t,connected:n,sendCommand:r,registerSink:i}){let[a,o]=(0,p.useState)(()=>[Jn(1)]),[s,c]=(0,p.useState)(()=>qn(1)),l=(0,p.useRef)(new Set),u=(0,p.useRef)(!1),d=(0,p.useRef)(new Map),f=(0,p.useRef)(new Map),[h,g]=(0,p.useState)(()=>({grid:new zn(80,24).snapshot(),cursor:{row:0,col:0}})),_=a.find(e=>e.id===s)??a[0],v=(0,p.useRef)(s);v.current=s;let y=h.grid,b=h.cursor,x=_.phase,S=_.reason??``,C=_.exitCode,w=(0,p.useRef)(null),T=(0,p.useRef)({cols:80,rows:24,charWidth:9,lineHeight:16}),ee=(0,p.useRef)(null),E=(0,p.useCallback)(()=>{let e=w.current,t=ee.current;e&&t&&(t.value&&=``,t.focus(),document.activeElement!==t&&e.focus())},[]),te=(0,p.useCallback)(()=>{let e=ee.current;if(!e)return``;let t=e.value;return e.value=``,t},[]);(0,p.useEffect)(()=>{let e=!1;return fetch(`/api/terminal`).then(e=>e.json()).then(t=>{e||(t.enabled?(o(e=>e.map(e=>e.phase===`checking`?{...e,phase:`starting`}:e)),u.current=!0):o(e=>e.map(e=>({...e,phase:`unavailable`,reason:t.reason??`终端未启用。`}))))}).catch(()=>{e||o(e=>e.map(e=>({...e,phase:`unavailable`,reason:`无法读取终端状态,请确认服务端已启动。`})))}),()=>{e=!0}},[]);let ne=e=>{let t=new zn(T.current.cols,T.current.rows);d.current.set(e,t);let n={grid:t.snapshot(),cursor:{row:0,col:0}};f.current.set(e,n),v.current===e&&g(n)},re=(0,p.useCallback)(e=>{if(e.type===`terminal.output`){let t=d.current.get(e.sessionId);if(!t)return;let n={grid:t.write(new TextEncoder().encode(e.data)),cursor:t.cursor()};f.current.set(e.sessionId,n),v.current===e.sessionId&&g(n)}else e.type===`terminal.exit`?(l.current.delete(e.sessionId),ne(e.sessionId),o(t=>t.map(t=>t.id===e.sessionId?{...t,phase:`exited`,exitCode:e.exitCode}:t))):e.type===`terminal.error`?(l.current.delete(e.sessionId),ne(e.sessionId),o(t=>t.map(t=>t.id===e.sessionId?{...t,phase:`exited`,reason:e.message}:t))):e.type===`terminal.status`&&!e.enabled&&o(t=>t.map(t=>({...t,phase:`unavailable`,reason:e.reason??`终端未启用。`})))},[]),ie=(0,p.useRef)(i);ie.current=i;let ae=(0,p.useRef)(r);ae.current=r,(0,p.useEffect)(()=>(ie.current(re),()=>{ie.current(void 0)}),[re]),(0,p.useEffect)(()=>()=>{for(let e of l.current)ae.current({type:`terminal.close`,sessionId:e});l.current.clear()},[]);let oe=(0,p.useCallback)(t=>{if(!e)return;let n=new zn(T.current.cols,T.current.rows);d.current.set(t,n),f.current.set(t,{grid:n.snapshot(),cursor:n.cursor()}),g({grid:n.snapshot(),cursor:{row:0,col:0}}),o(e=>e.map(e=>e.id===t?{...e,phase:`starting`,exitCode:void 0,reason:``}:e)),E(),r({type:`terminal.open`,sessionId:t,workspaceId:e,cols:T.current.cols,rows:T.current.rows})?(l.current.add(t),o(e=>e.map(e=>e.id===t?{...e,phase:`running`}:e))):o(e=>e.map(e=>e.id===t?{...e,phase:`exited`,reason:`与 Super Pi 服务的连接尚未就绪。`}:e))},[E,r,e]);(0,p.useEffect)(()=>{if(u.current)for(let e of a)(e.phase===`starting`||e.phase===`checking`)&&!l.current.has(e.id)&&oe(e.id)},[a,oe]);let se=(0,p.useRef)(n);(0,p.useEffect)(()=>{let e=n&&!se.current;se.current=n,e&&o(e=>e.map(e=>e.phase===`exited`&&!e.deliberate?{...e,phase:`starting`,reason:``}:e))},[n]);let ce=(0,p.useCallback)(()=>{let e=new Set(a.map(e=>e.title)),t=1;for(;e.has(String(t));)t+=1;let n=Jn(t);o(e=>e.length>=Kn?e:[...e,n]),c(n.id),g(f.current.get(n.id)??{grid:new zn(T.current.cols,T.current.rows).snapshot(),cursor:{row:0,col:0}}),E()},[E,a]),le=(0,p.useCallback)(e=>{c(e);let t=f.current.get(e);t&&g(t),E()},[E]),ue=(0,p.useCallback)(e=>{r({type:`terminal.close`,sessionId:e}),l.current.delete(e),d.current.delete(e),f.current.delete(e),o(t=>{let n=t.findIndex(t=>t.id===e),r=t.filter(t=>t.id!==e);if(!r.length)return t;if(v.current===e){let e=r[Math.min(n,r.length-1)];c(e.id);let t=f.current.get(e.id);t&&g(t)}return r})},[r]);(0,p.useLayoutEffect)(()=>{let e=w.current;if(!e)return;let t=()=>{let t=e.querySelector(`[data-terminal-probe]`),n=t?.getBoundingClientRect().width||7.2,i=t?.getBoundingClientRect().height||16,a=getComputedStyle(e),o=e.clientWidth-parseFloat(a.paddingLeft)-parseFloat(a.paddingRight),s=e.clientHeight-parseFloat(a.paddingTop)-parseFloat(a.paddingBottom),c=Math.max(20,Math.min(500,Math.floor(o/n))),u=Math.max(5,Math.min(200,Math.floor(s/i)));if(c===T.current.cols&&u===T.current.rows&&n===T.current.charWidth&&i===T.current.lineHeight)return;T.current={cols:c,rows:u,charWidth:n,lineHeight:i};for(let[e,t]of d.current)t.resize(c,u),l.current.has(e)&&r({type:`terminal.resize`,sessionId:e,cols:c,rows:u});let f=v.current,p=d.current.get(f);p&&g({grid:p.snapshot(),cursor:p.cursor()})};t();let n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[r]);let de=e=>{if((e.ctrlKey||e.metaKey)&&(e.key===`c`||e.key===`v`))return;let t=Yn(e);t!==void 0&&(e.preventDefault(),r({type:`terminal.input`,sessionId:v.current,data:t}))},fe=()=>{let e=te();e&&r({type:`terminal.input`,sessionId:v.current,data:e})},pe=e=>{let t=e.clipboardData.getData(`text`);t&&(e.preventDefault(),r({type:`terminal.input`,sessionId:v.current,data:t.replace(/\r?\n/g,`\r`)}))},me=(0,p.useCallback)(()=>{let e=v.current;r({type:`terminal.close`,sessionId:e}),l.current.delete(e),o(t=>t.map(t=>t.id===e?{...t,phase:`exited`,deliberate:!0}:t))},[r]),he=(0,p.useMemo)(()=>y.map((e,t)=>({rowIndex:t,runs:Xn(e)})),[y]);return x===`checking`?(0,m.jsx)(`p`,{className:`rail-empty`,"data-terminal-phase":`checking`,children:`正在检查终端状态…`}):x===`unavailable`?(0,m.jsxs)(`div`,{className:`terminal-unavailable`,"data-terminal-phase":`unavailable`,children:[(0,m.jsx)(`p`,{className:`terminal-unavailable-reason`,children:S}),(0,m.jsx)(`p`,{className:`rail-empty`,children:`终端默认关闭,因为它会把服务器的 shell 暴露给能访问该端口的设备。开启后仅接受本机与局域网地址的连接,且工作目录限定为已配置的工作区。`})]}):(0,m.jsxs)(`div`,{className:`terminal-panel`,"data-terminal-panel":`1`,"data-terminal-phase":x,children:[(0,m.jsxs)(`div`,{className:`terminal-strip`,role:`tablist`,"aria-label":`终端会话`,"data-terminal-strip":`1`,children:[a.map(e=>(0,m.jsxs)(`div`,{className:`terminal-tab${e.id===s?` is-active`:``}`,children:[(0,m.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":e.id===s,className:`terminal-tab-btn`,"data-terminal-slot":e.id,onClick:()=>le(e.id),title:Gn[e.phase],children:[(0,m.jsx)(`span`,{className:`terminal-tab-dot terminal-tab-dot-${e.phase}`,"aria-hidden":`true`}),e.title]}),(0,m.jsx)(`button`,{type:`button`,className:`terminal-tab-close`,"aria-label":`关闭终端 ${e.title}`,"data-terminal-slot-close":e.id,onClick:()=>ue(e.id),children:`×`})]},e.id)),a.length<Kn&&(0,m.jsx)(`button`,{type:`button`,className:`terminal-strip-add`,"data-terminal-add":`1`,onClick:ce,title:`新建终端`,"aria-label":`新建终端`,children:`+`})]}),(0,m.jsxs)(`div`,{className:`terminal-toolbar`,children:[(0,m.jsxs)(`span`,{className:`terminal-status terminal-status-${x}`,"data-terminal-status":x,children:[(0,m.jsx)(`span`,{className:`terminal-status-dot`,"aria-hidden":`true`}),Gn[x]]}),(0,m.jsxs)(`span`,{className:`terminal-toolbar-right`,children:[t&&(0,m.jsx)(`span`,{className:`terminal-cwd`,"data-terminal-hint":`1`,title:t,children:t}),x===`running`?(0,m.jsx)(`button`,{type:`button`,className:`terminal-close-btn`,"data-terminal-close":`1`,title:`关闭这个终端会话`,"aria-label":`关闭这个终端会话`,onClick:me,children:`结束会话`}):(0,m.jsx)(`button`,{type:`button`,className:`terminal-restart-btn`,"data-terminal-restart":`1`,onClick:()=>oe(s),children:`重新打开`})]})]}),S&&(0,m.jsx)(`p`,{className:`tool-error`,"data-terminal-error":`1`,role:`alert`,children:S}),x===`exited`&&C!==void 0&&C!==0&&(0,m.jsxs)(`p`,{className:`tool-error`,"data-terminal-exit":`1`,children:[`会话已结束,退出码 `,C,`。`]}),(0,m.jsxs)(`div`,{className:`terminal-surface`,"data-terminal-surface":`1`,ref:w,tabIndex:0,role:`textbox`,"aria-label":`终端输出与输入`,"aria-multiline":`true`,onKeyDown:de,onPaste:pe,onMouseDown:e=>{e.preventDefault(),E()},children:[(0,m.jsx)(`textarea`,{ref:ee,className:`terminal-input-capture`,"aria-label":`终端输入`,spellCheck:!1,autoCapitalize:`off`,autoCorrect:`off`,rows:1,defaultValue:``,onChange:fe,onFocus:()=>w.current?.classList.add(`is-input-focused`),onBlur:()=>w.current?.classList.remove(`is-input-focused`)}),(0,m.jsx)(`span`,{className:`terminal-probe`,"data-terminal-probe":`1`,"aria-hidden":`true`,children:`M`}),(0,m.jsxs)(`div`,{className:`terminal-grid`,"data-terminal-grid":`1`,"aria-hidden":`true`,children:[he.map(({rowIndex:e,runs:t})=>(0,m.jsx)(`div`,{className:`terminal-row`,children:t.map((e,t)=>(0,m.jsx)(`span`,{className:[`terminal-cell`,e.cell.bold?`is-bold`:``,e.cell.dim?`is-dim`:``,e.cell.underline?`is-underline`:``,e.cell.inverse?`is-inverse`:``].filter(Boolean).join(` `),style:{...e.cell.fg?{color:e.cell.fg}:{},...e.cell.bg?{background:e.cell.bg}:{}},children:e.text},t))},e)),(0,m.jsx)(`span`,{className:`terminal-cursor`,style:{left:b.col*T.current.charWidth,top:b.row*T.current.lineHeight,width:T.current.charWidth,height:T.current.lineHeight},"aria-hidden":`true`})]})]})]})}var $n={workspaces:[],conversations:[],subagentRuns:[],queuedMessages:[]},er=e=>e.nativeEvent.isComposing||e.keyCode===229,tr=e=>{if(typeof e!=`string`||e.length===0)return``;let t=new Date(e);return Number.isNaN(t.getTime())?``:new Intl.DateTimeFormat(`zh-CN`,{hour:`2-digit`,minute:`2-digit`}).format(t)},nr=6e4,rr=60*nr,ir=24*rr,ar=7*ir,or=30*ir,sr=365*ir,cr=(e,t)=>{let n=new Date(e);if(Number.isNaN(n.getTime()))return``;let r=t-n.getTime();return r<3e4?`now`:r<rr?`${Math.max(1,Math.floor(r/nr))}m ago`:r<ir?`${Math.floor(r/rr)}h ago`:r<ar?`${Math.floor(r/ir)}d ago`:r<or?`${Math.floor(r/ar)}w ago`:r<sr?`${Math.floor(r/or)}mo ago`:`${Math.floor(r/sr)}y ago`},lr=(e,t)=>e.updatedAt<t.updatedAt?1:e.updatedAt>t.updatedAt?-1:0,ur=(e,t)=>{let n=e.archivedAt??``,r=t.archivedAt??``;return n<r?1:n>r?-1:0},dr=e=>{if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?``:`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`},fr=1e3,pr=3e4,mr=async e=>{try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}let t=document.createElement(`textarea`);t.value=e,t.setAttribute(`readonly`,``),t.style.cssText=`position:fixed;top:0;left:0;width:1px;height:1px;padding:0;border:0;opacity:0;pointer-events:none`,document.body.appendChild(t);try{return t.select(),t.setSelectionRange(0,t.value.length),document.execCommand(`copy`)}catch{return!1}finally{t.remove()}};function hr({workspace:e,x:t,y:n,notify:r,onClose:i}){let a=(0,p.useRef)(null),[o,s]=(0,p.useState)({left:t,top:n});(0,p.useLayoutEffect)(()=>{let e=a.current;if(!e)return;let r=e.getBoundingClientRect();s({left:Math.max(8,Math.min(t,window.innerWidth-r.width-8)),top:Math.max(8,Math.min(n,window.innerHeight-r.height-8))})},[t,n]),(0,p.useEffect)(()=>{let e=e=>{e.key===`Escape`&&(e.stopPropagation(),i())},t=e=>{a.current?.contains(e.target)||i()},n={x:window.scrollX,y:window.scrollY,width:window.innerWidth,height:window.innerHeight},r=()=>{(window.scrollX!==n.x||window.scrollY!==n.y)&&i()},o=()=>{(window.innerWidth!==n.width||window.innerHeight!==n.height)&&i()};return window.addEventListener(`keydown`,e,!0),window.addEventListener(`pointerdown`,t,!0),window.addEventListener(`scroll`,r,!0),window.addEventListener(`resize`,o),()=>{window.removeEventListener(`keydown`,e,!0),window.removeEventListener(`pointerdown`,t,!0),window.removeEventListener(`scroll`,i,!0),window.removeEventListener(`resize`,o)}},[i]);let c=async()=>{let t=await mr(e.path);i(),t?r(`已复制工作区路径:${e.path}`,`info`):r(`复制失败:浏览器拒绝了剪贴板写入,可以手动选中路径复制`,`error`)};return(0,m.jsxs)(`div`,{ref:a,className:`ctx-menu`,role:`menu`,"data-ctx-menu":`1`,"data-workspace-id":e.id,style:{left:o.left,top:o.top},onContextMenu:e=>e.preventDefault(),onPointerDown:e=>e.stopPropagation(),children:[(0,m.jsx)(`button`,{type:`button`,role:`menuitem`,className:`ctx-menu-item`,"data-copy-workspace-path":e.id,onClick:()=>void c(),children:`复制工作区路径`}),(0,m.jsx)(`div`,{className:`ctx-menu-hint`,"aria-hidden":`true`,children:e.path})]})}function gr({conversation:e,x:t,y:n,notify:r,onRename:i,onClose:a}){let o=(0,p.useRef)(null),[s,c]=(0,p.useState)({left:t,top:n});(0,p.useLayoutEffect)(()=>{let e=o.current;if(!e)return;let r=e.getBoundingClientRect();c({left:Math.max(8,Math.min(t,window.innerWidth-r.width-8)),top:Math.max(8,Math.min(n,window.innerHeight-r.height-8))})},[t,n]),(0,p.useEffect)(()=>{let e=e=>{e.key===`Escape`&&(e.stopPropagation(),a())},t=e=>{o.current?.contains(e.target)||a()},n={x:window.scrollX,y:window.scrollY,width:window.innerWidth,height:window.innerHeight},r=()=>{(window.scrollX!==n.x||window.scrollY!==n.y)&&a()},i=()=>{(window.innerWidth!==n.width||window.innerHeight!==n.height)&&a()};return window.addEventListener(`keydown`,e,!0),window.addEventListener(`pointerdown`,t,!0),window.addEventListener(`scroll`,r,!0),window.addEventListener(`resize`,i),()=>{window.removeEventListener(`keydown`,e,!0),window.removeEventListener(`pointerdown`,t,!0),window.removeEventListener(`scroll`,a,!0),window.removeEventListener(`resize`,i)}},[a]);let l=async()=>{let t=await mr(e.id);a(),t?r(`已复制会话 ID:${e.id}`,`info`):r(`复制失败:浏览器拒绝了剪贴板写入`,`error`)};return(0,m.jsxs)(`div`,{ref:o,className:`ctx-menu`,role:`menu`,"data-ctx-menu":`1`,"data-session-id":e.id,style:{left:s.left,top:s.top},onContextMenu:e=>e.preventDefault(),onPointerDown:e=>e.stopPropagation(),children:[(0,m.jsx)(`button`,{type:`button`,role:`menuitem`,className:`ctx-menu-item`,"data-copy-session-id":e.id,onClick:()=>void l(),children:`复制会话 ID`}),(0,m.jsx)(`button`,{type:`button`,role:`menuitem`,className:`ctx-menu-item`,"data-ai-rename-session":e.id,onClick:()=>{a(),i()},children:`AI 智能重命名`}),(0,m.jsx)(`div`,{className:`ctx-menu-hint`,"aria-hidden":`true`,children:e.id})]})}var _r={model:`模型`,thinking:`思考`,agent:`智能体`,subagent:`子智能体`},vr={model:`模型`,thinking:`思考等级`,agent:`智能体`,subagent:`子智能体`},yr={model:`选择模型`,thinking:`选择思考等级`,agent:`选择智能体`,subagent:`选择子智能体`},br=`图文`,xr=e=>e.imageInput?br:void 0,Sr=e=>e.normalize(`NFKD`).replace(/\p{M}/gu,``).toLowerCase(),Cr=(e,t)=>{let n=Sr(t.trim());return n?e.filter(e=>Sr(`${e.label} ${e.detail??``} ${e.badge??``}`).includes(n)):e};function wr({onClose:e,onCreate:t}){let[n,r]=(0,p.useState)(),[i,a]=(0,p.useState)(!0),[o,s]=(0,p.useState)(),[c,l]=(0,p.useState)(``),[u,d]=(0,p.useState)(``),f=async e=>{a(!0),s(void 0);try{let t=await fetch(`/api/fs/dirs${e?`?path=${encodeURIComponent(e)}`:``}`),n=await t.json();if(!t.ok)throw Error(n.error??`HTTP ${t.status}`);let i=n;r(i),d(i.path),l(i.suggestedName)}catch(e){s(e instanceof Error?e.message:`目录加载失败`)}finally{a(!1)}};(0,p.useEffect)(()=>{f()},[]),(0,p.useEffect)(()=>{let t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e]);let h=e=>{e?.preventDefault();let t=u.trim();t&&f(t)};return(0,m.jsx)(`div`,{className:`overlay`,onClick:e,children:(0,m.jsxs)(`div`,{className:`picker workspace-picker`,onClick:e=>e.stopPropagation(),children:[(0,m.jsx)(`h2`,{children:`选择工作区目录`}),(0,m.jsxs)(`form`,{className:`picker-path-bar`,onSubmit:h,children:[(0,m.jsx)(`input`,{className:`picker-path-input`,value:u,onChange:e=>d(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(er(e)?e.preventDefault():(e.preventDefault(),h()))},placeholder:`输入或粘贴目录绝对路径(如 D:\\projects 或 ~/code)`}),(0,m.jsx)(`button`,{type:`submit`,className:`picker-go-btn`,disabled:!u.trim()||i,children:`跳转`}),(0,m.jsx)(`button`,{type:`button`,className:`picker-up-btn`,disabled:!n?.parent||i,onClick:()=>n?.parent&&void f(n.parent),title:`返回上一级目录`,children:`上一级`})]}),n?.drives?.length||n?.homeDir?(0,m.jsxs)(`div`,{className:`picker-shortcuts`,children:[(0,m.jsx)(`span`,{className:`picker-shortcuts-label`,children:`快捷位置:`}),n?.homeDir&&(0,m.jsx)(`button`,{type:`button`,className:`picker-shortcut`,onClick:()=>void f(`~`),title:n.homeDir,children:`🏠 主目录`}),n?.drives?.map(e=>(0,m.jsx)(`button`,{type:`button`,className:`picker-shortcut`,onClick:()=>void f(e),children:e},e))]}):null,(0,m.jsxs)(`div`,{className:`picker-list`,children:[i&&(0,m.jsx)(`div`,{className:`picker-status`,children:`加载中…`}),!i&&o&&(0,m.jsxs)(`div`,{className:`picker-error`,children:[o,(0,m.jsx)(`button`,{onClick:()=>void f(n?.path||u),children:`重试`})]}),!i&&!o&&n?.entries.map(e=>(0,m.jsxs)(`button`,{className:`picker-dir`,onClick:()=>void f(e.path),children:[`📁 `,e.name]},e.path)),!i&&!o&&n&&n.entries.length===0&&(0,m.jsx)(`div`,{className:`picker-status`,children:`此目录下没有子目录`}),!i&&!o&&n?.truncated&&(0,m.jsx)(`div`,{className:`picker-status`,children:`目录过多,仅显示前 2000 项`})]}),(0,m.jsxs)(`label`,{className:`picker-name`,children:[`工作区名称`,(0,m.jsx)(`input`,{value:c,onChange:e=>l(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(er(e)?e.preventDefault():(e.preventDefault(),c.trim()&&n&&t(c.trim(),n.path)))},placeholder:`工作区名称`})]}),(0,m.jsxs)(`div`,{className:`picker-actions`,children:[(0,m.jsx)(`button`,{className:`picker-cancel`,onClick:e,children:`取消`}),(0,m.jsx)(`button`,{className:`picker-ok`,disabled:!c.trim()||i||!!o||!n,onClick:()=>n&&t(c.trim(),n.path),children:`使用这个目录`})]})]})})}var Tr={timeout:`扩展提问超时,已取消`,aborted:`运行已停止,扩展提问已取消`,expired:`运行已结束,扩展提问已取消`},Er=10;function Dr(e,t){if(!t)return`正在从 Pi 读取${e}列表…`;if(t.source!==`pi`)return`读取 Pi ${e}列表失败:${t.error??`未知原因`}`}function Or(e){if(!e)return`正在读取 agent 列表…`;if(e.source!==`directory`)return`读取 agent 列表失败:${e.error??`未知原因`}`;if(e.problems.length)return`${e.problems.length} 个 agent 文件无法使用:${e.problems.map(e=>e.file).join(`、`)}`;if(!e.agents.length)return`${e.directory} 下没有 primary agent`}var kr=e=>Math.abs(e)<1e3?String(e):`${(e/1e3).toFixed(1).replace(/\.0$/,``)}k`;function Ar(e){if(e===void 0||!Number.isFinite(e))return``;let t=Math.max(0,e);return t<1e3?`${Math.round(t)}ms`:t<6e4?`${(t/1e3).toFixed(1)}s`:`${Math.floor(t/6e4)}分${Math.round(t%6e4/1e3)}秒`}var jr={dispatch:`派发时(子进程还没起来)`,prompt:`派活时(Pi 拒收了任务)`,turn:`生成回答时`,tool:`调用工具时`,settle:`收尾时`};function Mr({call:e,index:t,expanded:n,onToggle:r}){let i=e.args??[];return(0,m.jsxs)(`div`,{className:`call-block call-block-${e.status??`running`}`,"data-call-block":t,"data-call-tool":e.label,"data-call-detail":e.detail??void 0,"data-call-status":e.status??`running`,"data-call-expanded":n?`true`:`false`,"data-call-arg-count":i.length,children:[(0,m.jsx)(`button`,{type:`button`,className:`call-fold-edge`,"data-call-fold-edge":t,"aria-expanded":n,"aria-label":`${n?`折叠`:`展开`} ${e.label} 调用`,title:n?`折叠这次调用`:`展开这次调用`,onClick:r}),(0,m.jsxs)(`div`,{className:`call-head-row`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`call-head`,"data-call-head":t,"aria-expanded":n,onClick:r,children:[(0,m.jsx)(`span`,{className:`call-chevron`,"aria-hidden":`true`,children:n?`▾`:`▸`}),(0,m.jsx)(`span`,{className:`call-glyph`,"aria-hidden":`true`,children:e.status===`error`?`✕`:e.status===`ok`?`✓`:`·`}),(0,m.jsx)(`span`,{className:`call-label`,title:e.label,children:e.label}),e.detail&&(0,m.jsx)(`span`,{className:`call-detail`,title:e.detail,children:e.detail}),e.durationMs!==void 0&&(0,m.jsx)(`span`,{className:`call-duration`,children:Ar(e.durationMs)}),e.preparing&&(0,m.jsx)(`span`,{className:`call-preparing`,"data-call-preparing":t,children:`生成参数中…`})]}),n&&(0,m.jsx)(`button`,{type:`button`,className:`call-fold-top`,"data-call-fold-top":t,onClick:r,children:`收起`})]}),!n&&e.live&&(0,m.jsx)(`div`,{className:`call-live-preview`,"data-call-live-preview":t,title:`展开查看完整输出`,children:e.live.split(`
|
|
51
|
-
`).slice(-1)[0]}),n&&(0,m.jsx)(`div`,{className:`call-args`,"data-call-args":i.length,children:i.length===0?(0,m.jsx)(`div`,{className:`call-arg call-arg-empty`,"data-call-arg-empty":t,children:`(这次调用没有可显示的参数)`}):i.map(e=>(0,m.jsxs)(`div`,{className:`call-arg`,"data-call-arg":e.key,"data-call-arg-value":e.value,children:[(0,m.jsx)(`span`,{className:`call-arg-key`,children:e.key}),(0,m.jsx)(`span`,{className:`call-arg-value`,title:e.value,children:e.value})]},e.key))}),n&&(e.result||e.live)&&(0,m.jsxs)(`div`,{className:`call-result`,"data-call-result":t,"data-call-result-state":e.result?`done`:`running`,children:[(0,m.jsxs)(`div`,{className:`call-result-head`,children:[(0,m.jsx)(`span`,{className:`call-result-title`,children:e.result?`执行结果`:`执行中 · 输出预览`}),e.result?(0,m.jsx)(Nr,{index:t,text:e.result.text}):null]}),(0,m.jsx)(`pre`,{className:`call-result-body`,"data-call-result-body":t,children:e.result?e.result.text:e.live}),e.result?.truncated&&(0,m.jsxs)(`div`,{className:`call-result-truncated`,children:[`(输出过长,已保留末尾关键内容`,e.result.droppedLines?`,省略前 ${e.result.droppedLines} 行`:``,`)`]})]})]})}function Nr({index:e,text:t}){let[n,r]=(0,p.useState)(!1);return(0,m.jsx)(`button`,{type:`button`,className:`call-result-copy`,"data-call-result-copy":e,onClick:async()=>{await mr(t)&&(r(!0),window.setTimeout(()=>r(!1),1600))},children:n?`已复制`:`复制`})}function Pr({messageId:e,nestedCount:t,preview:n,expanded:r,onToggle:i,children:a}){return(0,m.jsxs)(`section`,{className:`thinking-block`,"data-thinking-block":e,"data-thinking-expanded":r?`true`:`false`,"data-thinking-calls":t,children:[(0,m.jsx)(`button`,{type:`button`,className:`call-fold-edge`,"data-thinking-fold-edge":e,"aria-expanded":r,"aria-label":`${r?`折叠`:`展开`}这段思考`,title:r?`折叠这段思考`:`展开这段思考`,onClick:i}),(0,m.jsxs)(`button`,{type:`button`,className:`thinking-head`,"data-thinking-head":e,"aria-expanded":r,title:r?`折叠这段思考`:`展开这段思考`,onClick:i,children:[(0,m.jsx)(`span`,{className:`thinking-chevron`,"aria-hidden":`true`,children:r?`▾`:`▸`}),(0,m.jsx)(`span`,{className:`thinking-label`,children:`思考`}),t>0&&(0,m.jsxs)(`span`,{className:`thinking-count`,"data-thinking-count":t,children:[t,` 次工具调用`]}),!r&&n&&(0,m.jsx)(`span`,{className:`thinking-preview`,title:n,children:n})]}),r&&(0,m.jsx)(`div`,{className:`thinking-body`,"data-thinking-body":e,children:a})]})}function Fr({run:e,name:t,expanded:n,onToggle:r,onStop:i,stopping:a}){let o=e.toolCalls??[],s=n?o:o.slice(-10),c=o.length-s.length,l=e.status===`running`,u=e.output??``,d=e.dispatchedBy===`model`,[f,h]=(0,p.useState)(0);(0,p.useEffect)(()=>{if(!l)return;h(Date.now());let e=window.setInterval(()=>h(Date.now()),200);return()=>window.clearInterval(e)},[l,e.startedAt]);let g=Date.parse(e.startedAt),_=l&&f>0&&Number.isFinite(g)?f-g:void 0,v=[...o].reverse().find(e=>e.status===void 0)?.label;return(0,m.jsxs)(`article`,{className:`subagent-card subagent-${e.status}${d?` subagent-by-model`:``}`,"data-subagent-card":e.id,"data-subagent-status":e.status,"data-subagent-agent":e.agentId,"data-subagent-tools":o.length,"data-subagent-dispatched-by":d?`model`:`human`,children:[(0,m.jsxs)(`div`,{className:`subagent-head`,children:[(0,m.jsx)(`span`,{className:`subagent-badge`,children:`子智能体`}),d&&(0,m.jsxs)(`span`,{className:`subagent-source`,"data-subagent-source":`model`,title:`primary 模型自己决定派这个子智能体去干活`,children:[(0,m.jsx)(`span`,{className:`subagent-source-glyph`,"aria-hidden":`true`,children:`⚡`}),`模型自主派发`]}),(0,m.jsx)(`strong`,{className:`subagent-name`,"data-subagent-name":`1`,children:t||e.agentId}),(0,m.jsx)(`span`,{className:`subagent-status`,"data-subagent-status-text":`1`,children:l?`运行中`:e.status===`completed`?`已完成`:e.status===`stopped`?`已停止`:`失败`}),l?_!==void 0&&(0,m.jsxs)(`span`,{className:`subagent-clock`,"data-subagent-elapsed":`1`,"data-subagent-elapsed-ms":_,children:[`已运行 `,Ar(_)]}):e.durationMs!==void 0&&(0,m.jsxs)(`span`,{className:`subagent-duration`,"data-subagent-duration":`1`,"data-subagent-duration-ms":e.durationMs,children:[`用时 `,Ar(e.durationMs)]}),l&&(0,m.jsx)(`button`,{type:`button`,className:`subagent-stop`,"data-subagent-stop":e.id,disabled:a,onClick:i,children:`停止`})]}),l&&e.activity&&(0,m.jsxs)(`div`,{className:`subagent-activity`,"data-subagent-activity":e.activity.kind,"data-subagent-activity-at":e.activity.at,children:[(0,m.jsx)(`span`,{className:`subagent-activity-dot`,"aria-hidden":`true`}),e.activity.kind===`tool`?`正在调用 ${e.activity.label??`工具`}`:`正在思考…`]}),(0,m.jsxs)(`div`,{className:`subagent-task`,"data-subagent-task":`1`,children:[d&&(0,m.jsx)(`span`,{className:`subagent-task-source`,"data-subagent-model-task":`1`,children:`模型给的任务`}),e.task]}),(0,m.jsx)(`div`,{className:`subagent-output`,"data-subagent-output":`1`,"data-live-length":u.length,children:u||(l?`…`:e.outputTruncated?`(已按 50 KB 上限截断,浏览器仍收到完整内容)`:`(没有输出)`)}),e.failure&&(0,m.jsxs)(`div`,{className:`subagent-failure`,"data-subagent-failure":`1`,"data-subagent-failure-stage":e.failure.stage,children:[(0,m.jsx)(`span`,{className:`subagent-failure-label`,children:`卡在`}),(0,m.jsx)(`span`,{className:`subagent-failure-stage`,"data-subagent-failure-text":`1`,children:jr[e.failure.stage]}),e.failure.stage===`tool`&&v&&(0,m.jsxs)(`span`,{className:`subagent-failure-tool`,"data-subagent-failure-tool":`1`,children:[`· 正在跑 `,v]}),o.length>0&&(0,m.jsxs)(`span`,{className:`subagent-failure-progress`,children:[`· 死前已尝试 `,o.length,` 次工具调用`]})]}),e.error&&(0,m.jsx)(`div`,{className:`subagent-error`,"data-subagent-error":`1`,children:e.error}),o.length>0&&(0,m.jsxs)(`div`,{className:`subagent-tools`,"data-subagent-tool-count":o.length,children:[c>0&&!n&&(0,m.jsxs)(`button`,{type:`button`,className:`subagent-more`,"data-subagent-hidden":c,onClick:r,children:[`… 另有 `,c,` 条工具调用`]}),s.map((e,t)=>(0,m.jsxs)(`div`,{className:`subagent-tool${e.status?` subagent-tool-${e.status}`:``}`,"data-subagent-tool":e.label,"data-subagent-tool-detail":e.detail??void 0,"data-subagent-tool-status":e.status??`running`,children:[(0,m.jsx)(`span`,{className:`subagent-tool-glyph`,"aria-hidden":`true`,children:e.status===`error`?`✕`:e.status===`ok`?`✓`:`·`}),(0,m.jsx)(`span`,{className:`subagent-tool-label`,title:e.label,children:e.label}),e.detail&&(0,m.jsx)(`span`,{className:`subagent-tool-detail`,title:e.detail,children:e.detail}),e.durationMs!==void 0&&(0,m.jsx)(`span`,{className:`subagent-tool-duration`,children:Ar(e.durationMs)})]},`${t}:${e.label}`))]}),e.usage&&(0,m.jsxs)(`div`,{className:`subagent-usage`,"data-subagent-usage":`1`,"data-subagent-turns":e.usage.turns,children:[(0,m.jsxs)(`span`,{children:[e.usage.turns,` turns`]}),(0,m.jsxs)(`span`,{children:[`↑`,kr(e.usage.input)]}),(0,m.jsxs)(`span`,{children:[`↓`,kr(e.usage.output)]}),e.usage.cacheRead>0&&(0,m.jsxs)(`span`,{children:[`cache↓`,kr(e.usage.cacheRead)]}),e.usage.cacheWrite>0&&(0,m.jsxs)(`span`,{children:[`cache↑`,kr(e.usage.cacheWrite)]}),e.usage.cost>0&&(0,m.jsxs)(`span`,{children:[`$`,e.usage.cost.toFixed(4)]})]}),o.length>10&&(0,m.jsx)(`button`,{type:`button`,className:`subagent-collapse`,"data-subagent-collapse":e.id,"aria-expanded":n,onClick:r,children:n?`收起`:`展开全部 ${o.length} 条`})]})}function Ir({items:e,pi:t,running:n,onCancel:r,onSteer:i,onSendQueued:a}){let[o,s]=(0,p.useState)(!1);if(!e.length)return null;let c=e.filter(e=>e.state===`sending`);return(0,m.jsxs)(`section`,{className:`queue-dock`,"data-queue-dock":`1`,"data-queue-count":e.length,"data-queue-sending":c.length,"aria-label":`排队等待发送的消息`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`queue-dock-head`,"data-queue-collapse":`1`,"aria-expanded":!o,onClick:()=>s(e=>!e),children:[(0,m.jsx)(`span`,{className:`chevron`,children:o?`▸`:`▾`}),(0,m.jsxs)(`strong`,{children:[e.length,` 条待发送`]}),e.some(e=>e.priority)&&(0,m.jsx)(`span`,{className:`queue-dock-badge`,"data-queue-badge":`priority`,children:`下一轮优先发送`}),o&&(0,m.jsx)(`span`,{className:`queue-dock-preview`,children:e[0].content})]}),!o&&(0,m.jsx)(m.Fragment,{children:(0,m.jsx)(`ul`,{className:`queue-dock-list`,children:e.map((e,t)=>{let o=e.state===`sending`,s=!!e.priority,c=e.content||(e.images?.length?`【图片】(${e.images.length})`:``);return(0,m.jsxs)(`li`,{className:`queue-row ${o?`queue-row-sending`:`queue-row-queued`}`,"data-queue-id":e.id,"data-queue-state":e.state,children:[(0,m.jsx)(`span`,{className:`queue-index`,"aria-hidden":`true`,children:t+1}),(0,m.jsx)(`span`,{className:`queue-text`,title:c,children:c}),(0,m.jsx)(`span`,{className:`queue-state`,"data-queue-state-label":s?`priority`:o?`sending`:`queued`,children:s?`下一轮优先`:`待发送`}),o?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{className:`queue-locked`,"data-queue-locked":e.id,children:s?`当前轮结束后优先发送`:`等待当前轮结束后发送`}),(0,m.jsx)(`button`,{type:`button`,className:`queue-cancel queue-copy`,"data-queue-copy":e.id,onClick:()=>void navigator.clipboard?.writeText(e.content),children:`复制`})]}):(0,m.jsxs)(m.Fragment,{children:[n?s?(0,m.jsx)(`span`,{className:`queue-locked`,children:`等待当前轮结束`}):(0,m.jsx)(`button`,{type:`button`,className:`queue-steer`,"data-queue-steer":e.id,title:`优先发送:当前轮到达下一个工具批次边界后,这条消息最先开始下一轮`,"aria-label":`让「${c}」在下一轮优先发送`,onClick:()=>i(e.id),children:`优先发送`}):(0,m.jsx)(`button`,{type:`button`,className:`queue-steer`,"data-queue-send":e.id,title:`立即作为下一轮发送这条已保存的消息`,"aria-label":`发送「${c}」作为下一轮`,onClick:()=>a(e.id),children:s?`发送下一轮`:`立即发送`}),(0,m.jsx)(`button`,{type:`button`,className:`queue-cancel`,"data-queue-cancel":e.id,title:`取消这条排队消息,它不会被发出`,"aria-label":`取消排队消息「${c}」`,onClick:()=>r(e.id),children:`取消`}),(0,m.jsx)(`button`,{type:`button`,className:`queue-cancel queue-copy`,"data-queue-copy":e.id,onClick:()=>void navigator.clipboard?.writeText(e.content),children:`复制`})]})]},e.id)})})})]})}function Lr({question:e,index:t,expanded:n,onToggle:r,onAnswer:i}){return(0,m.jsxs)(`div`,{className:`call-block question-block-${e.status}`,"data-call-block":t,"data-call-tool":`question`,"data-call-detail":`提问`,"data-call-status":e.status===`answered`?`ok`:e.status===`cancelled`?`error`:`running`,"data-call-expanded":n?`true`:`false`,"data-question-block":t,children:[(0,m.jsx)(`button`,{type:`button`,className:`call-fold-edge`,"data-question-fold-edge":t,"aria-expanded":n,"aria-label":`${n?`折叠`:`展开`}提问`,title:n?`折叠这段提问`:`展开这段提问`,onClick:r}),(0,m.jsxs)(`div`,{className:`call-head-row`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`call-head`,"data-call-head":t,"aria-expanded":n,onClick:r,children:[(0,m.jsx)(`span`,{className:`call-chevron`,"aria-hidden":`true`,children:n?`▾`:`▸`}),(0,m.jsx)(`span`,{className:`call-glyph`,"aria-hidden":`true`,children:e.status===`answered`?`✓`:e.status===`cancelled`?`✕`:`?`}),(0,m.jsx)(`span`,{className:`call-label`,children:`提问`}),(0,m.jsxs)(`span`,{className:`call-detail`,children:[e.items.length,` 个问题`]})]}),n&&(0,m.jsx)(`button`,{type:`button`,className:`call-fold-top`,"data-call-fold-top":t,onClick:r,children:`收起`})]}),n&&(0,m.jsx)(`div`,{className:`question-body`,"data-question-body":t,children:(0,m.jsx)(Rr,{question:e,onAnswer:i})})]})}function Rr({question:e,onAnswer:t}){let[n,r]=(0,p.useState)(()=>Object.fromEntries((e.answers??[]).map(e=>[e.id,e.selected]))),[i,a]=(0,p.useState)(()=>e.answers?.map(e=>e.note??``).join(`
|
|
51
|
+
`).slice(-1)[0]}),n&&(0,m.jsx)(`div`,{className:`call-args`,"data-call-args":i.length,children:i.length===0?(0,m.jsx)(`div`,{className:`call-arg call-arg-empty`,"data-call-arg-empty":t,children:`(这次调用没有可显示的参数)`}):i.map(e=>(0,m.jsxs)(`div`,{className:`call-arg`,"data-call-arg":e.key,"data-call-arg-value":e.value,children:[(0,m.jsx)(`span`,{className:`call-arg-key`,children:e.key}),(0,m.jsx)(`span`,{className:`call-arg-value`,title:e.value,children:e.value})]},e.key))}),n&&(e.result||e.live)&&(0,m.jsxs)(`div`,{className:`call-result`,"data-call-result":t,"data-call-result-state":e.result?`done`:`running`,children:[(0,m.jsxs)(`div`,{className:`call-result-head`,children:[(0,m.jsx)(`span`,{className:`call-result-title`,children:e.result&&!e.live?`执行结果`:e.result?`执行结果 · 完整输出`:`执行中 · 输出预览`}),e.result?(0,m.jsx)(Nr,{index:t,text:e.live??e.result.text}):null]}),(0,m.jsx)(`pre`,{className:`call-result-body`,"data-call-result-body":t,children:e.live??e.result?.text}),e.result?.truncated&&e.live&&(0,m.jsx)(`div`,{className:`call-result-truncated`,children:`(服务端已截断到末尾 8 KB;上方显示的是执行中累积的完整输出)`}),e.result?.truncated&&!e.live&&(0,m.jsxs)(`div`,{className:`call-result-truncated`,children:[`(输出过长,已保留末尾关键内容`,e.result.droppedLines?`,省略前 ${e.result.droppedLines} 行`:``,`)`]})]})]})}function Nr({index:e,text:t}){let[n,r]=(0,p.useState)(!1);return(0,m.jsx)(`button`,{type:`button`,className:`call-result-copy`,"data-call-result-copy":e,onClick:async()=>{await mr(t)&&(r(!0),window.setTimeout(()=>r(!1),1600))},children:n?`已复制`:`复制`})}function Pr({messageId:e,nestedCount:t,preview:n,expanded:r,onToggle:i,children:a}){return(0,m.jsxs)(`section`,{className:`thinking-block`,"data-thinking-block":e,"data-thinking-expanded":r?`true`:`false`,"data-thinking-calls":t,children:[(0,m.jsx)(`button`,{type:`button`,className:`call-fold-edge`,"data-thinking-fold-edge":e,"aria-expanded":r,"aria-label":`${r?`折叠`:`展开`}这段思考`,title:r?`折叠这段思考`:`展开这段思考`,onClick:i}),(0,m.jsxs)(`button`,{type:`button`,className:`thinking-head`,"data-thinking-head":e,"aria-expanded":r,title:r?`折叠这段思考`:`展开这段思考`,onClick:i,children:[(0,m.jsx)(`span`,{className:`thinking-chevron`,"aria-hidden":`true`,children:r?`▾`:`▸`}),(0,m.jsx)(`span`,{className:`thinking-label`,children:`思考`}),t>0&&(0,m.jsxs)(`span`,{className:`thinking-count`,"data-thinking-count":t,children:[t,` 次工具调用`]}),!r&&n&&(0,m.jsx)(`span`,{className:`thinking-preview`,title:n,children:n})]}),r&&(0,m.jsx)(`div`,{className:`thinking-body`,"data-thinking-body":e,children:a})]})}function Fr({run:e,name:t,expanded:n,onToggle:r,onStop:i,stopping:a}){let o=e.toolCalls??[],s=n?o:o.slice(-10),c=o.length-s.length,l=e.status===`running`,u=e.output??``,d=e.dispatchedBy===`model`,[f,h]=(0,p.useState)(0);(0,p.useEffect)(()=>{if(!l)return;h(Date.now());let e=window.setInterval(()=>h(Date.now()),200);return()=>window.clearInterval(e)},[l,e.startedAt]);let g=Date.parse(e.startedAt),_=l&&f>0&&Number.isFinite(g)?f-g:void 0,v=[...o].reverse().find(e=>e.status===void 0)?.label;return(0,m.jsxs)(`article`,{className:`subagent-card subagent-${e.status}${d?` subagent-by-model`:``}`,"data-subagent-card":e.id,"data-subagent-status":e.status,"data-subagent-agent":e.agentId,"data-subagent-tools":o.length,"data-subagent-dispatched-by":d?`model`:`human`,children:[(0,m.jsxs)(`div`,{className:`subagent-head`,children:[(0,m.jsx)(`span`,{className:`subagent-badge`,children:`子智能体`}),d&&(0,m.jsxs)(`span`,{className:`subagent-source`,"data-subagent-source":`model`,title:`primary 模型自己决定派这个子智能体去干活`,children:[(0,m.jsx)(`span`,{className:`subagent-source-glyph`,"aria-hidden":`true`,children:`⚡`}),`模型自主派发`]}),(0,m.jsx)(`strong`,{className:`subagent-name`,"data-subagent-name":`1`,children:t||e.agentId}),(0,m.jsx)(`span`,{className:`subagent-status`,"data-subagent-status-text":`1`,children:l?`运行中`:e.status===`completed`?`已完成`:e.status===`stopped`?`已停止`:`失败`}),l?_!==void 0&&(0,m.jsxs)(`span`,{className:`subagent-clock`,"data-subagent-elapsed":`1`,"data-subagent-elapsed-ms":_,children:[`已运行 `,Ar(_)]}):e.durationMs!==void 0&&(0,m.jsxs)(`span`,{className:`subagent-duration`,"data-subagent-duration":`1`,"data-subagent-duration-ms":e.durationMs,children:[`用时 `,Ar(e.durationMs)]}),l&&(0,m.jsx)(`button`,{type:`button`,className:`subagent-stop`,"data-subagent-stop":e.id,disabled:a,onClick:i,children:`停止`})]}),l&&e.activity&&(0,m.jsxs)(`div`,{className:`subagent-activity`,"data-subagent-activity":e.activity.kind,"data-subagent-activity-at":e.activity.at,children:[(0,m.jsx)(`span`,{className:`subagent-activity-dot`,"aria-hidden":`true`}),e.activity.kind===`tool`?`正在调用 ${e.activity.label??`工具`}`:`正在思考…`]}),(0,m.jsxs)(`div`,{className:`subagent-task`,"data-subagent-task":`1`,children:[d&&(0,m.jsx)(`span`,{className:`subagent-task-source`,"data-subagent-model-task":`1`,children:`模型给的任务`}),e.task]}),(0,m.jsx)(`div`,{className:`subagent-output`,"data-subagent-output":`1`,"data-live-length":u.length,children:u||(l?`…`:e.outputTruncated?`(已按 50 KB 上限截断,浏览器仍收到完整内容)`:`(没有输出)`)}),e.failure&&(0,m.jsxs)(`div`,{className:`subagent-failure`,"data-subagent-failure":`1`,"data-subagent-failure-stage":e.failure.stage,children:[(0,m.jsx)(`span`,{className:`subagent-failure-label`,children:`卡在`}),(0,m.jsx)(`span`,{className:`subagent-failure-stage`,"data-subagent-failure-text":`1`,children:jr[e.failure.stage]}),e.failure.stage===`tool`&&v&&(0,m.jsxs)(`span`,{className:`subagent-failure-tool`,"data-subagent-failure-tool":`1`,children:[`· 正在跑 `,v]}),o.length>0&&(0,m.jsxs)(`span`,{className:`subagent-failure-progress`,children:[`· 死前已尝试 `,o.length,` 次工具调用`]})]}),e.error&&(0,m.jsx)(`div`,{className:`subagent-error`,"data-subagent-error":`1`,children:e.error}),o.length>0&&(0,m.jsxs)(`div`,{className:`subagent-tools`,"data-subagent-tool-count":o.length,children:[c>0&&!n&&(0,m.jsxs)(`button`,{type:`button`,className:`subagent-more`,"data-subagent-hidden":c,onClick:r,children:[`… 另有 `,c,` 条工具调用`]}),s.map((e,t)=>(0,m.jsxs)(`div`,{className:`subagent-tool${e.status?` subagent-tool-${e.status}`:``}`,"data-subagent-tool":e.label,"data-subagent-tool-detail":e.detail??void 0,"data-subagent-tool-status":e.status??`running`,children:[(0,m.jsx)(`span`,{className:`subagent-tool-glyph`,"aria-hidden":`true`,children:e.status===`error`?`✕`:e.status===`ok`?`✓`:`·`}),(0,m.jsx)(`span`,{className:`subagent-tool-label`,title:e.label,children:e.label}),e.detail&&(0,m.jsx)(`span`,{className:`subagent-tool-detail`,title:e.detail,children:e.detail}),e.durationMs!==void 0&&(0,m.jsx)(`span`,{className:`subagent-tool-duration`,children:Ar(e.durationMs)})]},`${t}:${e.label}`))]}),e.usage&&(0,m.jsxs)(`div`,{className:`subagent-usage`,"data-subagent-usage":`1`,"data-subagent-turns":e.usage.turns,children:[(0,m.jsxs)(`span`,{children:[e.usage.turns,` turns`]}),(0,m.jsxs)(`span`,{children:[`↑`,kr(e.usage.input)]}),(0,m.jsxs)(`span`,{children:[`↓`,kr(e.usage.output)]}),e.usage.cacheRead>0&&(0,m.jsxs)(`span`,{children:[`cache↓`,kr(e.usage.cacheRead)]}),e.usage.cacheWrite>0&&(0,m.jsxs)(`span`,{children:[`cache↑`,kr(e.usage.cacheWrite)]}),e.usage.cost>0&&(0,m.jsxs)(`span`,{children:[`$`,e.usage.cost.toFixed(4)]})]}),o.length>10&&(0,m.jsx)(`button`,{type:`button`,className:`subagent-collapse`,"data-subagent-collapse":e.id,"aria-expanded":n,onClick:r,children:n?`收起`:`展开全部 ${o.length} 条`})]})}function Ir({items:e,pi:t,running:n,onCancel:r,onSteer:i,onSendQueued:a}){let[o,s]=(0,p.useState)(!1);if(!e.length)return null;let c=e.filter(e=>e.state===`sending`);return(0,m.jsxs)(`section`,{className:`queue-dock`,"data-queue-dock":`1`,"data-queue-count":e.length,"data-queue-sending":c.length,"aria-label":`排队等待发送的消息`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`queue-dock-head`,"data-queue-collapse":`1`,"aria-expanded":!o,onClick:()=>s(e=>!e),children:[(0,m.jsx)(`span`,{className:`chevron`,children:o?`▸`:`▾`}),(0,m.jsxs)(`strong`,{children:[e.length,` 条待发送`]}),e.some(e=>e.priority)&&(0,m.jsx)(`span`,{className:`queue-dock-badge`,"data-queue-badge":`priority`,children:`下一轮优先发送`}),o&&(0,m.jsx)(`span`,{className:`queue-dock-preview`,children:e[0].content})]}),!o&&(0,m.jsx)(m.Fragment,{children:(0,m.jsx)(`ul`,{className:`queue-dock-list`,children:e.map((e,t)=>{let o=e.state===`sending`,s=!!e.priority,c=e.content||(e.images?.length?`【图片】(${e.images.length})`:``);return(0,m.jsxs)(`li`,{className:`queue-row ${o?`queue-row-sending`:`queue-row-queued`}`,"data-queue-id":e.id,"data-queue-state":e.state,children:[(0,m.jsx)(`span`,{className:`queue-index`,"aria-hidden":`true`,children:t+1}),(0,m.jsx)(`span`,{className:`queue-text`,title:c,children:c}),(0,m.jsx)(`span`,{className:`queue-state`,"data-queue-state-label":s?`priority`:o?`sending`:`queued`,children:s?`下一轮优先`:`待发送`}),o?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{className:`queue-locked`,"data-queue-locked":e.id,children:s?`当前轮结束后优先发送`:`等待当前轮结束后发送`}),(0,m.jsx)(`button`,{type:`button`,className:`queue-cancel queue-copy`,"data-queue-copy":e.id,onClick:()=>void navigator.clipboard?.writeText(e.content),children:`复制`})]}):(0,m.jsxs)(m.Fragment,{children:[n?s?(0,m.jsx)(`span`,{className:`queue-locked`,children:`等待当前轮结束`}):(0,m.jsx)(`button`,{type:`button`,className:`queue-steer`,"data-queue-steer":e.id,title:`优先发送:当前轮到达下一个工具批次边界后,这条消息最先开始下一轮`,"aria-label":`让「${c}」在下一轮优先发送`,onClick:()=>i(e.id),children:`优先发送`}):(0,m.jsx)(`button`,{type:`button`,className:`queue-steer`,"data-queue-send":e.id,title:`立即作为下一轮发送这条已保存的消息`,"aria-label":`发送「${c}」作为下一轮`,onClick:()=>a(e.id),children:s?`发送下一轮`:`立即发送`}),(0,m.jsx)(`button`,{type:`button`,className:`queue-cancel`,"data-queue-cancel":e.id,title:`取消这条排队消息,它不会被发出`,"aria-label":`取消排队消息「${c}」`,onClick:()=>r(e.id),children:`取消`}),(0,m.jsx)(`button`,{type:`button`,className:`queue-cancel queue-copy`,"data-queue-copy":e.id,onClick:()=>void navigator.clipboard?.writeText(e.content),children:`复制`})]})]},e.id)})})})]})}function Lr({question:e,index:t,expanded:n,onToggle:r,onAnswer:i}){return(0,m.jsxs)(`div`,{className:`call-block question-block-${e.status}`,"data-call-block":t,"data-call-tool":`question`,"data-call-detail":`提问`,"data-call-status":e.status===`answered`?`ok`:e.status===`cancelled`?`error`:`running`,"data-call-expanded":n?`true`:`false`,"data-question-block":t,children:[(0,m.jsx)(`button`,{type:`button`,className:`call-fold-edge`,"data-question-fold-edge":t,"aria-expanded":n,"aria-label":`${n?`折叠`:`展开`}提问`,title:n?`折叠这段提问`:`展开这段提问`,onClick:r}),(0,m.jsxs)(`div`,{className:`call-head-row`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`call-head`,"data-call-head":t,"aria-expanded":n,onClick:r,children:[(0,m.jsx)(`span`,{className:`call-chevron`,"aria-hidden":`true`,children:n?`▾`:`▸`}),(0,m.jsx)(`span`,{className:`call-glyph`,"aria-hidden":`true`,children:e.status===`answered`?`✓`:e.status===`cancelled`?`✕`:`?`}),(0,m.jsx)(`span`,{className:`call-label`,children:`提问`}),(0,m.jsxs)(`span`,{className:`call-detail`,children:[e.items.length,` 个问题`]})]}),n&&(0,m.jsx)(`button`,{type:`button`,className:`call-fold-top`,"data-call-fold-top":t,onClick:r,children:`收起`})]}),n&&(0,m.jsx)(`div`,{className:`question-body`,"data-question-body":t,children:(0,m.jsx)(Rr,{question:e,onAnswer:i})})]})}function Rr({question:e,onAnswer:t}){let[n,r]=(0,p.useState)(()=>Object.fromEntries((e.answers??[]).map(e=>[e.id,e.selected]))),[i,a]=(0,p.useState)(()=>e.answers?.map(e=>e.note??``).join(`
|
|
52
52
|
`)??``),o=(e,t,n)=>{r(r=>{let i=r[e]??[];return n?{...r,[e]:i.includes(t)?i.filter(e=>e!==t):[...i,t]}:{...r,[e]:[t]}})},s=()=>{t(e.items.map(e=>({id:e.id,selected:n[e.id]??[],...e.extraNote&&i.trim()?{note:i.trim()}:{}})),!1)},c=e.items.some(e=>(n[e.id]??[]).length>0);return(0,m.jsxs)(`div`,{className:`question-block question-${e.status}`,"data-question-status":e.status,children:[e.items.map(t=>(0,m.jsxs)(`div`,{className:`question-item`,children:[(0,m.jsx)(`div`,{className:`question-text`,children:t.header?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{className:`question-header`,children:t.header}),(0,m.jsx)(`span`,{className:`question-sep`,children:` · `}),(0,m.jsx)(qe,{source:t.question})]}):(0,m.jsx)(qe,{source:t.question})}),(0,m.jsx)(`div`,{className:`question-options`,"data-question-options":t.id,children:t.options.map(r=>{let i=(n[t.id]??[]).includes(r),a=e.status!==`pending`;return(0,m.jsxs)(`label`,{className:i?`is-chosen`:``,"data-chosen":a&&i?`1`:void 0,children:[(0,m.jsx)(`input`,{type:t.multiple?`checkbox`:`radio`,name:`q-${t.id}`,checked:i,disabled:a,onChange:()=>o(t.id,r,t.multiple)}),(0,m.jsx)(Je,{source:r}),a&&i?(0,m.jsx)(`span`,{className:`question-mark`,"aria-label":`已选择`,children:`✓`}):null]},r)})}),e.status===`pending`&&t.extraNote?(0,m.jsx)(`textarea`,{value:i,placeholder:`补充说明(可选)`,onChange:e=>a(e.target.value)}):e.status===`answered`&&(e.answers??[]).some(e=>e.note)?(0,m.jsxs)(`div`,{className:`question-summary`,"data-question-summary":`1`,children:[`补充:`,(e.answers??[]).map(e=>e.note).filter(Boolean).join(`;`)]}):null,e.status===`cancelled`&&(0,m.jsx)(`div`,{className:`question-summary`,"data-question-summary":`1`,children:`已取消,没有作答。`})]},t.id)),e.status===`pending`&&(0,m.jsxs)(`div`,{className:`question-actions`,children:[(0,m.jsx)(`button`,{type:`button`,onClick:s,disabled:!c,children:`提交`}),(0,m.jsx)(`button`,{type:`button`,className:`question-skip`,onClick:()=>t([],!0),children:`跳过`})]})]})}function zr({request:e,onAnswer:t,pending:n}){let[r,i]=(0,p.useState)(e.prefill??``),a=e.method===`input`||e.method===`editor`,o=(0,m.jsx)(`button`,{type:`button`,className:`extui-cancel`,onClick:()=>t({cancelled:!0}),children:`取消提问`});return(0,m.jsxs)(`article`,{className:`extui-card extui-${e.method}`,"data-request-id":e.requestId,"data-method":e.method,children:[(0,m.jsxs)(`div`,{className:`extui-head`,children:[(0,m.jsx)(`span`,{className:`extui-badge`,children:`扩展提问`}),e.timeoutMs!==void 0&&(0,m.jsxs)(`span`,{className:`extui-deadline`,children:[Math.round(e.timeoutMs/1e3),`s 超时`]})]}),n&&(0,m.jsx)(`p`,{role:`status`,children:`提交中…`}),(0,m.jsxs)(`fieldset`,{disabled:n,style:{border:0,padding:0,margin:0},children:[(0,m.jsx)(`h3`,{className:`extui-title`,children:e.title||e.method}),e.method===`confirm`&&(0,m.jsx)(`p`,{className:`extui-body`,children:e.message}),e.method===`select`&&(0,m.jsxs)(`div`,{className:`extui-options`,children:[(e.options??[]).map(e=>(0,m.jsx)(`button`,{type:`button`,className:`extui-option`,onClick:()=>t({value:e}),children:e},e)),(e.options??[]).length===0&&(0,m.jsx)(`p`,{className:`extui-body`,children:`扩展没有提供任何选项`})]}),a&&(0,m.jsxs)(`form`,{className:`extui-form`,onSubmit:e=>{e.preventDefault(),!n&&r.trim()&&t({value:r})},children:[e.method===`input`?(0,m.jsx)(`input`,{className:`extui-field`,value:r,onChange:e=>i(e.target.value),onKeyDown:e=>{e.key===`Enter`&&er(e)&&e.preventDefault()},placeholder:e.placeholder??``}):(0,m.jsx)(`textarea`,{className:`extui-field`,value:r,onChange:e=>i(e.target.value),onKeyDown:e=>{e.key===`Enter`&&er(e)&&e.preventDefault()}}),(0,m.jsxs)(`div`,{className:`extui-actions`,children:[(0,m.jsx)(`button`,{type:`submit`,className:`extui-primary`,disabled:!r.trim(),children:`提交`}),o]})]}),!a&&(0,m.jsxs)(`div`,{className:`extui-actions`,children:[e.method===`confirm`&&(0,m.jsx)(`button`,{type:`button`,className:`extui-primary`,onClick:()=>t({confirmed:!0}),children:`确认`}),e.method===`confirm`&&(0,m.jsx)(`button`,{type:`button`,className:`extui-no`,onClick:()=>t({confirmed:!1}),children:`拒绝`}),o]})]})]})}function Br({initial:e,label:t,onCommit:n,onClose:r}){let[i,a]=(0,p.useState)(e),o=(0,p.useRef)(null),s=(0,p.useRef)(!1);(0,p.useEffect)(()=>{o.current?.focus(),o.current?.select()},[]);let c=!i.trim(),l=()=>{s.current=!0,r()},u=()=>{if(c)return;let t=i.trim();(t===e||n(t))&&l()};return(0,m.jsxs)(`div`,{className:`inline-edit`,"data-editing":`1`,children:[(0,m.jsx)(`input`,{ref:o,className:`inline-edit-input`,value:i,"aria-label":t,onChange:e=>a(e.target.value),onKeyDown:e=>{if(e.key===`Enter`){if(er(e))return;e.preventDefault(),u()}else e.key===`Escape`&&(e.preventDefault(),l())},onBlur:()=>{s.current||r()}}),(0,m.jsx)(`button`,{type:`button`,className:`inline-edit-ok`,title:`确认重命名`,"aria-label":`确认重命名`,disabled:c,onMouseDown:e=>e.preventDefault(),onClick:u,children:`✓`}),(0,m.jsx)(`button`,{type:`button`,className:`inline-edit-cancel`,title:`取消重命名`,"aria-label":`取消重命名`,onMouseDown:e=>e.preventDefault(),onClick:l,children:`✗`})]})}function Vr({kind:e,label:t,value:n,detail:r,options:i,disabled:a,note:o,onChoose:s,scope:c}){let[l,u]=(0,p.useState)(!1),[d,f]=(0,p.useState)(``),[h,g]=(0,p.useState)(0),_=(0,p.useRef)(null),v=(0,p.useRef)(null),y=(0,p.useRef)(null),b=(0,p.useRef)(null),x=(0,p.useRef)([]),S=i.find(e=>e.selected),C=Cr(i,d),w=C.length===0?-1:Math.min(Math.max(h,0),C.length-1),T=w<0?void 0:C[w],ee=(e=!1)=>{u(!1),e&&v.current?.focus()},E=()=>{f(``),g(Math.max(i.findIndex(e=>e.selected),0)),u(!0)},te=e=>g(t=>C.length?Math.min(Math.max(t+e,0),C.length-1):0);(0,p.useEffect)(()=>{if(!l)return;let e=e=>{_.current?.contains(e.target)||ee()};return window.addEventListener(`mousedown`,e),()=>window.removeEventListener(`mousedown`,e)},[l]),(0,p.useEffect)(()=>{if(!l)return;let e=_.current,t=t=>{e?.contains(t.relatedTarget)||ee()};return e?.addEventListener(`focusout`,t),()=>e?.removeEventListener(`focusout`,t)},[l]),(0,p.useEffect)(()=>{l&&b.current?.focus()},[l]),(0,p.useEffect)(()=>{l&&w>=0&&x.current[w]?.scrollIntoView({block:`nearest`})},[l,w]),(0,p.useLayoutEffect)(()=>{if(!l)return;let e=y.current;if(!e)return;e.style.setProperty(`--picker-nudge`,`0px`),e.style.setProperty(`--picker-drop`,`0px`);let t=e.getBoundingClientRect(),n=Math.min(window.innerWidth-8-t.right,Math.max(8-t.left,0)),r=Math.min(window.innerHeight-8-t.bottom,Math.max(8-t.top,0));e.style.setProperty(`--picker-nudge`,`${n}px`),e.style.setProperty(`--picker-drop`,`${r}px`)},[l,C.length,i.length]);let ne=e=>{if(l){if(e.key===`Escape`)e.preventDefault(),ee(!0);else if(e.key===`ArrowDown`)e.preventDefault(),te(1);else if(e.key===`ArrowUp`)e.preventDefault(),te(-1);else if(e.key===`Home`)e.preventDefault(),g(0);else if(e.key===`End`)e.preventDefault(),g(Math.max(C.length-1,0));else if(e.key===`Enter`){if(er(e))return;e.preventDefault(),T&&(s(T.key),ee(!0))}}},re=`picker-list-${c??e}`,ie=t=>`picker-option-${c??e}-${t}`;return(0,m.jsxs)(`div`,{className:`session-picker-item session-picker-${e}`,ref:_,onKeyDown:l?ne:void 0,children:[(0,m.jsxs)(`button`,{ref:v,type:`button`,className:`session-picker-trigger`,disabled:a,"aria-haspopup":`listbox`,"aria-expanded":l,title:o??`${_r[e]}:${r?`${t} · ${r}`:t}`,"data-picker-trigger":e,"data-picker-value":n??t,"data-picker-selected":i.some(e=>e.selected),onClick:()=>l?ee():E(),children:[(0,m.jsx)(`span`,{className:`session-picker-kind`,children:_r[e]}),(0,m.jsx)(`span`,{className:`session-picker-name`,children:t}),r&&(0,m.jsx)(`span`,{className:`session-picker-detail`,children:r}),(0,m.jsx)(`span`,{className:`session-picker-caret`,"aria-hidden":`true`,children:`▾`})]}),l&&(0,m.jsxs)(`div`,{className:`picker-menu`,ref:y,"data-picker-menu":e,"data-picker-highlight":w,children:[(0,m.jsxs)(`div`,{className:`picker-filter`,children:[(0,m.jsx)(`span`,{className:`picker-filter-icon`,"aria-hidden":`true`,children:`🔍`}),(0,m.jsx)(`input`,{ref:b,className:`picker-filter-input`,"data-picker-filter":e,role:`combobox`,"aria-label":`筛选${vr[e]}选项`,"aria-expanded":`true`,"aria-controls":re,"aria-autocomplete":`list`,"aria-activedescendant":T?ie(w):void 0,value:d,placeholder:`输入以筛选…`,autoComplete:`off`,spellCheck:!1,onChange:e=>{f(e.target.value),g(0)}}),d&&(0,m.jsx)(`button`,{type:`button`,className:`picker-filter-clear`,"data-picker-filter-clear":e,title:`清空筛选`,"aria-label":`清空筛选`,onMouseDown:e=>e.preventDefault(),onClick:()=>{f(``),g(0),b.current?.focus()},children:`✕`})]}),S&&!C.some(e=>e.key===S.key)&&(0,m.jsxs)(`div`,{className:`picker-current`,"data-picker-current":e,"data-picker-current-value":S.key,children:[(0,m.jsx)(`span`,{className:`picker-current-label`,children:`当前`}),(0,m.jsx)(`span`,{className:`picker-current-value`,children:S.label})]}),(0,m.jsxs)(`div`,{className:`picker-list`,role:`listbox`,id:re,"aria-label":yr[e],children:[C.map((e,t)=>(0,m.jsxs)(`button`,{id:ie(t),type:`button`,role:`option`,"aria-selected":e.selected,ref:e=>{x.current[t]=e},className:`picker-option${e.selected?` selected`:``}${t===w&&!e.selected?` preview`:``}`,"data-picker-option":e.key,"data-picker-option-selected":e.selected,"data-picker-highlight":t===w,onClick:()=>{s(e.key),ee(!0)},children:[e.color&&(0,m.jsx)(`span`,{className:`picker-option-swatch`,style:{background:e.color},"aria-hidden":`true`}),(0,m.jsx)(`span`,{className:`picker-option-name`,children:e.label}),e.badge&&(0,m.jsx)(`span`,{className:`picker-option-badge`,"data-picker-option-badge":e.badge,children:e.badge}),e.detail&&(0,m.jsx)(`span`,{className:`picker-option-detail`,children:e.detail}),e.selected&&(0,m.jsx)(`span`,{className:`picker-option-mark`,"aria-hidden":`true`,children:`✓`})]},e.key)),C.length===0&&(0,m.jsx)(`div`,{className:`picker-empty`,"data-picker-empty":e,children:`没有匹配「${d.trim()}」的${vr[e]}`})]})]})]})}var Hr=`__pi_default__`;function Ur({workspace:e,catalog:t,agents:n,onSave:r,onRename:i,onClose:a}){let[o,s]=(0,p.useState)(e.defaultAgentId),[c,l]=(0,p.useState)(e.defaultModel),[u,d]=(0,p.useState)(e.defaultThinkingLevel);(0,p.useEffect)(()=>{let e=e=>{e.key===`Escape`&&!e.defaultPrevented&&a()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[a]);let f=t?.source===`pi`,h=[{key:Hr,label:`跟随 Pi 默认`,detail:`不为新会话指定模型`,selected:c===void 0},...(t?.models??[]).map(e=>({key:`${e.provider}/${e.modelId}`,label:e.label,detail:e.detail,badge:xr(e),selected:c?.provider===e.provider&&c.modelId===e.modelId}))],g=[{key:Hr,label:`跟随 Pi 默认`,detail:`不为新会话指定思考等级`,selected:u===void 0},...(t?.levels??[]).map(e=>({key:e,label:e,selected:e===u}))],_=e=>{if(e===Hr){l(void 0);return}let n=(t?.models??[]).find(t=>t.provider===e.split(`/`)[0]&&t.modelId===e.split(`/`)[1]);n&&l({provider:n.provider,modelId:n.modelId,label:n.label})},v=e=>d(e===Hr?void 0:e),y=[{key:Hr,label:`跟随 Pi 默认`,detail:`新会话不使用任何 agent 角色`,selected:o===void 0},...(n?.agents??[]).map(e=>({key:e.id,label:e.name,detail:e.toolSummary,color:e.color,selected:o===e.id}))];return(0,m.jsx)(`div`,{className:`overlay`,onClick:a,children:(0,m.jsxs)(`div`,{className:`picker settings-dialog`,"data-settings-dialog":`1`,onClick:e=>e.stopPropagation(),children:[(0,m.jsx)(`h2`,{children:`工作区设置`}),(0,m.jsxs)(`div`,{className:`settings-scope`,children:[e.name,` · 默认值只影响之后新建的会话,已有会话不变`]}),(0,m.jsxs)(`div`,{className:`settings-row`,children:[(0,m.jsx)(`span`,{className:`settings-label`,children:`默认智能体`}),(0,m.jsx)(Vr,{kind:`agent`,scope:`settings-agent`,label:n?.agents.find(e=>e.id===o)?.name??`跟随 Pi 默认`,value:o??Hr,detail:o?`${n?.agents.find(e=>e.id===o)?.toolSummary??``}`:void 0,options:y,disabled:!n||n.source===`unavailable`,note:Or(n),onChoose:e=>s(e===Hr?void 0:e)})]}),(0,m.jsxs)(`div`,{className:`settings-row`,children:[(0,m.jsx)(`span`,{className:`settings-label`,children:`默认模型`}),(0,m.jsx)(Vr,{kind:`model`,scope:`settings-model`,label:c?.label??`跟随 Pi 默认`,value:c?`${c.provider}/${c.modelId}`:Hr,detail:c?`${c.provider}/${c.modelId}`:void 0,options:h,disabled:!f,note:Dr(`模型`,t),onChoose:_})]}),(0,m.jsxs)(`div`,{className:`settings-row`,children:[(0,m.jsx)(`span`,{className:`settings-label`,children:`思考强度`}),(0,m.jsx)(Vr,{kind:`thinking`,scope:`settings-thinking`,label:u??`跟随 Pi 默认`,value:u??Hr,options:g,disabled:!f,note:Dr(`思考等级`,t),onChoose:v})]}),(0,m.jsxs)(`div`,{className:`picker-actions`,children:[(0,m.jsx)(`button`,{type:`button`,className:`settings-rename`,"data-settings-rename":`1`,onClick:i,children:`重命名工作区`}),(0,m.jsx)(`button`,{type:`button`,className:`picker-cancel`,"data-settings-cancel":`1`,onClick:a,children:`取消`}),(0,m.jsx)(`button`,{type:`button`,className:`picker-ok`,"data-settings-save":`1`,onClick:()=>r(o,c,u),children:`保存`})]})]})})}var Wr=[{id:`main`,label:`主`,name:`主 tab`},{id:`tools`,label:`工具`,name:`工具 tab`},{id:`files`,label:`文件`,name:`文件 tab`},{id:`git`,label:`Git`,name:`Git tab`},{id:`terminal`,label:`终端`,name:`终端 tab`}],Gr={running:`⟳`,failed:`!`,question:`?`,unread:`•`,idle:``},Kr={running:`进行中`,failed:`出错`,question:`等你回答`,unread:`有未读`,idle:`空闲`};function qr(e,t,n){return t?`question`:e.status===`failed`?`failed`:e.status===`running`?`running`:e.updatedAt>(n??``)?`unread`:`idle`}function Jr({state:e}){let t=Gr[e];return e===`idle`?null:(0,m.jsx)(`i`,{className:`session-state session-state-${e}`,"data-session-state":e,title:Kr[e],"aria-label":Kr[e],children:(0,m.jsx)(`i`,{className:`session-state-mark`,"aria-hidden":`true`,children:t})})}var Yr={pending:`未开始`,in_progress:`进行中`,completed:`已完成`},Xr={pending:`○`,in_progress:`◐`,completed:`✓`},Zr={high:`高`,medium:`中`,low:`低`};function Qr(e){let t=e.filter(e=>e.status!==`completed`).length;return e.length?t?`${t} 个未完成 / 共 ${e.length} 个`:`全部完成:${e.length} 个`:`0 个待办任务`}function $r({todo:e,index:t}){let n=e.id??`todo_${t}`;return(0,m.jsxs)(`li`,{className:`todo-item todo-${e.status}`,"data-todo-item":n,"data-todo-status":e.status,children:[(0,m.jsx)(`span`,{className:`todo-mark`,"aria-hidden":`true`,children:Xr[e.status]}),(0,m.jsx)(`span`,{className:`todo-text`,children:e.content}),(0,m.jsx)(`span`,{className:`todo-status`,"data-todo-status-text":`1`,children:Yr[e.status]}),e.priority&&(0,m.jsx)(`span`,{className:`todo-priority`,"data-todo-priority":e.priority,children:Zr[e.priority]})]})}function ei({tasks:e}){return(0,m.jsx)(`ul`,{className:`bg-list`,"data-bg-task-count":e.length,children:e.map((e,t)=>{let n=e.id||`bg_${t}`,r=e.status?.trim()||`未知状态`;return(0,m.jsxs)(`li`,{className:`bg-item`,"data-bg-task":n,"data-bg-task-status":e.status??`unknown`,children:[(0,m.jsx)(`span`,{className:`bg-title`,children:e.title?.trim()||e.id||`未命名任务 ${t+1}`}),(0,m.jsxs)(`span`,{className:`bg-meta`,children:[e.agentId?.trim()&&(0,m.jsx)(`span`,{className:`bg-agent`,"data-bg-agent":e.agentId,children:e.agentId}),(0,m.jsx)(`span`,{className:`bg-status`,children:r})]})]},n)})})}function ti({todos:e,tasks:t,collapsed:n,onToggle:r,workspaceId:i,workspaceLabel:a,connected:o,files:s,onOpenFile:c,activeTab:l,onSelectTab:u,sendCommand:d,registerTerminalSink:f,terminalAvailable:p}){let h=Wr;return h.some(e=>e.id===l)||h[0].id,(0,m.jsx)(`div`,{className:`right-rail${n?` right-rail-collapsed`:``}`,role:`complementary`,"aria-label":`右侧栏`,"data-right-rail":`1`,"data-right-rail-collapsed":n,children:n?(0,m.jsx)(`button`,{type:`button`,className:`right-rail-open`,"data-right-rail-open":`1`,title:`展开右侧栏`,"aria-label":`展开右侧栏`,onClick:r,children:`‹`}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`div`,{className:`right-rail-head`,children:[(0,m.jsx)(`div`,{className:`right-tabs`,role:`tablist`,"aria-label":`右侧栏 tab`,"data-right-tab-count":h.length,children:h.map(e=>(0,m.jsx)(`button`,{type:`button`,role:`tab`,id:`right-tab-${e.id}`,className:`right-tab${e.id===l?` right-tab-active`:``}`,"data-right-tab":e.id,"aria-selected":e.id===l,"aria-controls":`right-panel-${e.id}`,title:e.name,"aria-label":e.name,onClick:()=>u(e.id),children:e.label},e.id))}),(0,m.jsx)(`button`,{type:`button`,className:`right-rail-collapse`,"data-right-rail-collapse":`1`,title:`收起右侧栏(聊天区会变宽)`,"aria-label":`收起右侧栏`,onClick:r,children:`›`})]}),Wr.filter(e=>e.id===l).map(n=>(0,m.jsxs)(`div`,{className:`right-rail-body`,role:`tabpanel`,id:`right-panel-${n.id}`,"aria-labelledby":`right-tab-${n.id}`,"data-right-panel":n.id,children:[n.id===`main`&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`div`,{className:`rail-section-head`,children:[(0,m.jsx)(`h2`,{className:`rail-section-title`,children:`待办任务`}),(0,m.jsx)(`span`,{className:`rail-section-count`,"data-todo-summary":`1`,children:Qr(e)})]}),e.length>0?(0,m.jsx)(`ol`,{className:`todo-list`,"data-todo-count":e.length,children:e.map((e,t)=>(0,m.jsx)($r,{todo:e,index:t},e.id??`todo_${t}`))}):(0,m.jsx)(`p`,{className:`rail-empty`,"data-todo-empty":`1`,children:`暂无待办任务。Agent 开始处理多步骤任务时,会自己把待办写到这里。`}),(0,m.jsxs)(`div`,{className:`rail-section-head`,children:[(0,m.jsx)(`h2`,{className:`rail-section-title`,children:`后台任务`}),(0,m.jsx)(`span`,{className:`rail-section-count`,"data-bg-summary":`1`,children:t.length?`${t.length} 个运行中`:`0 个`})]}),t.length>0?(0,m.jsx)(ei,{tasks:t}):(0,m.jsx)(`p`,{className:`rail-empty`,"data-bg-empty":`1`,children:`当前没有正在运行的后台任务。`})]}),n.id===`tools`&&(0,m.jsx)(ii,{}),n.id===`files`&&(0,m.jsx)(Dt,{workspaceId:i,files:s,onOpenFile:c}),n.id===`git`&&(0,m.jsx)(ne,{workspaceId:i??null}),n.id===`terminal`&&(0,m.jsx)(Qn,{workspaceId:i,workspaceLabel:a,connected:o,sendCommand:d,registerSink:f})]},n.id))]})})}function ni(){try{if(typeof window>`u`)return Yt.slice();let e=en(window.localStorage.getItem(Zt));return window.localStorage.getItem(`super-pi:tools:v1`)===null?Yt.slice():e}catch{return Yt.slice()}}function ri(e){try{if(typeof window>`u`)return;window.localStorage.setItem(Zt,F(e))}catch{}}function ii(){let[e,t]=(0,p.useState)(ni),[n,r]=(0,p.useState)(),[i,a]=(0,p.useState)(!1),o=e.find(e=>e.id===n);return(0,p.useEffect)(()=>{ri(e)},[e]),(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`div`,{className:`rail-section-head`,children:[(0,m.jsx)(`h2`,{className:`rail-section-title`,children:`工具`}),(0,m.jsxs)(`span`,{className:`rail-section-count`,"data-tool-summary":`1`,children:[e.length,` 个`]})]}),e.length>0?(0,m.jsx)(`ul`,{className:`tool-grid`,"data-tool-count":e.length,children:e.map(e=>(0,m.jsxs)(`li`,{className:`tool-slot`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`tool-icon`,"data-tool-icon":e.id,"data-tool-kind":e.kind,"data-tool-state":e.id===n?`open`:`idle`,title:`打开${e.name}`,"aria-label":`打开${e.name}`,"aria-current":e.id===n?`true`:void 0,onClick:()=>r(t=>t===e.id?void 0:e.id),children:[(0,m.jsx)(`span`,{className:`tool-icon-glyph`,"aria-hidden":`true`,children:e.glyph}),(0,m.jsx)(`span`,{className:`tool-icon-name`,children:e.name})]}),e.kind===`link`&&(0,m.jsx)(`button`,{type:`button`,className:`tool-remove`,"data-tool-remove":e.id,title:`移除${e.name}`,"aria-label":`移除${e.name}`,onClick:()=>{t(t=>rn(t,e.id)),n===e.id&&r(void 0)},children:`✕`})]},e.id))}):(0,m.jsx)(`p`,{className:`rail-empty`,"data-tool-empty":`1`,children:`还没有工具。点下面的「工具设置」添加。`}),(0,m.jsx)(`button`,{type:`button`,className:`tools-settings-btn`,"data-tool-settings-trigger":`1`,title:`添加预置工具、网址工具与说明`,"aria-label":`打开工具设置`,onClick:()=>a(!0),children:`⚙ 工具设置`}),i&&(0,m.jsx)(ai,{tools:e,onToolsChange:t,onClose:()=>a(!1)}),o&&(0,m.jsx)(si,{tool:o,onClose:()=>r(void 0)})]})}function ai({tools:e,onToolsChange:t,onClose:n}){let[r,i]=(0,p.useState)(``),[a,o]=(0,p.useState)(``),[s,c]=(0,p.useState)();return(0,p.useEffect)(()=>{let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,d.createPortal)((0,m.jsx)(`div`,{className:`tool-overlay`,"data-tool-settings-overlay":`1`,onClick:e=>{e.target===e.currentTarget&&n()},children:(0,m.jsxs)(`div`,{className:`tool-dialog`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`tool-settings-title`,"data-tool-settings":`1`,children:[(0,m.jsxs)(`div`,{className:`tool-dialog-head`,children:[(0,m.jsx)(`h2`,{className:`tool-dialog-title`,id:`tool-settings-title`,children:`⚙ 工具设置`}),(0,m.jsx)(`button`,{type:`button`,className:`tool-dialog-close`,"data-tool-settings-close":`1`,title:`关闭(Esc)`,"aria-label":`关闭工具设置`,onClick:n,children:`✕`})]}),(0,m.jsxs)(`div`,{className:`tool-dialog-body`,children:[(0,m.jsx)(`div`,{className:`rail-section-head`,children:(0,m.jsx)(`h2`,{className:`rail-section-title`,children:`从预置列表添加`})}),(0,m.jsx)(`div`,{className:`tool-presets`,"data-tool-presets":Jt.length,children:Jt.map(n=>{let r=e.some(e=>e.kind===n.kind);return(0,m.jsxs)(`div`,{className:`tool-preset`,"data-tool-preset":n.kind,children:[(0,m.jsx)(`span`,{className:`tool-preset-glyph`,"aria-hidden":`true`,children:n.glyph}),(0,m.jsxs)(`span`,{className:`tool-preset-text`,children:[(0,m.jsx)(`strong`,{children:n.name}),(0,m.jsx)(`small`,{children:n.blurb})]}),(0,m.jsx)(`button`,{type:`button`,className:`tool-preset-add`,"data-tool-add-preset":n.kind,disabled:r,title:r?`${n.name}已经在工具栏里了`:`添加${n.name}`,"aria-label":r?`${n.name}已添加`:`添加${n.name}`,onClick:()=>t(I(e,n.kind)),children:r?`已添加`:`添加`})]},n.kind)})}),(0,m.jsx)(`div`,{className:`rail-section-head`,children:(0,m.jsx)(`h2`,{className:`rail-section-title`,children:`添加网址工具`})}),(0,m.jsx)(`p`,{className:`tool-hint`,children:`填一个网址,它会变成一个图标;点开后在弹窗里用按钮在新标签页打开。网址只接受 http / https / mailto。`}),(0,m.jsx)(`input`,{className:`tool-input`,"data-tool-url-input":`1`,value:r,maxLength:2048,placeholder:`https://example.com/工具`,"aria-label":`工具网址`,onChange:e=>{i(e.target.value),c(void 0)}}),(0,m.jsx)(`input`,{className:`tool-input`,"data-tool-url-name":`1`,value:a,maxLength:40,placeholder:`名称(可留空,默认用域名)`,"aria-label":`工具名称(可选)`,onChange:e=>o(e.target.value)}),(0,m.jsx)(`button`,{type:`button`,className:`tool-url-add`,"data-tool-url-add":`1`,disabled:!r.trim(),onClick:()=>{let n=$t(r);n.ok?e.length>=32?c(`工具最多 32 个,先删掉一个再加。`):(t([...e,{id:nn(`link`,e.map(e=>e.id)),kind:`link`,name:a.trim()||oi(n.url),glyph:`↗`,url:n.url}]),i(``),o(``),c(void 0)):c(n.reason)},children:`添加网址工具`}),s&&(0,m.jsx)(`p`,{className:`tool-error`,"data-tool-error":`1`,role:`alert`,children:s}),(0,m.jsxs)(`p`,{className:`tool-hint`,"data-tool-scope-note":`1`,children:[`能自定义到哪:从上面挑预置工具,或自己填一个网址。`,(0,m.jsx)(`b`,{children:`没有开放「写一段脚本来执行」这一档`}),`——它在浏览器里等同于任意代码执行,会拿着本应用的权限跑。计算器是手写的算术解析器,不含 eval,也认不出变量名。`]})]})]})}),document.body)}function oi(e){try{return new URL(e,typeof window>`u`?`http://localhost`:window.location.href).hostname||e.slice(0,30)}catch{return e.slice(0,30)}}function si({tool:e,onClose:t}){return(0,p.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]),(0,d.createPortal)((0,m.jsx)(`div`,{className:`tool-overlay`,"data-tool-overlay":e.id,onClick:e=>{e.target===e.currentTarget&&t()},children:(0,m.jsxs)(`div`,{className:`tool-dialog`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`tool-dialog-title`,"data-tool-dialog":e.id,children:[(0,m.jsxs)(`div`,{className:`tool-dialog-head`,children:[(0,m.jsxs)(`h2`,{className:`tool-dialog-title`,id:`tool-dialog-title`,children:[(0,m.jsx)(`span`,{className:`tool-dialog-glyph`,"aria-hidden":`true`,children:e.glyph}),e.name]}),(0,m.jsx)(`button`,{type:`button`,className:`tool-dialog-close`,"data-tool-close":`1`,title:`关闭(Esc)`,"aria-label":`关闭${e.name}`,onClick:t,children:`✕`})]}),(0,m.jsxs)(`div`,{className:`tool-dialog-body`,children:[e.kind===`calculator`&&(0,m.jsx)(li,{}),e.kind===`timestamp`&&(0,m.jsx)(ui,{}),e.kind===`link`&&(0,m.jsx)(di,{tool:e})]})]})}),document.body)}function ci({image:e,onClose:t}){return(0,p.useEffect)(()=>{let e=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]),(0,d.createPortal)((0,m.jsx)(`div`,{className:`lightbox-overlay`,"data-lightbox-overlay":`1`,onClick:e=>{e.target===e.currentTarget&&t()},children:(0,m.jsxs)(`div`,{className:`lightbox-dialog`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`lightbox-title`,"data-lightbox-dialog":`1`,children:[(0,m.jsxs)(`div`,{className:`lightbox-head`,children:[(0,m.jsx)(`h2`,{className:`lightbox-title`,id:`lightbox-title`,children:e.name||`图片大图`}),(0,m.jsx)(`button`,{type:`button`,className:`lightbox-close`,"data-lightbox-close":`1`,title:`关闭(Esc)`,"aria-label":`关闭大图`,onClick:t,children:`✕`})]}),(0,m.jsx)(`div`,{className:`lightbox-body`,children:(0,m.jsx)(`img`,{src:e.url,alt:e.name||`图片大图`,className:`lightbox-image`})})]})}),document.body)}function li(){let[e,t]=(0,p.useState)(`12 * (3 + 4)`),[n,r]=(0,p.useState)(!1),i=gn(e),a=e=>{r(!1),t(t=>n?e:t+e)};return(0,m.jsxs)(`div`,{className:`tool-calc`,"data-tool-calc":`1`,children:[(0,m.jsx)(`input`,{className:`tool-input tool-calc-input`,"data-calc-input":`1`,value:e,maxLength:240,"aria-label":`算式`,spellCheck:!1,autoComplete:`off`,placeholder:`例如 (12 + 8) / 4`,onChange:e=>{r(!1),t(e.target.value)},onKeyDown:e=>{e.key===`Enter`&&e.preventDefault()}}),(0,m.jsx)(`div`,{className:`tool-calc-keys`,"data-calc-keys":`1`,children:[[`7`,`7`],[`8`,`8`],[`9`,`9`],[`÷`,`/`],[`(`,`(`],[`)`,`)`],[`4`,`4`],[`5`,`5`],[`6`,`6`],[`×`,`*`],[`^`,`^`],[`%`,`%`],[`1`,`1`],[`2`,`2`],[`3`,`3`],[`-`,`-`],[`←`,`back`],[`C`,`clear`],[`0`,`0`],[`.`,`.`],[`+`,`+`]].map(([e,n])=>(0,m.jsx)(`button`,{type:`button`,className:`tool-calc-key`,"data-calc-key":n,"aria-label":e===`C`?`清空`:e===`←`?`退格`:`输入 ${e}`,onClick:()=>{n===`clear`?(t(``),r(!1)):n===`back`?(t(e=>e.slice(0,-1)),r(!1)):a(n)},children:e},e))}),i.ok?(0,m.jsx)(`p`,{className:`tool-calc-result`,"data-calc-result":`1`,"data-calc-value":String(i.value),children:_n(i.value)}):(0,m.jsx)(`p`,{className:`tool-calc-error`,"data-calc-error":`1`,role:`alert`,children:i.reason})]})}function ui(){let[e,t]=(0,p.useState)(``),n=vn(e),r=n.ok?bn(n.ms):null;return(0,m.jsxs)(`div`,{className:`tool-stamp`,"data-tool-stamp":`1`,children:[(0,m.jsx)(`input`,{className:`tool-input`,"data-stamp-input":`1`,value:e,maxLength:64,spellCheck:!1,"aria-label":`时间戳或日期`,placeholder:`1757000000 或 2026-10-08T09:00:00`,onChange:e=>t(e.target.value)}),r?(0,m.jsxs)(`dl`,{className:`tool-stamp-out`,"data-stamp-result":`1`,children:[(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`dt`,{children:`本地时间`}),(0,m.jsx)(`dd`,{"data-stamp-local":`1`,children:r.local})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`dt`,{children:`ISO(UTC)`}),(0,m.jsx)(`dd`,{"data-stamp-iso":`1`,children:r.iso})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`dt`,{children:`秒`}),(0,m.jsx)(`dd`,{"data-stamp-seconds":`1`,children:r.seconds})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`dt`,{children:`毫秒`}),(0,m.jsx)(`dd`,{"data-stamp-ms":`1`,children:r.milliseconds})]})]}):(0,m.jsx)(`p`,{className:`tool-stamp-error`,"data-stamp-error":`1`,role:`alert`,children:n.ok?`这个日期无法显示。`:n.reason})]})}function di({tool:e}){let[t,n]=(0,p.useState)(!1),r=`请帮我开发一个可挂载到 Super Pi 右侧工具栏的小工具。\n\n目标地址:${e.url}\n\n请使用独立 HTTP 服务器提供页面,并给出启动命令、文件结构和测试步骤。`,i=async()=>{let e=await mr(r);n(e),window.setTimeout(()=>n(!1),1800)};return(0,m.jsxs)(`div`,{className:`tool-link`,"data-tool-link":e.id,children:[(0,m.jsx)(`p`,{className:`tool-hint`,children:`网页工具由独立 HTTP 服务器提供,把页面挂到服务器后即可使用。`}),(0,m.jsx)(`code`,{className:`tool-link-url`,"data-tool-link-url":e.id,children:e.url}),(0,m.jsxs)(`div`,{className:`tool-link-actions`,children:[(0,m.jsx)(`a`,{className:`tool-link-open`,"data-tool-link-open":e.id,href:e.url,target:`_blank`,rel:`noopener noreferrer`,title:e.url,children:`在新标签页打开 ?`}),(0,m.jsx)(`button`,{type:`button`,className:`tool-link-copy-prompt`,"data-tool-copy-prompt":e.id,onClick:()=>void i(),children:t?`已复制`:`复制开发 Prompt`})]}),/^https?:\/\//i.test(e.url??``)&&(0,m.jsx)(`iframe`,{className:`tool-link-frame`,"data-tool-frame":e.id,src:e.url,title:e.name,sandbox:`allow-forms allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts`,referrerPolicy:`no-referrer`})]})}var fi=`(max-width: 1100px)`,pi=(e,t,n)=>Math.min(Math.max(e,t),Math.max(t,n));function mi(e,t,n){let r=Math.max(0,Math.round(n)-480),i=pi(520,180,Math.max(180,r-240)),a=pi(Math.round(e),180,i),o=pi(640,240,Math.max(240,r-a));return{sidebar:a,rail:pi(Math.round(t),240,o),sidebarMin:180,sidebarMax:i,railMin:240,railMax:o,sumCap:r}}var hi=`super-pi.rail-widths.v1`,gi=`super-pi.reader-state.v1`,_i=48,vi=160,yi=e=>{e.dataset.programmaticScroll=`true`,window.setTimeout(()=>{delete e.dataset.programmaticScroll},0)};function bi(){try{if(typeof window>`u`)return{conversations:{}};let e=JSON.parse(window.localStorage.getItem(`super-pi.reader-state.v1`)??`null`);if(!e||typeof e!=`object`)return{conversations:{}};let t={};if(e.conversations&&typeof e.conversations==`object`)for(let[n,r]of Object.entries(e.conversations)){let e=r;typeof e.followTail==`boolean`&&(t[n]={followTail:e.followTail,scrollTop:Number.isFinite(e.scrollTop)?Math.max(0,Number(e.scrollTop)):0,...typeof e.anchorKey==`string`?{anchorKey:e.anchorKey}:{},...Number.isFinite(e.anchorOffset)?{anchorOffset:Number(e.anchorOffset)}:{}})}let n={};if(e.readAt&&typeof e.readAt==`object`)for(let[t,r]of Object.entries(e.readAt))typeof r==`string`&&(n[t]=r);return{activeId:typeof e.activeId==`string`?e.activeId:void 0,workspaceId:typeof e.workspaceId==`string`?e.workspaceId:void 0,conversations:t,readAt:n}}catch{return{conversations:{}}}}function xi(e){try{typeof window<`u`&&window.localStorage.setItem(gi,JSON.stringify(e))}catch{}}function Si(){try{if(typeof window>`u`)return{};let e=window.localStorage.getItem(hi);if(e===null)return{};let t=JSON.parse(e),n=e=>typeof e==`number`&&Number.isFinite(e)&&e>0?Math.round(e):void 0;return{sidebar:n(t.sidebar),rail:n(t.rail)}}catch{return{}}}function Ci(e){try{if(typeof window>`u`)return;window.localStorage.setItem(hi,JSON.stringify(e))}catch{}}function wi({side:e,width:t,min:n,max:r,label:i,onWidth:a}){let[o,s]=(0,p.useState)(!1),c=e=>e.shiftKey?64:16;return(0,m.jsx)(`div`,{className:`rail-resizer rail-resizer-${e}${o?` rail-resizer-dragging`:``}`,"data-rail-resizer":e,"data-rail-resizer-dragging":o?`true`:`false`,"data-rail-resizer-width":t,role:`separator`,"aria-orientation":`vertical`,"aria-label":i,"aria-valuenow":t,"aria-valuemin":n,"aria-valuemax":r,tabIndex:0,onMouseDown:i=>{i.preventDefault(),i.currentTarget.focus();let o=i.clientX,c=t;s(!0);let l=document.body,u=l.style.cursor,d=l.style.userSelect;l.style.cursor=`col-resize`,l.style.userSelect=`none`;let f=t=>{let i=e===`left`?t.clientX-o:o-t.clientX;a(pi(c+i,n,r))},p=()=>{l.style.cursor=u,l.style.userSelect=d,s(!1),window.removeEventListener(`mousemove`,f),window.removeEventListener(`mouseup`,p)};window.addEventListener(`mousemove`,f),window.addEventListener(`mouseup`,p)},onKeyDown:i=>{let o=c(i);i.key===`ArrowLeft`?(i.preventDefault(),a(pi(e===`left`?t-o:t+o,n,r))):i.key===`ArrowRight`?(i.preventDefault(),a(pi(e===`left`?t+o:t-o,n,r))):i.key===`Home`?(i.preventDefault(),a(n)):i.key===`End`&&(i.preventDefault(),a(r))}})}function Ti(){let[e,t]=(0,p.useState)($n),[n,r]=(0,p.useState)([]),i=(0,p.useRef)([]),a=(0,p.useRef)(null);a.current||=bi();let o=n.reduce((e,t)=>t.apply(e),e),[s,c]=(0,p.useState)(a.current.activeId),[l,u]=(0,p.useState)(!1),[d,f]=(0,p.useState)(),[h,g]=(0,p.useState)({}),[_,v]=(0,p.useState)(a.current.workspaceId),[y,b]=(0,p.useState)(!1),x=(0,p.useRef)(void 0),S=(0,p.useRef)(a.current.conversations),C=(0,p.useRef)(a.current.readAt??{}),[w,T]=(0,p.useState)(0),ee=(0,p.useRef)(null),E=(0,p.useRef)(null),te=(0,p.useRef)(void 0),ne=(0,p.useRef)(a.current.activeId),[re,ie]=(0,p.useState)({followTail:!0,scrollTop:0}),ae=(0,p.useRef)(void 0),oe=(0,p.useCallback)(e=>{ae.current=e},[]),[se,ce]=(0,p.useState)({}),[le,ue]=(0,p.useState)([]),[de,fe]=(0,p.useState)([]),[pe,me]=(0,p.useState)(new Map),[he,ge]=(0,p.useState)(new Map),[_e,ve]=(0,p.useState)(),[ye,be]=(0,p.useState)(),[xe,Se]=(0,p.useState)(),[Ce,D]=(0,p.useState)(),[O,we]=(0,p.useState)(),[Te,Ee]=(0,p.useState)(`idle`),[De,k]=(0,p.useState)(()=>typeof window<`u`&&typeof window.matchMedia==`function`&&window.matchMedia(`(max-width: 1100px)`).matches),[A,Oe]=(0,p.useState)(`chat`),[ke,Ae]=(0,p.useState)(()=>typeof window>`u`?1440:window.innerWidth);(0,p.useEffect)(()=>{let e=()=>Ae(window.innerWidth);return window.addEventListener(`resize`,e),e(),()=>window.removeEventListener(`resize`,e)},[]);let[je,Me]=(0,p.useState)(Si),Ne=mi(je.sidebar??270,je.rail??320,ke);(0,p.useEffect)(()=>{Ci({sidebar:Ne.sidebar,rail:Ne.rail})},[Ne.sidebar,Ne.rail]);let Pe=e=>Me(t=>({...t,sidebar:e})),Fe=e=>Me(t=>({...t,rail:e}));(0,p.useEffect)(()=>{if(typeof window>`u`||typeof window.matchMedia!=`function`)return;let e=window.matchMedia(fi),t=e=>{e.matches&&k(!0)};return e.addEventListener(`change`,t),e.matches&&k(!0),()=>e.removeEventListener(`change`,t)},[]);let[Ie,Le]=(0,p.useState)(new Map),[Re,ze]=(0,p.useState)({}),[Be,Ve]=(0,p.useState)({}),[He,Ue]=(0,p.useState)({}),[We,Ge]=(0,p.useState)(),[Ke,Je]=(0,p.useState)(),[Ye,Xe]=(0,p.useState)(),Ze=(0,p.useRef)(new Map),[Qe,$e]=(0,p.useState)({}),et=(0,p.useRef)(new Set),[tt,nt]=(0,p.useState)([]),[rt,at]=(0,p.useState)([]),[st,ct]=(0,p.useState)(),[lt,ut]=(0,p.useState)(!1),dt=(0,p.useRef)(null),ft=(0,p.useRef)(!1),pt=(0,p.useRef)(0),mt=(0,p.useRef)([]),ht=(0,p.useRef)(void 0),gt=(0,p.useRef)(!1),[_t,vt]=(0,p.useState)(()=>Date.now());(0,p.useEffect)(()=>{let e=window.setInterval(()=>vt(Date.now()),3e4);return()=>window.clearInterval(e)},[]);let yt=(0,p.useMemo)(()=>o.conversations.filter(e=>!e.archivedAt),[o.conversations]),j=(0,p.useMemo)(()=>yt.find(e=>e.id===s)??yt.find(e=>e.workspaceId===_)??(_&&o.workspaces.some(e=>e.id===_)?void 0:yt[0]),[s,yt,_,o.workspaces]),bt=(0,p.useMemo)(()=>o.workspaces.find(e=>e.id===_)??o.workspaces[0],[o.workspaces,_]),xt=(0,p.useRef)(_);xt.current=_,(0,p.useEffect)(()=>{j&&v(j.workspaceId)},[j?.id]),(0,p.useEffect)(()=>{ht.current=s},[s]),(0,p.useEffect)(()=>{te.current=j?.id},[j?.id]),(0,p.useEffect)(()=>{let e=j?.id;if(!e)return;let t=o.conversations.find(t=>t.id===e);if(!t)return;let n=C.current[e];C.current[e]=t.updatedAt,n!==t.updatedAt&&T(e=>e+1),xi({activeId:ht.current,workspaceId:j?.workspaceId??_,conversations:S.current,readAt:C.current})},[j?.id,o.conversations]),(0,p.useEffect)(()=>{l&&s&&xi({activeId:s,workspaceId:j?.workspaceId??_,conversations:S.current})},[s,j?.workspaceId,l,_]),(0,p.useEffect)(()=>{let e=ee.current;if(!e||!j?.id)return;let t=j.id,n=S.current[t]??{followTail:!0,scrollTop:0};ie(n),requestAnimationFrame(()=>{if(ee.current===e){if(n.followTail)yi(e),e.scrollTop=e.scrollHeight;else{let t=n.anchorKey?e.querySelector(`[data-transcript-key="${CSS.escape(n.anchorKey)}"]`):null;e.scrollTop=t?Math.max(0,e.scrollTop+t.getBoundingClientRect().top-(n.anchorOffset??0)-e.getBoundingClientRect().top):n.scrollTop}}}),ne.current=void 0},[j?.id]);let St=(0,p.useCallback)((e,t=!1,n=!1)=>{let r=te.current;if(!r)return;let i=e.scrollHeight-e.clientHeight-e.scrollTop,a=S.current[r]??{followTail:!0,scrollTop:0},o=t?!1:n?!0:a.followTail?i<=vi:i<=_i,s,c;if(!o){let t=e.getBoundingClientRect().top,n=[...e.querySelectorAll(`[data-transcript-key]`)].find(e=>e.getBoundingClientRect().bottom>t);s=n?.dataset.transcriptKey,c=n?n.getBoundingClientRect().top-t:void 0}let l={followTail:o,scrollTop:e.scrollTop,...s?{anchorKey:s,anchorOffset:c}:{}};S.current[r]=l,ie(l),xi({activeId:r,workspaceId:xt.current,conversations:S.current})},[]),Ct=Qe[j?.id??``]??{text:``,images:[],uploading:0},Tt=Ct.text,Dt=Ct.images,Ot=Ct.uploading,M=(e,t)=>$e(n=>({...n,[e]:t(n[e]??{text:``,images:[],uploading:0})})),kt=e=>M(j?.id??``,t=>({...t,text:e})),[jt,Mt]=(0,p.useState)({visible:!1,query:``,rect:null}),Nt=e=>M(j?.id??``,t=>({...t,images:typeof e==`function`?e(t.images):e})),[Pt,Ft]=(0,p.useState)([]),It=Pt.length>0?Pt:j?[j.id]:[],Lt=(0,p.useMemo)(()=>It.map(e=>yt.find(t=>t.id===e)).filter(e=>e!==void 0),[It,yt]),zt=(0,p.useCallback)(e=>{c(e);let t=yt.find(t=>t.id===e)?.workspaceId;t&&v(t),qt(`session`),Ft(t=>t.includes(e)?t:t.length>0?[...t,e]:[...j?.id&&j.id!==e?[j.id]:[],e])},[j]),Vt=(0,p.useCallback)(e=>{let t=Pt.indexOf(e);if(t<0)return;let n=Pt.filter(t=>t!==e);if(Ft(n),j?.id!==e)return;let r=n[Math.min(t,n.length-1)];r&&c(r)},[Pt,j]),N=Et(_),[Ht,Ut]=(0,p.useState)(Wr[0].id),[Wt,Gt]=(0,p.useState)(!1);(0,p.useEffect)(()=>{let e=!1;return fetch(`/api/terminal`).then(e=>e.json()).then(t=>{e||Gt(!!t?.enabled)}).catch(()=>{e||Gt(!1)}),()=>{e=!0}},[]);let[Kt,qt]=(0,p.useState)(`session`);(0,p.useEffect)(()=>{Kt===`file`&&!N.active&&qt(`session`)},[Kt,N.active]);let Jt=(0,p.useCallback)(e=>{N.setActivePath(e),qt(`file`),Ut(`files`)},[N.setActivePath]),Yt=(0,p.useCallback)(async e=>{await N.openFile(e),qt(`file`)},[N.openFile]),Xt=(0,p.useMemo)(()=>Lt.map(e=>({id:`session:${e.id}`,rawId:e.id,kind:`session`,label:e.title,title:e.title,closable:Lt.length>1||N.open.length>0,badge:(0,m.jsx)(Jr,{state:qr(e,le.some(t=>t.conversationId===e.id),C.current[e.id])})})),[Lt,N.open.length,le,o.conversations,w]),P=(0,p.useMemo)(()=>N.open.map(e=>({id:`file:${e.path}`,rawId:e.path,kind:`file`,label:e.name,title:e.path,closable:!0,badge:e.dirty?(0,m.jsx)(`span`,{className:`file-tab-badge`,"data-file-tab-dirty":e.path,"aria-label":`未保存`,children:`●`}):void 0})),[N.open]),Zt=(0,p.useMemo)(()=>[...Xt,...P],[Xt,P]),Qt=Kt===`file`&&N.activePath?`file:${N.activePath}`:j?.id?`session:${j.id}`:void 0,$t=(0,p.useCallback)(e=>{if(e.startsWith(`file:`)){let t=e.slice(5);Jt(t)}else if(e.startsWith(`session:`)){let t=e.slice(8);zt(t)}},[Jt,zt]),en=(0,p.useCallback)(e=>{if(e.startsWith(`file:`)){let t=e.slice(5);N.closeFile(t),N.activePath===t&&N.open.length<=1&&qt(`session`)}else if(e.startsWith(`session:`)){let t=e.slice(8);Vt(t)}},[N,Vt]),F=N.active,nn=j?.id;(0,p.useEffect)(()=>{nn&&!nn.startsWith(`pending:`)&&cn({type:`conversation.select`,conversationId:nn})},[nn]);let I=(e,t=`info`)=>{if(!e)return;let n=++pt.current;fe(r=>[...r,{key:n,text:e,kind:t}]),mt.current.push(window.setTimeout(()=>fe(e=>e.filter(e=>e.key!==n)),7e3))},rn=(e,t)=>{let n=e.findIndex(e=>e.id===t.id);if(n<0)return[t,...e];let r=[...e];return r[n]=t,r},an=(e,t)=>{let n=e.findIndex(e=>e.id===t.id);if(n<0)return[t,...e];let r=[...e];return r[n]=t,r},on=(e,t)=>{if(t.blocking)ue(n=>[...n.filter(n=>n.conversationId!==e||n.request.requestId!==t.requestId),{conversationId:e,request:t}]);else if(t.method===`notify`)I(t.message||t.title,t.notifyType??`info`);else if(t.method===`setStatus`){let e=t.statusKey??``;me(n=>{let r=new Map(n);return t.statusText===void 0?r.delete(e):r.set(e,t.statusText),r})}else if(t.method===`setWidget`){let e=t.widgetKey??``;ge(n=>{let r=new Map(n);return t.widgetLines===void 0?r.delete(e):r.set(e,{lines:t.widgetLines,placement:t.widgetPlacement??`aboveEditor`}),r})}else t.method===`setTitle`?ve(t.title):t.method===`set_editor_text`&&e===ht.current&&kt(t.text??``)},sn=(e,t,n)=>{ue(n=>n.filter(n=>n.conversationId!==e||n.request.requestId!==t));let r=Tr[n];r&&I(r,`warning`)};(0,p.useEffect)(()=>{let e=!1,n=0,o,s=()=>{if(e)return;let l=location.protocol===`https:`?`wss`:`ws`,d=new WebSocket(`${l}://${location.host}/ws`);x.current=d,d.onopen=()=>{e||(n=0,u(!0),d.send(JSON.stringify({type:`catalog.fetch`,conversationId:ht.current})),d.send(JSON.stringify({type:`agent.catalog.fetch`})),d.send(JSON.stringify({type:`subagent.catalog.fetch`})))},d.onclose=()=>{if(!e){gt.current=!1;for(let e of i.current)e.onFailure?.();i.current=[],r([]),u(!1),o=window.setTimeout(s,Math.min(pr,fr*2**n++))}},d.onmessage=({data:n})=>{if(e)return;let o=JSON.parse(n);if(o.type.startsWith(`terminal.`))ae.current?.(o);else if(o.type===`conversation.autoRename.result`){let e=Ze.current.get(o.conversationId);e&&(Ze.current.delete(o.conversationId),o.ok?e.resolve(o.title):e.reject(Error(o.error)))}else if(o.type===`message.thinking`)t(e=>({...e,conversations:e.conversations.map(e=>e.id===o.conversationId?{...e,messages:e.messages.map(e=>e.id===o.messageId?{...e,thinking:(e.thinking??``)+o.delta}:e)}:e)}));else if(o.type===`state`)gt.current=!1,i.current=i.current.filter(e=>!e.accepted?.(o.state)),r(i.current),t(o.state),u(!0),c(e=>{let t=o.state.conversations.filter(e=>!e.archivedAt),n=a.current?.activeId,r=!!(e&&t.some(t=>t.id===e)),s=!!(e&&i.current.some(t=>t.temporaryId===e));return r||s?e:n&&t.some(e=>e.id===n)?n:t.find(e=>e.workspaceId===xt.current)?.id}),v(e=>{let t=a.current?.workspaceId;return t&&o.state.workspaces.some(e=>e.id===t)?t:e&&(o.state.workspaces.some(t=>t.id===e)||i.current.some(t=>t.temporaryId===e))?e:o.state.workspaces[0]?.id});else if(o.type===`message.delta`)t(e=>({...e,conversations:e.conversations.map(e=>e.id===o.conversationId?{...e,messages:e.messages.map(e=>e.id===o.messageId?{...e,content:e.content+o.delta}:e)}:e)}));else if(o.type===`message.revert.result`)ii(void 0),Ge(void 0),o.ok||f(o.message);else if(o.type===`operation.result`){let e=i.current.find(e=>e.id===o.requestId);if(i.current=i.current.filter(e=>e.id!==o.requestId),r(i.current),e?.temporaryId){let t=e.temporaryId;c(n=>n===t?o.ok?o.entityId:e.previousActiveId:n),Ft(e=>e.flatMap(e=>e===t?o.ok&&o.entityId?[o.entityId]:[]:[e])),v(e=>e===t?o.ok?o.entityId:void 0:e)}o.ok||(e?.onFailure?.(),f(o.message??`操作失败`))}else o.type===`error`?(f(o.message),gt.current&&(gt.current=!1,I(`重命名失败:${o.message}`,`error`))):o.type===`extension.ui`?on(o.conversationId,o.request):o.type===`extension.ui.closed`?sn(o.conversationId,o.requestId,o.reason):o.type===`model.catalog`?(!o.conversationId||o.conversationId===ht.current)&&be(o.catalog):o.type===`agent.catalog`?Se(o.catalog):o.type===`subagent.catalog`?D(o.catalog):o.type===`server.version`?(we(o.version),o.version.needsRestart&&I(`检测到 Super Pi 代码已更新(v${o.version.runningVersion} → v${o.version.diskVersion}),请执行 /super_pi restart 重启服务生效`,`warning`)):o.type===`subagent.event`?t(e=>({...e,subagentRuns:rn(e.subagentRuns??[],o.run)})):o.type===`workflow.event`?t(e=>({...e,workflows:an(e.workflows??[],o.workflow)})):o.type===`message.tools`?t(e=>({...e,conversations:e.conversations.map(e=>e.id===o.conversationId?{...e,messages:e.messages.map(e=>e.id===o.messageId?{...e,toolCalls:o.toolCalls}:e)}:e)})):o.type===`pi.queue`?Le(e=>{let t=new Map(e);return t.set(o.conversationId,{steering:o.steering,followUp:o.followUp}),t}):o.type===`conversation.fork.result`&&(pi(e=>e===o.conversationId?void 0:e),I(o.ok?`已从「${o.title}」分叉出新会话,放在侧边栏最上面;没有切换过去。${o.messagesCopied?`复制了 ${o.messagesCopied} 条消息。`:`原会话还没有消息,只复制了会话本身。`}`:`分叉失败:${o.message}`,o.ok?`info`:`error`))}};return s(),()=>{e=!0,window.clearTimeout(o);for(let e of mt.current)window.clearTimeout(e);x.current?.close()}},[]);let cn=(0,p.useCallback)(e=>x.current?.readyState===WebSocket.OPEN&&(x.current.send(JSON.stringify(e)),!0),[]),L=(e,t,n,a,o,s)=>{if(x.current?.readyState!==WebSocket.OPEN||i.current.some(e=>e.key===t))return!1;let c=tn(),l={id:c,key:t,apply:n,temporaryId:a,previousActiveId:ht.current,onFailure:o,accepted:s};return i.current=[...i.current,l],r(i.current),x.current.send(JSON.stringify({...e,operationRequestId:c})),!0},ln=(e,t)=>n=>({...n,conversations:n.conversations.map(n=>n.id===e?{...n,...t}:n)}),un=(e,t)=>n=>({...n,workspaces:n.workspaces.map(n=>n.id===e?{...n,...t}:n)}),dn=n.some(e=>e.key===`send:${j?.id}`||e.key===`configuration:${j?.id}`||e.temporaryId===j?.id||e.key===`archive:${j?.id}`),fn=(e,t,n,r,i)=>{e&&x.current?.send(JSON.stringify({type:`question.answer`,conversationId:e,messageId:t,callIndex:n,answers:r,cancelled:i}))},pn=(e,t,n)=>L({type:`extension.ui.answer`,conversationId:e,requestId:t,...n},`answer:${e}:${t}`,e=>e),mn=j?.model??ye?.defaultModel,hn=j?.thinkingLevel??ye?.defaultThinkingLevel,gn=ye?.source===`pi`,_n=!!ye?.models.find(e=>e.provider===mn?.provider&&e.modelId===mn?.modelId)?.imageInput,vn=(e,t)=>!e||!t?e:{...e,models:e.models.filter(e=>(o.modelFilterRules??[]).every(n=>{try{return!new RegExp(n.workspacePattern,`i`).test(t.name)||new RegExp(n.modelPattern,`i`).test(e.label)||new RegExp(n.modelPattern,`i`).test(`${e.provider}/${e.modelId}`)}catch{return!0}}))},yn=(vn(ye,o.workspaces.find(e=>e.id===j?.workspaceId))?.models??[]).map(e=>({key:`${e.provider}/${e.modelId}`,label:e.label,detail:e.detail,badge:xr(e),selected:mn?.provider===e.provider&&mn.modelId===e.modelId})),bn=(ye?.levels??[]).map(e=>({key:e,label:e,selected:e===hn})),xn=e=>{if(!j)return;let[t,n]=e.split(`/`);t&&n&&L({type:`conversation.model`,conversationId:j.id,provider:t,modelId:n},`configuration:${j.id}`,ln(j.id,{model:ye?.models.find(e=>e.provider===t&&e.modelId===n)??{provider:t,modelId:n,label:n}}))},Sn=e=>{j&&L({type:`conversation.thinking`,conversationId:j.id,level:e},`configuration:${j.id}`,ln(j.id,{thinkingLevel:e}))},Cn=xe?.agents.find(e=>e.id===j?.agentId),wn=[{key:Hr,label:`跟随 Pi 默认`,detail:`不使用任何 agent 角色`,selected:!j?.agentId},...(xe?.agents??[]).map(e=>({key:e.id,label:e.name,detail:e.toolSummary,color:e.color,selected:j?.agentId===e.id}))],Tn=Cn?.model,En=!!(Tn&&j?.model&&j.model.provider===Tn.provider&&j.model.modelId===Tn.modelId);Cn?.thinkingLevel&&(j?.thinkingLevel,Cn.thinkingLevel);let Dn=e=>{if(j){let t=xe?.agents.find(t=>t.id===e);L({type:`conversation.agent`,conversationId:j.id,agentId:e===Hr?null:e},`configuration:${j.id}`,ln(j.id,{agentId:t?.id,...t?.model?{model:{...t.model,label:t.model.modelId}}:{},...t?.thinkingLevel?{thinkingLevel:t.thinkingLevel}:{}}))}},kn=le.filter(e=>e.conversationId===j?.id),An=(0,p.useMemo)(()=>(o.subagentRuns??[]).filter(e=>e.conversationId===j?.id),[o.subagentRuns,j?.id]),jn=(0,p.useMemo)(()=>(o.workflows??[]).filter(e=>e.conversationId===j?.id),[o.workflows,j?.id]),Mn=(0,p.useMemo)(()=>new Map(jn.map(e=>[e.id,e])),[jn]),Nn=(0,p.useMemo)(()=>new Map((Ce?.agents??[]).map(e=>[e.id,e.name])),[Ce]),Pn=(0,p.useMemo)(()=>new Map((j?.messages??[]).map(e=>[e.id,e])),[j?.messages]),In=(0,p.useMemo)(()=>new Map(An.map(e=>[e.id,e])),[An]),Ln=(0,p.useMemo)(()=>{if(!j)return[];let e=We?.conversationId===j.id?`m:${We.messageId}`:void 0,t=j.messages.filter(t=>`m:${t.id}`!==e).map((e,t)=>({at:Date.parse(e.createdAt)||0,seq:t,key:`m:${e.id}`}));return An.forEach((e,n)=>t.push({at:Date.parse(e.startedAt)||0,seq:t.length+n,key:`r:${e.id}`})),jn.forEach((e,n)=>t.push({at:Date.parse(e.startedAt)||0,seq:t.length+n,key:`w:${e.id}`})),t.sort((e,t)=>e.at-t.at||e.seq-t.seq).map(e=>e.key)},[j,An,jn,We]);(0,p.useEffect)(()=>{let e=ee.current;if(!e||!j?.id)return;let t=()=>{S.current[j.id]?.followTail&&(yi(e),e.scrollTop=e.scrollHeight)};if(t(),typeof ResizeObserver>`u`)return;let n=new ResizeObserver(t);n.observe(e);for(let t of e.children)n.observe(t);return()=>n.disconnect()},[j?.id,j?.messages,An,jn,Ln]);let Rn=e=>ze(t=>({...t,[e]:!t[e]})),zn=(e,t)=>Ve(n=>({...n,[`${e}:${t}`]:!n[`${e}:${t}`]})),Bn=(e,t)=>Ue(n=>({...n,[`${e}:${t}`]:n[`${e}:${t}`]!==!1})),[Vn,Hn]=(0,p.useState)({}),Un=e=>Hn(t=>({...t,[e]:t[e]===!1})),Wn=e=>{L({type:`subagent.stop`,runId:e},`stop:${e}`,e=>e)||I(`连接断开,无法停止子智能体,请重试`,`error`)},Gn=e=>{L({type:`workflow.stop`,workflowId:e},`stop:${e}`,e=>e)||I(`连接断开,无法停止编排,请重试`,`error`)},Kn=e=>[...he].filter(([,t])=>t.placement===e).map(([e,t])=>{let n=t.lines;return(0,m.jsxs)(`div`,{className:`extui-widget`,"data-widget-key":e,"data-widget-lines":n.length,children:[n.slice(0,Er).map((e,t)=>(0,m.jsx)(`div`,{children:e},`${t}:${e}`)),n.length>Er&&(0,m.jsx)(`div`,{children:`… (widget truncated)`})]},e)}),qn=(e,t)=>{let n=`pending:${tn()}`,r={id:n,name:e,path:t,updatedAt:new Date().toISOString()};L({type:`workspace.create`,name:e,path:t},`create-workspace`,e=>({...e,workspaces:[...e.workspaces,r]}),n)&&(v(n),c(void 0),b(!1))},[Jn,Yn]=(0,p.useState)(),Xn=(e,t)=>Yn(n=>n?.kind===e&&n.id===t?n:{kind:e,id:t}),Zn=()=>Yn(void 0),Qn=(e,t)=>Jn?.kind===e&&Jn.id===t,nr=(e,t,n)=>t.startsWith(`pending:`)?!1:L(e===`workspace`?{type:`workspace.rename`,workspaceId:t,name:n}:{type:`conversation.rename`,conversationId:t,name:n},`rename:${t}`,e===`workspace`?un(t,{name:n}):ln(t,{title:n}))?(gt.current=!0,Zn(),!0):(I(`连接断开,改名未保存,请重试`,`error`),!1),rr=async e=>{if(e.startsWith(`pending:`)){I(`这个会话还在创建中,稍后再试`,`warning`);return}if(Ze.current.has(e))return;I(`正在根据对话内容生成标题…`,`info`);let t=new Promise((t,n)=>{Ze.current.set(e,{resolve:t,reject:n}),window.setTimeout(()=>{Ze.current.delete(e)&&n(Error(`模型在 30 秒内没有返回标题`))},32e3)});if(!cn({type:`conversation.autoRename`,conversationId:e}))Ze.current.delete(e),I(`连接断开,无法生成标题`,`error`);else try{let n=await t;nr(`conversation`,e,n),I(`已重命名为「${n}」`,`info`)}catch(e){I(`重命名失败:${e instanceof Error?e.message:String(e)}`,`error`)}},ir=e=>{if(e.id.startsWith(`pending:`))return;let t=o.conversations.filter(t=>t.workspaceId===e.id).length;window.confirm(`删除工作区「${e.name}」?${t?`其中 ${t} 条会话将一并删除,`:``}此操作不可撤销。`)&&L({type:`workspace.delete`,workspaceId:e.id},`delete:${e.id}`,t=>({...t,workspaces:t.workspaces.filter(t=>t.id!==e.id),conversations:t.conversations.filter(t=>t.workspaceId!==e.id)}))},[ar,or]=(0,p.useState)(),sr=ar?o.workspaces.find(e=>e.id===ar):void 0,{theme:_r,setTheme:vr}=On(),[yr,br]=(0,p.useState)(!1),[Sr,Cr]=(0,p.useState)(!1),kr=(e,t,n,r)=>{e.startsWith(`pending:`)||(L({type:`workspace.settings`,workspaceId:e,model:n?{provider:n.provider,modelId:n.modelId}:null,thinkingLevel:r??null,agentId:t??null},`defaults:${e}`,un(e,{defaultModel:n,defaultThinkingLevel:r,defaultAgentId:t}))?or(void 0):I(`连接断开,设置未保存,请重试`,`error`))},Ar=e=>{if(e.startsWith(`pending:`)||i.current.some(t=>t.key===`defaults:${e}`))return;let t=`pending:${tn()}`,n={id:t,workspaceId:e,title:`新会话`,status:`idle`,updatedAt:new Date().toISOString(),messages:[]};L({type:`conversation.create`,workspaceId:e},`create-session:${e}`,e=>({...e,conversations:[n,...e.conversations]}),t)&&(v(e),c(t),qt(`session`),Ft(e=>[...e.filter(e=>e!==t),t]))},jr=e=>{e.startsWith(`pending:`)||L({type:`conversation.archive`,conversationId:e},`archive:${e}`,ln(e,{archivedAt:new Date().toISOString()}))},Nr=e=>L({type:`conversation.unarchive`,conversationId:e},`archive:${e}`,ln(e,{archivedAt:void 0})),Rr=async e=>{if(!j){I(`请先选择或创建会话`,`error`);return}if(!_n){I(`当前模型不支持图片输入`,`error`);return}let t=[`image/png`,`image/jpeg`,`image/gif`,`image/webp`],n=e.filter(e=>t.includes(e.type)?e.size>5242880?(I(`图片「${e.name}」超过 5MB 上限`,`error`),!1):!0:(I(`不支持的文件格式「${e.name}」,仅支持 PNG/JPEG/GIF/WebP`,`error`),!1));if(n.length===0)return;let r=j.id;M(r,e=>({...e,uploading:e.uploading+n.length}));let i=n.map(e=>({id:tn(),conversationId:r,name:e.name,url:URL.createObjectURL(e)}));at(e=>[...e,...i]);for(let[e,t]of n.entries()){let n=i[e];try{let e=await new Promise((e,n)=>{let r=new FileReader;r.onload=()=>{let t=r.result,n=t.indexOf(`,`);e(n>=0?t.slice(n+1):t)},r.onerror=n,r.readAsDataURL(t)}),i=await fetch(`/api/upload`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({conversationId:r,name:t.name,mimeType:t.type,data:e})});if(!(i.headers.get(`content-type`)??``).includes(`application/json`)){I(`服务器未返回 JSON 响应,请刷新或重启服务`,`error`);continue}if(i.ok){let e=await i.json();if(et.current.has(n.id))continue;at(e=>e.filter(e=>e.id!==n.id)),URL.revokeObjectURL(n.url),M(r,t=>({...t,images:[...t.images,{id:e.id,name:e.name,mimeType:e.mimeType,bytes:e.bytes}]}))}else{let e=await i.json().catch(()=>({error:`上传失败`}));I(e.error||`上传失败: ${i.status}`,`error`)}}catch(e){I(`上传错误: ${e instanceof Error?e.message:`网络错误`}`,`error`)}finally{at(e=>e.map(e=>e.id===n.id?{...e,failed:!0}:e)),M(r,e=>({...e,uploading:Math.max(0,e.uploading-1)}))}}},Gr=e=>{let t=e.clipboardData?.items;if(!t)return;let n=[];for(let e=0;e<t.length;e++){let r=t[e];if(r.type.startsWith(`image/`)){let e=r.getAsFile();e&&n.push(e)}}if(n.length>0){if(!_n){I(`当前模型不支持图片输入`,`error`);return}e.preventDefault(),Rr(n)}},Kr=e=>{e.dataTransfer?.types?.includes(`Files`)&&(e.preventDefault(),ut(!0))},Yr=e=>{e.currentTarget.contains(e.relatedTarget)||ut(!1)},Xr=e=>{ut(!1);let t=Array.from(e.dataTransfer?.files??[]).filter(e=>e.type.startsWith(`image/`));if(t.length>0){if(e.preventDefault(),!_n){I(`当前模型不支持图片输入`,`error`);return}Rr(t)}},Zr=t=>{if(t.preventDefault(),!j||dn||!Tt.trim()&&Dt.length===0)return;if(Dt.length>0&&!_n){I(`当前模型不支持图片输入,请移除图片或切换至支持图文的模型`,`error`);return}if(Ot>0){I(`图片正在上传中,请稍候…`,`info`);return}let n=j.status===`running`,r=`pending:${tn()}`,i=j.id,a=Tt,o=Dt,s=new Set([...e.conversations.find(e=>e.id===i)?.messages.map(e=>e.id)??[],...e.queuedMessages?.map(e=>e.id)??[]]);L({type:`message.send`,conversationId:j.id,content:Tt,...Dt.length>0?{images:Dt}:{}},`send:${i}`,e=>e.conversations.find(e=>e.id===i)?.messages.some(e=>!s.has(e.id)&&e.role===`user`&&e.content===a.trim())||e.queuedMessages?.some(e=>!s.has(e.id)&&e.conversationId===i&&e.content===a.trim())||n?e:{...e,conversations:e.conversations.map(e=>e.id===i?{...e,messages:[...e.messages,{id:r,role:`user`,content:a,images:o,createdAt:new Date().toISOString()}]}:e)},void 0,()=>{nt(e=>[...e,{id:r,conversationId:i,content:a,images:o}]),M(i,e=>e.text||e.images.length?e:{...e,text:a,images:o})},e=>!!(e.conversations.find(e=>e.id===i)?.messages.some(e=>!s.has(e.id)&&e.role===`user`&&e.content===a.trim())||e.queuedMessages?.some(e=>!s.has(e.id)&&e.conversationId===i&&e.content===a.trim())))?M(j.id,e=>({...e,text:``,images:[]})):I(`连接断开,消息未发送,草稿已保留,请重试`,`error`)},Qr=(0,p.useMemo)(()=>(o.queuedMessages??[]).filter(e=>e.conversationId===j?.id),[o.queuedMessages,j?.id]),$r=e=>{L({type:`message.cancel`,conversationId:j?.id??``,queueId:e},`queue:${e}`,t=>({...t,queuedMessages:t.queuedMessages?.filter(t=>t.id!==e)}))||I(`连接断开,取消没有生效,请重试`,`error`)},ei=e=>{L({type:`message.steer`,conversationId:j?.id??``,queueId:e},`queue:${e}`,t=>({...t,queuedMessages:t.queuedMessages?.map(t=>t.id===e?{...t,priority:!0}:t)}))||I(`连接断开,优先发送没有生效,请重试`,`error`)},ni=e=>{L({type:`message.sendQueued`,conversationId:j?.id??``,queueId:e},`send-queued:${e}`,t=>({...t,queuedMessages:t.queuedMessages?.filter(t=>t.id!==e)}),void 0,void 0,t=>!t.queuedMessages?.some(t=>t.id===e))||I(`连接断开,发送没有生效,请重试`,`error`)},[ri,ii]=(0,p.useState)(),ai=(e,t=!1)=>{if(!j||ri)return;let n=t?j.messages.find(t=>t.id===e):void 0;n&&($e(e=>{let t=e[j.id]??{text:``,images:[],uploading:0};return t.text.trim()||t.images.length?e:{...e,[j.id]:{...t,text:n.content,images:n.images??[]}}}),Ge({conversationId:j.id,messageId:e})),cn({type:`message.revert`,conversationId:j.id,messageId:e,withdraw:t})?ii(e):(Ge(void 0),I(`连接断开,回退未执行,请重试`,`error`))},[oi,si]=(0,p.useState)(),li=(0,p.useRef)(void 0),ui=async(e,t)=>{li.current&&clearTimeout(li.current);let n=await mr(t);si({id:e,kind:n?`copied`:`error`}),n||I(`复制失败:浏览器拒绝了剪贴板写入,可以手动选中这条消息的文字复制`,`error`),li.current=setTimeout(()=>si(void 0),2e3)};(0,p.useEffect)(()=>()=>{li.current&&clearTimeout(li.current)},[]);let[di,pi]=(0,p.useState)(),hi=e=>{di||e.startsWith(`pending:`)||(cn({type:`conversation.fork`,conversationId:e})?pi(e):I(`连接断开,分叉没有执行,请重试`,`error`))};return(0,m.jsxs)(`main`,{className:`shell${De?` shell-rail-collapsed`:``} mobile-panel-${A}`,"data-rail-collapsed":De,"data-selected-workspace":_??``,style:{"--sidebar-width":`${Ne.sidebar}px`,"--rail-col":De?void 0:`${Ne.rail}px`},children:[(0,m.jsxs)(`aside`,{children:[(0,m.jsxs)(`div`,{className:`brand`,children:[(0,m.jsx)(`span`,{children:`π`}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`strong`,{children:`SUPER PI`}),(0,m.jsx)(`small`,{children:`agent workspace`})]})]}),(0,m.jsx)(`div`,{className:`sidebar-actions`,children:(0,m.jsx)(`button`,{className:`workspace-new`,onClick:()=>b(!0),children:`+ 工作区`})}),(0,m.jsx)(`div`,{className:`label`,children:`工作区`}),(0,m.jsx)(`nav`,{children:o.workspaces.map(e=>{let t=o.conversations.filter(t=>t.workspaceId===e.id),n=t.filter(e=>!e.archivedAt).sort(lr),r=t.filter(e=>e.archivedAt).sort(ur),i=h[e.id]??!1,a=se[e.id]??!0;return(0,m.jsxs)(`section`,{className:`workspace-group`,children:[(0,m.jsx)(`div`,{className:`workspace-header`,children:Qn(`workspace`,e.id)?(0,m.jsx)(Br,{initial:e.name,label:`重命名工作区 ${e.name}`,onCommit:t=>nr(`workspace`,e.id,t),onClose:Zn}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`button`,{className:`workspace-toggle`,"aria-expanded":!i,title:e.path,onContextMenu:t=>{t.preventDefault();let n=t.currentTarget.getBoundingClientRect();Je({workspace:e,x:t.clientX||n.left+24,y:t.clientY||n.top+n.height})},onClick:()=>{v(e.id),c(yt.find(t=>t.workspaceId===e.id)?.id),g(t=>({...t,[e.id]:!i}))},children:[(0,m.jsx)(`span`,{className:`chevron chevron-folder`,"aria-hidden":`true`,children:i?`📁`:`📂`}),(0,m.jsxs)(`span`,{children:[(0,m.jsx)(`strong`,{onDoubleClick:()=>Xn(`workspace`,e.id),children:e.name}),(0,m.jsx)(`small`,{children:e.path})]})]}),(0,m.jsx)(`button`,{className:`workspace-add`,title:`在此工作区新建会话`,onClick:()=>Ar(e.id),children:`+`}),(0,m.jsx)(`button`,{className:`workspace-settings`,title:`工作区设置(默认智能体 / 模型 / 思考强度)`,"aria-label":`工作区设置 ${e.name}`,onClick:()=>or(e.id),children:`⚙`}),(0,m.jsx)(`button`,{className:`workspace-delete`,title:`删除工作区`,onClick:()=>ir(e),children:`×`})]})}),!i&&(n.length?n.map(t=>(0,m.jsx)(`div`,{className:`conversation-row`,children:Qn(`conversation`,t.id)?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(Br,{initial:t.title,label:`重命名会话 ${t.title}`,onCommit:e=>nr(`conversation`,t.id,e),onClose:Zn}),(0,m.jsx)(`small`,{className:`conversation-time`,children:cr(t.updatedAt,_t)})]}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`button`,{className:`conversation ${j?.id===t.id?`selected`:``}`,"data-conversation":t.id,title:t.title,"aria-label":`打开会话 ${t.title}`,onContextMenu:e=>{e.preventDefault();let n=e.currentTarget.getBoundingClientRect();Xe({conversation:t,x:e.clientX||n.left+24,y:e.clientY||n.top+n.height})},onClick:()=>{zt(t.id),v(e.id)},children:[(0,m.jsx)(`i`,{className:`conversation-mark`,children:(0,m.jsx)(Jr,{state:qr(t,le.some(e=>e.conversationId===t.id),C.current[t.id])})}),(0,m.jsx)(`span`,{"data-conversation-title":t.id,onDoubleClick:()=>Xn(`conversation`,t.id),children:t.title}),(0,m.jsx)(`small`,{children:cr(t.updatedAt,_t)})]}),(0,m.jsx)(`button`,{type:`button`,className:`conversation-fork`,"data-fork-conversation":t.id,"data-fork-state":di===t.id?`pending`:`idle`,disabled:!!di,title:`从此会话分叉出一个新会话`,"aria-label":`从会话 ${t.title} 分叉出一个新会话`,onClick:()=>hi(t.id),children:`⑂`}),(0,m.jsx)(`button`,{className:`conversation-archive`,title:`归档会话`,"aria-label":`归档会话 ${t.title}`,onClick:()=>jr(t.id),children:`×`})]})},t.id)):(0,m.jsx)(`div`,{className:`conversation-empty`,children:`暂无会话`})),!i&&r.length>0&&(0,m.jsxs)(`div`,{className:`archived-group`,"data-archived-count":r.length,children:[(0,m.jsxs)(`button`,{className:`archived-toggle`,title:a?`展开已归档会话`:`收起已归档会话`,"aria-expanded":!a,onClick:()=>ce(t=>({...t,[e.id]:!a})),children:[(0,m.jsx)(`span`,{className:`chevron`,"aria-hidden":`true`,children:a?`▸`:`▾`}),(0,m.jsxs)(`span`,{className:`archived-label`,children:[`Archived (`,r.length,`)`]})]}),!a&&r.map(e=>(0,m.jsx)(`div`,{className:`conversation-archived`,"data-archived-at":e.archivedAt,children:Qn(`conversation`,e.id)?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(Br,{initial:e.title,label:`重命名已归档会话 ${e.title}`,onCommit:t=>nr(`conversation`,e.id,t),onClose:Zn}),(0,m.jsx)(`small`,{children:dr(e.archivedAt)})]}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`i`,{className:`conversation-mark`,"aria-hidden":`true`}),(0,m.jsx)(`span`,{"data-archived-title":e.id,onDoubleClick:()=>Xn(`conversation`,e.id),children:e.title}),(0,m.jsx)(`small`,{children:dr(e.archivedAt)}),(0,m.jsx)(`button`,{type:`button`,className:`conversation-fork`,"data-fork-conversation":e.id,"data-fork-state":di===e.id?`pending`:`idle`,disabled:!!di,title:`从此会话分叉出一个新会话`,"aria-label":`从已归档会话 ${e.title} 分叉出一个新会话`,onClick:()=>hi(e.id),children:`⑂`}),(0,m.jsx)(`button`,{className:`conversation-restore`,title:`恢复为正常会话`,"aria-label":`恢复会话 ${e.title}`,onClick:()=>Nr(e.id),children:`↑`})]})},e.id))]})]},e.id)})}),(0,m.jsxs)(`footer`,{children:[(0,m.jsxs)(`div`,{className:`footer-status`,children:[(0,m.jsx)(`i`,{className:l?`online`:`offline`}),l?`已连接`:`正在连接`,(0,m.jsx)(`span`,{children:`本地持久化`})]}),(0,m.jsxs)(`button`,{type:`button`,className:`theme-settings-trigger`,"data-theme-open":`1`,"aria-haspopup":`dialog`,"aria-expanded":yr,onClick:()=>br(!0),children:[(0,m.jsx)(`span`,{"aria-hidden":`true`,children:`⚙`}),`设置`]}),(0,m.jsxs)(`button`,{type:`button`,className:`theme-settings-trigger`,"data-help-open":`1`,"aria-haspopup":`dialog`,"aria-expanded":Sr,onClick:()=>Cr(!0),children:[(0,m.jsx)(`span`,{"aria-hidden":`true`,children:`📖`}),`使用指南`]}),(0,m.jsxs)(`button`,{type:`button`,className:`theme-settings-trigger restart-needed-trigger`,title:`检查 Super Pi 更新`,onClick:async()=>{Ee(`updating`);try{let e=await fetch(`/api/update-check`);if(!e.ok)throw Error(`check failed`);let t=await e.json();if(t.needsRestart)I(`当前代码已更新,正在重启服务…`,`info`);else if(t.updateAvailable){if(!(await fetch(`/api/update`,{method:`POST`})).ok)throw Error(`update failed`);I(`发现新版本 v${t.latestVersion},正在更新并重启…`,`info`)}else I(`当前已是最新版本`,`info`)}catch{I(`检查更新失败,请检查网络或服务日志`,`error`)}finally{Ee(`idle`)}},children:[(0,m.jsx)(`span`,{"aria-hidden":`true`,children:Te===`updating`?`⟳`:`↻`}),Te===`updating`?`正在检查更新…`:`检查更新`]}),O?.needsRestart&&(0,m.jsxs)(`button`,{type:`button`,className:`theme-settings-trigger restart-needed-trigger`,title:`代码已更新:当前运行 v${O.runningVersion},磁盘版本 v${O.diskVersion}。点击复制重启命令 /super_pi restart`,onClick:async()=>{Ee(`updating`);try{if(!(await fetch(`/api/update`,{method:`POST`})).ok)throw Error(`update failed`);I(`正在更新 Super Pi,服务即将重启…`,`info`)}catch{Ee(`idle`),I(`更新启动失败,请检查服务日志`,`error`)}},children:[(0,m.jsx)(`span`,{"aria-hidden":`true`,children:Te===`updating`?`⟳`:`⚠️`}),Te===`updating`?`正在更新并重启…`:`更新并重启服务`]})]})]}),(0,m.jsx)(wi,{side:`left`,width:Ne.sidebar,min:Ne.sidebarMin,max:Ne.sidebarMax,label:`调整左侧栏宽度`,onWidth:Pe}),(0,m.jsxs)(`section`,{className:`chat`,"data-main-view":Kt,"data-main-view-kind":Kt,children:[Zt.length>0&&(0,m.jsx)(`div`,{className:`chat-tab-strip`,"data-chat-tab-strip":`1`,"data-session-count":Lt.length,"data-file-count":N.open.length,children:(0,m.jsx)(At,{tabs:Zt,prefix:`workspace-tab`,ariaLabel:`工作区标签页`,activeId:Qt,onSelect:$t,onClose:en,minWidth:120,maxWidth:320})}),(0,m.jsxs)(`header`,{children:[(0,m.jsxs)(`div`,{className:`chat-head`,children:[(0,m.jsx)(`h1`,{children:j?.title??`准备开始`}),pe.size>0?[...pe].map(([e,t])=>(0,m.jsx)(`p`,{"data-role":`run-status`,"data-status-key":e,children:`扩展状态:${e?`${e} · `:``}${t}`},e)):(0,m.jsx)(`p`,{"data-role":`run-status`,children:j?.status===`running`?`Agent 正在工作`:`Pi runtime · Web 控制台`})]}),(0,m.jsxs)(`span`,{className:`chat-view chat-view-${Kt}`,"data-main-view-indicator":Kt,"data-main-view-kind":Kt,title:Kt===`file`?`中间主画面正在显示文件 ${N.active?.path??``}`:`中间主画面正在显示这个会话的消息流`,children:[(0,m.jsx)(`span`,{className:`chat-view-label`,children:`主区显示`}),(0,m.jsx)(`span`,{className:`chat-view-kind`,children:Kt===`file`?`文件`:`会话`}),Kt===`file`&&N.active&&(0,m.jsx)(`span`,{className:`chat-view-name`,"data-main-view-name":N.active.name,children:N.active.name})]}),(0,m.jsx)(`div`,{className:`badge`,children:j?.status??`idle`})]}),d&&(0,m.jsx)(`div`,{className:`error`,children:d}),j?.error&&(0,m.jsx)(`div`,{className:`error`,"data-role":`conversation-error`,children:j.error}),_e&&(0,m.jsxs)(`div`,{className:`extui-title-note`,children:[`扩展建议标题:`,_e]}),de.length>0&&(0,m.jsx)(`div`,{className:`toasts`,role:`status`,"aria-live":`polite`,"data-toast-count":de.length,children:de.map(e=>(0,m.jsx)(`div`,{className:`toast toast-${e.kind}`,"data-toast-kind":e.kind,children:e.text},e.key))}),Kt===`file`?(0,m.jsx)(`div`,{className:`chat-file-view`,"data-main-file-view":F?.path,"data-file-view-kind":`editor`,children:F?(0,m.jsx)(wt,{file:F,state:N.saves[F.path]?.state??`idle`,message:N.saves[F.path]?.message??``,external:N.external[F.path]===!0,onChange:e=>N.updateBuffer(F.path,e),onSave:()=>void N.save(F.path,!1),onReload:()=>void N.reload(F.path),onOverwrite:()=>void N.save(F.path,!0)}):(0,m.jsx)(`p`,{className:`rail-empty`,"data-main-file-empty":`1`,children:`没有选中的文件。`})}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`div`,{className:`messages`,ref:ee,"data-message-scroll-container":j?.id??``,onScroll:e=>{let t=e.currentTarget;t.dataset.programmaticScroll===`true`?delete t.dataset.programmaticScroll:St(t)},children:[!j&&(0,m.jsxs)(`div`,{className:`empty`,children:[(0,m.jsx)(`div`,{className:`orb`,children:`π`}),(0,m.jsx)(`h2`,{children:`开始一个新会话`}),o.workspaces.length===0?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`p`,{children:`先创建一个工作区,再开始会话。`}),(0,m.jsx)(`button`,{onClick:()=>b(!0),children:`+ 新建工作区`})]}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`p`,{children:o.workspaces.length===1&&bt?`在「${bt.name}」中创建会话,即可向 Super Pi 发送任务。`:`选择工作区即可开始会话,向 Super Pi 发送任务。`}),o.workspaces.length>1&&(0,m.jsxs)(`div`,{className:`empty-workspace-select`,children:[(0,m.jsx)(`label`,{htmlFor:`empty-workspace-choice`,children:`工作区:`}),(0,m.jsxs)(`select`,{id:`empty-workspace-choice`,"aria-label":`选择工作区`,value:bt?.id,onChange:e=>{e.target.value===`__new__`?b(!0):v(e.target.value)},children:[o.workspaces.map(e=>(0,m.jsx)(`option`,{value:e.id,children:e.name},e.id)),(0,m.jsx)(`option`,{value:`__new__`,children:`+ 新建工作区…`})]})]}),bt&&(0,m.jsx)(`button`,{onClick:()=>Ar(bt.id),children:`新建会话`}),(0,m.jsx)(`span`,{className:`empty-secondary-action`,role:`button`,tabIndex:0,onClick:()=>b(!0),onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),b(!0))},children:`+ 新建工作区`})]})]}),Ln.map(e=>{if(e.startsWith(`m:`)){let t=Pn.get(e.slice(2));if(!t)return null;let n=!j?.messages.some(n=>n.id!==t.id&&n.role===`user`&&Ln.indexOf(`m:${n.id}`)>Ln.indexOf(e)),r=t.role===`user`&&j?.status!==`running`&&ri!==t.id,i=r&&n&&!t.id.startsWith(`pending:`),a=r&&!n&&!!t.piEntryId,o=t.content?(0,m.jsx)(qe,{source:t.content}):(0,m.jsx)(`span`,{className:`typing`,children:`正在思考`}),s=t.toolCalls??[];if(t.role===`user`){let n=oi?.id===t.id?oi.kind:void 0,r=t.content||(t.images?.length?`[图片]`:``);return(0,m.jsxs)(`article`,{className:`message user`,"data-transcript-key":e,children:[(0,m.jsxs)(`div`,{className:`message-body`,children:[(0,m.jsxs)(`div`,{className:`bubble`,children:[(0,m.jsxs)(`div`,{className:`meta`,children:[`你`,(0,m.jsx)(`time`,{children:tr(t.createdAt)})]}),t.images&&t.images.length>0&&(0,m.jsx)(`div`,{className:`message-images`,"data-message-images":`1`,children:t.images.map(e=>(0,m.jsx)(`button`,{type:`button`,className:`message-image-btn`,"data-message-image-id":e.id,onClick:()=>ct({url:`/api/upload/${encodeURIComponent(j?.id??``)}/${encodeURIComponent(e.id)}`,name:e.name,bytes:e.bytes}),title:e.name?`查看大图:${e.name}`:`查看大图`,children:(0,m.jsx)(`img`,{src:`/api/upload/${encodeURIComponent(j?.id??``)}/${encodeURIComponent(e.id)}`,alt:e.name||`图片`,className:`message-image-thumb`,loading:`lazy`})},e.id))}),(0,m.jsx)(`div`,{className:`content`,children:o})]}),(0,m.jsxs)(`div`,{className:`message-actions`,children:[(0,m.jsx)(`button`,{type:`button`,className:`message-copy`,"data-copy-message":t.id,"data-copy-state":n,"aria-label":`复制这条消息:${r}`,onClick:()=>ui(t.id,r),children:n===`copied`?`已复制`:n===`error`?`复制失败`:`复制`}),i&&(0,m.jsx)(`button`,{type:`button`,className:`message-revert`,"data-withdraw-message":t.id,title:`撤回并编辑:删除这条消息并将文字恢复到输入框继续编辑`,onClick:()=>ai(t.id,!0),children:`撤回`}),a&&(0,m.jsx)(`button`,{type:`button`,className:`message-revert`,"data-revert-message":t.id,title:`回退到这里:删除后续全部内容(Pi 的记录和这里的历史一起清掉,不会新建会话,也不动任何代码文件)`,onClick:()=>ai(t.id),children:`回退`})]})]}),(0,m.jsx)(`div`,{className:`avatar`,children:`你`})]},e)}let c=t.thinking?.trim()?t.thinking:``,l=(e,n)=>{let r=typeof e.at==`number`&&Number.isFinite(e.at)?e.at:n;return Math.max(0,Math.min(r,t.content.length))},u=new Set(s.map((e,t)=>c&&typeof e.thinkingAt==`number`&&e.thinkingAt<c.length?t:-1).filter(e=>e>=0)),d=[],f=0,p=s.map((e,t)=>({call:e,index:t,at:l(e,t)})).filter(({index:e})=>!u.has(e)).sort((e,t)=>e.at-t.at||e.index-t.index);for(let{call:e,index:n,at:r}of p){let i=Math.max(f,r);i>f&&d.push({text:t.content.slice(f,i)}),f=i,d.push({call:e,index:n})}d.push({text:t.content.slice(f)});let h=[];if(c){let e=0,t=s.map((e,t)=>({call:e,index:t,at:Math.max(0,Math.min(e.thinkingAt??0,c.length))})).filter(({index:e})=>u.has(e)).sort((e,t)=>e.at-t.at||e.index-t.index);for(let{call:n,index:r,at:i}of t){let t=Math.max(e,i);t>e&&h.push({text:c.slice(e,t)}),e=t,h.push({call:n,index:r})}h.push({text:c.slice(e)})}let g=c.split(`
|
|
53
53
|
`).map(e=>e.trim()).find(e=>e.length>0)??``,_=e=>e.call.question?(0,m.jsx)(`div`,{className:`call-blocks`,"data-call-block-index":e.index,children:(0,m.jsx)(Lr,{question:e.call.question,index:e.index,expanded:`${t.id}:${e.index}`in He?!!He[`${t.id}:${e.index}`]:!0,onToggle:()=>Bn(t.id,e.index),onAnswer:(n,r)=>fn(j?.id??``,t.id,e.index,n,r)})}):(0,m.jsx)(`div`,{className:`call-blocks`,"data-call-block-index":e.index,children:(0,m.jsx)(Mr,{call:e.call,index:e.index,expanded:`${t.id}:${e.index}`in Be&&!!Be[`${t.id}:${e.index}`],onToggle:()=>zn(t.id,e.index)})});return(0,m.jsxs)(`article`,{className:`message assistant`,"data-transcript-key":e,children:[(0,m.jsx)(`div`,{className:`avatar`,children:`π`}),(0,m.jsxs)(`div`,{className:`message-body`,children:[(0,m.jsxs)(`div`,{className:`meta`,children:[t.agentIdentity?.name??`Super Pi`,(0,m.jsx)(`time`,{children:tr(t.createdAt)})]}),c?(0,m.jsx)(Pr,{messageId:t.id,nestedCount:u.size,preview:g,expanded:Vn[t.id]===!0,onToggle:()=>Un(t.id),children:h.map((e,t)=>`text`in e?e.text?(0,m.jsx)(`div`,{className:`content thinking-text`,children:(0,m.jsx)(qe,{source:e.text})},`t${t}`):null:_(e))}):null,d.map((e,t)=>`text`in e?e.text?(0,m.jsx)(`div`,{className:`content`,children:(0,m.jsx)(qe,{source:e.text})},`t${t}`):null:_(e))]})]},e)}if(e.startsWith(`w:`)){let t=Mn.get(e.slice(2));return t?(0,m.jsxs)(`div`,{"data-transcript-key":e,children:[n.some(e=>e.key===`stop:${t.id}`)&&(0,m.jsx)(`span`,{children:`停止中…`}),(0,m.jsx)(Rt,{workflow:t,names:Nn,stopping:n.some(e=>e.key===`stop:${t.id}`),onStop:()=>Gn(t.id)},e)]},e):null}let t=In.get(e.slice(2));return t?(0,m.jsxs)(`div`,{"data-transcript-key":e,children:[n.some(e=>e.key===`stop:${t.id}`)&&(0,m.jsx)(`span`,{children:`停止中…`}),(0,m.jsx)(Fr,{run:t,stopping:n.some(e=>e.key===`stop:${t.id}`),name:Nn.get(t.agentId)??``,expanded:!!Re[t.id],onToggle:()=>Rn(t.id),onStop:()=>Wn(t.id)},e)]},e):null})]}),(0,m.jsxs)(`div`,{className:`stream-tail`,"data-stream-tail":`1`,"data-follow-tail":re.followTail?`true`:`false`,children:[(0,m.jsx)(`span`,{className:`stream-tail-status`,"data-run-status":j?.status??`idle`,"data-stream-state":l?j?.status===`running`?`streaming`:Qr.length?`waiting`:j?.status===`failed`?`failed`:`ready`:`waiting`,children:l?j?.status===`running`?`Streaming · 正在生成`:Qr.length?`Waiting · 消息排队中`:j?.status===`failed`?`运行失败`:j?.status===`stopped`?`已停止`:`就绪`:`连接中 / 等待连接`}),!re.followTail&&(0,m.jsx)(`button`,{type:`button`,className:`stream-tail-jump`,"data-jump-to-bottom":`1`,onClick:()=>{let e=ee.current;e&&(yi(e),e.scrollTop=e.scrollHeight,St(e,!1,!0))},children:`↓ 跳到底部`}),(0,m.jsx)(`span`,{className:`stream-tail-mode`,"data-follow-tail":re.followTail?`true`:`false`,children:re.followTail?`贴底`:`自由浏览`})]}),(0,m.jsx)(Ir,{items:Qr,pi:Ie.get(j?.id??``),running:j?.status===`running`,onCancel:$r,onSteer:ei,onSendQueued:ni}),(kn.length>0||[...he.values()].some(e=>e.placement===`aboveEditor`))&&(0,m.jsxs)(`div`,{className:`extui`,"data-extui-count":kn.length,children:[kn.map(e=>(0,m.jsx)(zr,{request:e.request,pending:n.some(t=>t.key===`answer:${e.conversationId}:${e.request.requestId}`),onAnswer:t=>pn(e.conversationId,e.request.requestId,t)},e.request.requestId)),Kn(`aboveEditor`)]}),(0,m.jsxs)(`form`,{onSubmit:Zr,onPaste:Gr,onDragOver:Kr,onDragLeave:Yr,onDrop:Xr,className:lt?`composer-dropzone-active`:void 0,children:[(0,m.jsx)(`textarea`,{ref:E,value:Tt,onCompositionStart:()=>{ft.current=!0},onCompositionEnd:()=>{ft.current=!1},onChange:e=>{kt(e.target.value);let t=e.target.value,n=e.target.selectionStart??t.length,r=t.slice(0,n),i=r.lastIndexOf(`/`),a=r.slice(i+1);i>=0&&!a.includes(` `)?Mt({visible:!0,query:a,rect:e.currentTarget.getBoundingClientRect()}):Mt({visible:!1,query:``,rect:null})},placeholder:j?_n?`描述你要完成的任务(支持粘贴/拖放图片)…`:`描述你要完成的任务…`:`先创建会话`,disabled:!j,onKeyDown:e=>{if(!(ft.current||er(e))){if(jt.visible){if(e.key===`Escape`){e.preventDefault(),Mt({visible:!1,query:``,rect:null});return}if([`ArrowDown`,`ArrowUp`,`Enter`].includes(e.key)){e.preventDefault();return}}e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),e.currentTarget.form?.requestSubmit())}}}),jt.visible&&jt.rect&&(0,m.jsx)(ot,{query:jt.query,anchorRect:jt.rect,command:cn,onSelect:e=>{let t=E.current?.selectionStart??Tt.length,n=Tt.slice(0,t),r=n.lastIndexOf(`/`),i=it(e,jt.query),a=`${n.slice(0,r)}/${i} ${Tt.slice(t)}`;kt(a),Mt({visible:!1,query:``,rect:null})},onClose:()=>Mt({visible:!1,query:``,rect:null})}),tt.filter(e=>e.conversationId===j?.id).map(e=>(0,m.jsxs)(`div`,{"data-failed-send":e.id,children:[(0,m.jsxs)(`span`,{children:[`发送失败:`,e.content]}),(0,m.jsx)(`button`,{type:`button`,disabled:!!(Tt||Dt.length),onClick:()=>{M(e.conversationId,t=>({...t,text:e.content,images:e.images})),nt(t=>t.filter(t=>t.id!==e.id))},children:`恢复草稿`}),(0,m.jsx)(`button`,{type:`button`,onClick:()=>nt(t=>t.filter(t=>t.id!==e.id)),children:`移除`})]},e.id)),rt.filter(e=>e.conversationId===j?.id).map(e=>(0,m.jsxs)(`div`,{"data-upload-preview":e.id,children:[(0,m.jsx)(`img`,{src:e.url,alt:e.name,width:48,height:48}),(0,m.jsx)(`span`,{children:e.failed?`上传失败`:`上传中…`}),(0,m.jsx)(`button`,{type:`button`,onClick:()=>{et.current.add(e.id),URL.revokeObjectURL(e.url),at(t=>t.filter(t=>t.id!==e.id))},children:`移除`})]},e.id)),(Dt.length>0||Ot>0)&&(0,m.jsxs)(`div`,{className:`composer-attachments`,"data-composer-attachments":`1`,children:[Dt.map((e,t)=>(0,m.jsxs)(`div`,{className:`composer-attachment-item`,"data-composer-attachment-id":e.id,children:[(0,m.jsx)(`img`,{src:`/api/upload/${encodeURIComponent(j?.id??``)}/${encodeURIComponent(e.id)}`,alt:e.name||`已附图片`,className:`composer-attachment-thumb`,onClick:()=>ct({url:`/api/upload/${encodeURIComponent(j?.id??``)}/${encodeURIComponent(e.id)}`,name:e.name,bytes:e.bytes}),title:`点击查看大图`}),(0,m.jsx)(`span`,{className:`composer-attachment-name`,title:e.name,children:e.name||`图片`}),(0,m.jsx)(`button`,{type:`button`,className:`composer-attachment-remove`,"data-composer-attachment-remove":e.id,onClick:()=>Nt(e=>e.filter((e,n)=>n!==t)),"aria-label":`移除 ${e.name||`图片`}`,title:`移除图片`,children:`✕`})]},e.id)),Ot>0&&(0,m.jsx)(`div`,{className:`composer-attachment-item composer-attachment-uploading`,children:(0,m.jsxs)(`span`,{children:[`图片上传中 (`,Ot,`)…`]})})]}),(0,m.jsxs)(`div`,{className:`composer`,children:[(0,m.jsxs)(`div`,{className:`session-picker`,"data-session-picker":`1`,children:[(0,m.jsx)(Vr,{kind:`agent`,label:Cn?.name??`跟随 Pi 默认`,value:j?.agentId??Hr,options:wn,disabled:!xe||xe.source===`unavailable`||dn,note:Or(xe),onChoose:Dn}),(0,m.jsx)(Vr,{kind:`model`,label:mn?.label??(ye?`Pi 默认`:`读取中…`),value:mn?`${mn.provider}/${mn.modelId}`:void 0,detail:En?`来自 ${Cn?.name}`:mn&&ye?.source===`pi`&&!j?.model?`Pi 默认模型`:mn?`${mn.provider}/${mn.modelId}`:void 0,options:yn,disabled:!gn||dn,note:Dr(`模型`,ye),onChoose:xn}),(0,m.jsx)(Vr,{kind:`thinking`,label:hn??(ye?`Pi 默认`:`读取中…`),value:hn,options:bn,disabled:!gn||dn,note:Dr(`思考等级`,ye),onChoose:Sn})]}),(0,m.jsxs)(`div`,{className:`composer-hints`,children:[(0,m.jsxs)(`button`,{type:`button`,className:`composer-attach-btn`,"data-composer-attach":`1`,onClick:()=>dt.current?.click(),disabled:!j||!_n||Ot>0,title:j?_n?`添加图片(支持剪贴板粘贴与拖拽)`:`当前模型不支持图片输入`:`请先创建或选择会话`,"aria-label":`添加图片`,children:[(0,m.jsx)(`span`,{"aria-hidden":`true`,children:`+`}),` 图片`]}),(0,m.jsx)(`input`,{ref:dt,type:`file`,accept:`image/png,image/jpeg,image/gif,image/webp`,multiple:!0,style:{display:`none`},onChange:e=>{e.target.files?.length&&(Rr(Array.from(e.target.files)),e.target.value=``)}}),(0,m.jsx)(`span`,{children:`Enter 发送 · Shift + Enter 换行`})]}),(0,m.jsxs)(`div`,{className:`composer-actions`,children:[j?.status===`running`&&(0,m.jsx)(`button`,{type:`button`,className:`stop`,"data-stop-run":j.id,disabled:n.some(e=>e.key===`stop:${j.id}`),onClick:()=>L({type:`run.stop`,conversationId:j.id},`stop:${j.id}`,e=>e),children:n.some(e=>e.key===`stop:${j.id}`)?`停止中…`:`停止`}),(0,m.jsx)(`button`,{className:`send ${j?.status===`running`?`send-queued`:``}`,"data-send-mode":j?.status===`running`?`queued`:`direct`,disabled:!Tt.trim()&&Dt.length===0||!j||Ot>0||!!ri||dn,title:j?ri?`正在撤回:Pi 的历史还没截断完成,撤回结束后即可发送`:!Tt.trim()&&Dt.length===0?`请输入消息或添加图片后发送`:Ot>0?`图片上传中…`:j.status===`running`?`这一轮结束后发送(发送后可在上面的排队区取消或插队)`:void 0:`请先创建或选择会话`,children:ri?`撤回中…`:j?.status===`running`?`排队发送 ↑`:`发送 ↑`})]})]})]}),Kn(`belowEditor`)]})]}),(0,m.jsx)(wi,{side:`right`,width:De?30:Ne.rail,min:Ne.railMin,max:Ne.railMax,label:`调整右侧栏宽度`,onWidth:Fe}),(0,m.jsxs)(`nav`,{className:`mobile-nav`,"aria-label":`移动端主导航`,children:[(0,m.jsxs)(`button`,{type:`button`,"data-mobile-nav":`workspaces`,className:A===`workspaces`?`active`:``,onClick:()=>Oe(`workspaces`),children:[`☰`,(0,m.jsx)(`span`,{children:`工作区`})]}),(0,m.jsxs)(`button`,{type:`button`,"data-mobile-nav":`chat`,className:A===`chat`?`active`:``,onClick:()=>Oe(`chat`),children:[`◉`,(0,m.jsx)(`span`,{children:`对话`})]}),(0,m.jsxs)(`button`,{type:`button`,"data-mobile-nav":`rail`,className:A===`rail`?`active`:``,onClick:()=>{Oe(`rail`),k(!1)},children:[`▣`,(0,m.jsx)(`span`,{children:`工具`})]})]}),` `,Ke&&(0,m.jsx)(hr,{workspace:Ke.workspace,x:Ke.x,y:Ke.y,notify:I,onClose:()=>Je(void 0)}),Ye&&(0,m.jsx)(gr,{conversation:Ye.conversation,x:Ye.x,y:Ye.y,notify:I,onRename:()=>void rr(Ye.conversation.id),onClose:()=>Xe(void 0)}),y&&(0,m.jsx)(wr,{onClose:()=>b(!1),onCreate:qn}),yr&&(0,m.jsx)(Fn,{workspaceId:_,theme:_r,onChooseTheme:e=>vr(e),onClose:()=>br(!1),agentCatalog:xe,subagentCatalog:Ce,modelFilterRules:o.modelFilterRules??[],pendingSettings:n.some(e=>e.key===`model-rules`||e.key===`agent-directories`),onSetModelRules:e=>L({type:`model.rules.set`,rules:e},`model-rules`,t=>({...t,modelFilterRules:e})),customAgentDirs:o.customAgentDirs??[],onSetCustomAgentDirs:e=>L({type:`agents.setCustomDirs`,dirs:e},`agent-directories`,t=>({...t,customAgentDirs:e})),onRescanAgents:()=>cn({type:`agents.rescan`})}),Sr&&(0,m.jsx)(Bt,{onClose:()=>Cr(!1)}),sr&&(0,m.jsx)(Ur,{workspace:sr,catalog:vn(ye,sr),agents:xe,onClose:()=>or(void 0),onRename:()=>{let e=sr.id;or(void 0),Xn(`workspace`,e)},onSave:(e,t,n)=>kr(sr.id,e,t,n)}),st&&(0,m.jsx)(ci,{image:st,onClose:()=>ct(void 0)}),(0,m.jsx)(ti,{todos:o.todosByConversation?.[j?.id??``]??[],tasks:o.backgroundTasks??[],collapsed:De,onToggle:()=>k(e=>!e),workspaceId:_,workspaceLabel:o.workspaces.find(e=>e.id===_)?.path,connected:l,files:N,onOpenFile:e=>void Yt(e),activeTab:Ht,onSelectTab:Ut,terminalAvailable:Wt,sendCommand:cn,registerTerminalSink:oe})]})}Dn(En()),(0,f.createRoot)(document.getElementById(`root`)).render((0,m.jsx)(p.StrictMode,{children:(0,m.jsx)(Ti,{})}));
|
package/dist/client/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<link rel="alternate icon" href="/favicon.ico" />
|
|
9
9
|
<link rel="apple-touch-icon" href="/favicon.svg" />
|
|
10
10
|
<title>Super Pi</title>
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-BYgM1GQA.js"></script>
|
|
12
12
|
<link rel="stylesheet" crossorigin href="/assets/index-Cb_uyk8r.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
@@ -382,10 +382,14 @@ export function createHttpServer(options) {
|
|
|
382
382
|
json(403, { error: result.message });
|
|
383
383
|
return;
|
|
384
384
|
}
|
|
385
|
-
// Validate cwd is a known workspace
|
|
386
|
-
|
|
385
|
+
// Validate cwd is a known workspace. Path comparison is normalized so Windows case
|
|
386
|
+
// differences or trailing separators do not produce a false "unknown workspace" failure
|
|
387
|
+
// when the extension hands back the same directory the server handed to it at spawn.
|
|
388
|
+
const normalized = (value) => value.replace(/[\\/]+/g, "/").replace(/\/+$/, "").toLowerCase();
|
|
389
|
+
const normalizedCwd = normalized(cwd);
|
|
390
|
+
const workspace = store.snapshot().workspaces.find((w) => normalized(w.path) === normalizedCwd);
|
|
387
391
|
if (!workspace) {
|
|
388
|
-
json(400, { error:
|
|
392
|
+
json(400, { error: `cwd is not a known workspace: ${cwd} (known: ${store.snapshot().workspaces.map((w) => w.path).join(" | ")})` });
|
|
389
393
|
return;
|
|
390
394
|
}
|
|
391
395
|
// Set up the background task record BEFORE spawning, so the UI shows it immediately
|
package/dist/server/runtime.js
CHANGED
|
@@ -6,7 +6,7 @@ import { resolve, join } from "node:path";
|
|
|
6
6
|
import { agentSpawnArgs, readAgents } from "./agents.js";
|
|
7
7
|
import { TASK_CAPABILITY_ENV, mintCapability, releaseCapability } from "./capability.js";
|
|
8
8
|
import { resolvePiCommand, shellQuote } from "./pi-command.js";
|
|
9
|
-
import { TASK_CONVERSATION_ENV, TASK_DEPTH_ENV, TASK_ENDPOINT_ENV, TASK_EXEC_ENDPOINT_ENV, TASK_ROSTER_ENV, TASK_TOOL_NAME, TODO_ENDPOINT_ENV, TODO_TOOL_NAME, WORKFLOW_ENDPOINT_ENV, WORKFLOW_TOOL_NAME, rosterPayload, } from "./task-tool.js";
|
|
9
|
+
import { TASK_CONVERSATION_ENV, TASK_DEPTH_ENV, TASK_ENDPOINT_ENV, TASK_EXEC_ENDPOINT_ENV, TASK_ROSTER_ENV, TASK_TOOL_NAME, TODO_ENDPOINT_ENV, TODO_TOOL_NAME, WORKFLOW_ENDPOINT_ENV, WORKFLOW_TOOL_NAME, RUN_ASYNC_TOOL_NAME, rosterPayload, } from "./task-tool.js";
|
|
10
10
|
import { BLOCKING_UI_METHODS, EXTENSION_UI_METHODS, } from "./types.js";
|
|
11
11
|
import { loadConversationImages } from "./upload.js";
|
|
12
12
|
import { describeToolCall, describeToolCallArgs, describeToolCallInProgress, extractPartialResultText, extractToolResultText, readQuestionCall } from "./tool-calls.js";
|
|
@@ -766,7 +766,7 @@ export class PiRpcRuntime {
|
|
|
766
766
|
// other. They also share the extension's existence - `extensionArgs` is non-empty exactly when
|
|
767
767
|
// `index.ts` is on disk and an endpoint was configured - so there is no case where one is mounted and
|
|
768
768
|
// the other is not.
|
|
769
|
-
const agentArgs = memoryReview ? ["--no-extensions", "--no-skills", "--no-mcp", "--no-context-files", "--no-prompt-templates", "--tools", "memory,skill_manage,session_search"] : await agentSpawnArgs(this.agents.promptDir, agent, { extraAllowedTools: [...(extensionArgs.length ? [TASK_TOOL_NAME, TODO_TOOL_NAME, WORKFLOW_TOOL_NAME, "question"] : []), ...(memoryEnabled ? ["memory", "skill_manage", "session_search"] : [])] });
|
|
769
|
+
const agentArgs = memoryReview ? ["--no-extensions", "--no-skills", "--no-mcp", "--no-context-files", "--no-prompt-templates", "--tools", "memory,skill_manage,session_search"] : await agentSpawnArgs(this.agents.promptDir, agent, { extraAllowedTools: [...(extensionArgs.length ? [TASK_TOOL_NAME, TODO_TOOL_NAME, WORKFLOW_TOOL_NAME, RUN_ASYNC_TOOL_NAME, "question"] : []), ...(memoryEnabled ? ["memory", "skill_manage", "session_search"] : [])] });
|
|
770
770
|
// Refused here, with the reason, rather than handed to the spawn: an ENOENT from `spawn` reads as
|
|
771
771
|
// "the app is broken" and hides the one fact that matters, which is where it looked for Pi.
|
|
772
772
|
if (!this.pi.found)
|
package/dist/server/store.js
CHANGED
|
@@ -968,10 +968,11 @@ export class Store {
|
|
|
968
968
|
// second while meaning the first.
|
|
969
969
|
if (outcome.result !== undefined)
|
|
970
970
|
call.result = outcome.result;
|
|
971
|
-
// The
|
|
972
|
-
//
|
|
973
|
-
|
|
974
|
-
|
|
971
|
+
// The streaming `live` preview is KEPT, not deleted. It accumulated during execution and is the
|
|
972
|
+
// full output a reader watched grow; the persisted `result` is a bounded 8KB tail of the same
|
|
973
|
+
// stream. Deleting live would replace the watched text with a possibly-different 8KB slice, and a
|
|
974
|
+
// finished tool block that vanishes the moment the call ends is a block that taught the reader
|
|
975
|
+
// nothing. The client renders `result` when present, falling back to `live` for the full preview.
|
|
975
976
|
conversation.updatedAt = now();
|
|
976
977
|
await this.persist();
|
|
977
978
|
return structuredClone(calls);
|
|
@@ -25,6 +25,15 @@ import type { AgentDefinition, TodoItem } from "./types.js";
|
|
|
25
25
|
*/
|
|
26
26
|
/** The name the model calls. Also the key Pi's tool allowlist matches on, and the deny key in `tools:`. */
|
|
27
27
|
export declare const TASK_TOOL_NAME = "task";
|
|
28
|
+
/**
|
|
29
|
+
* The independent background-command tool. NOT a sub-agent dispatch.
|
|
30
|
+
*
|
|
31
|
+
* Mirrored from `agents/super-pi-task/core.ts` for the same reason `TASK_TOOL_NAME` is: a tool name
|
|
32
|
+
* is a wire between two files Pi's module loader cannot cross, and `scripts/task-tool.test.mjs`
|
|
33
|
+
* asserts the two copies agree. Renaming on one side alone would fail at registerTool time with a
|
|
34
|
+
* message nobody reads.
|
|
35
|
+
*/
|
|
36
|
+
export declare const RUN_ASYNC_TOOL_NAME = "run_async";
|
|
28
37
|
/**
|
|
29
38
|
* How many task hops are allowed below a primary agent.
|
|
30
39
|
*
|
package/dist/server/task-tool.js
CHANGED
|
@@ -24,6 +24,15 @@
|
|
|
24
24
|
*/
|
|
25
25
|
/** The name the model calls. Also the key Pi's tool allowlist matches on, and the deny key in `tools:`. */
|
|
26
26
|
export const TASK_TOOL_NAME = "task";
|
|
27
|
+
/**
|
|
28
|
+
* The independent background-command tool. NOT a sub-agent dispatch.
|
|
29
|
+
*
|
|
30
|
+
* Mirrored from `agents/super-pi-task/core.ts` for the same reason `TASK_TOOL_NAME` is: a tool name
|
|
31
|
+
* is a wire between two files Pi's module loader cannot cross, and `scripts/task-tool.test.mjs`
|
|
32
|
+
* asserts the two copies agree. Renaming on one side alone would fail at registerTool time with a
|
|
33
|
+
* message nobody reads.
|
|
34
|
+
*/
|
|
35
|
+
export const RUN_ASYNC_TOOL_NAME = "run_async";
|
|
27
36
|
/**
|
|
28
37
|
* How many task hops are allowed below a primary agent.
|
|
29
38
|
*
|