@youweichen/pi-harness 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +14 -0
  2. package/dist/server/document-conversion/extension.js +164 -0
  3. package/dist/server/document-conversion/python/bridge.py +424 -0
  4. package/dist/server/document-conversion/python/fixtures.py +201 -0
  5. package/dist/server/document-conversion/python/native_code.py +149 -0
  6. package/dist/server/document-conversion/runtime.js +321 -0
  7. package/dist/server/document-conversion/service.js +340 -0
  8. package/dist/server/document-conversion/settings.js +63 -0
  9. package/dist/server/index.js +2 -0
  10. package/dist/server/native-tools.js +4 -0
  11. package/dist/server/okf/extension.js +118 -0
  12. package/dist/server/okf/markdown-sources.js +58 -0
  13. package/dist/server/okf/service.js +713 -0
  14. package/dist/server/okf/storage.js +165 -0
  15. package/dist/server/okf/types.js +1 -0
  16. package/dist/server/wiki-links.js +24 -0
  17. package/dist/server/wiki-service.js +37 -5
  18. package/package.json +2 -2
  19. package/web/dist/assets/{NodeWorkbench-BiP2ktQP.js → NodeWorkbench-DM6YTS5e.js} +1 -1
  20. package/web/dist/assets/{TerminalPanel-CKaSUsN-.js → TerminalPanel-aFJylyxg.js} +1 -1
  21. package/web/dist/assets/{abnfDiagram-VCTEODGH-CnwRJDRL.js → abnfDiagram-VCTEODGH-CcM7f7oX.js} +1 -1
  22. package/web/dist/assets/{arc-CG4Q7-W_.js → arc-Bv7vS5l5.js} +1 -1
  23. package/web/dist/assets/{architectureDiagram-5GKGNRK7-BrGqX_Rg.js → architectureDiagram-5GKGNRK7-Cl8QcB3w.js} +1 -1
  24. package/web/dist/assets/{blockDiagram-I7D4REHJ-C2t0PjZT.js → blockDiagram-I7D4REHJ-DarS2-4G.js} +1 -1
  25. package/web/dist/assets/{c4Diagram-7LVT6UL2-CadrcgGL.js → c4Diagram-7LVT6UL2-BY0_ttBt.js} +1 -1
  26. package/web/dist/assets/channel-DJGMgVTh.js +1 -0
  27. package/web/dist/assets/{chunk-2Q5K7J3B-CC3V2ITZ.js → chunk-2Q5K7J3B-Cz-zS7_X.js} +1 -1
  28. package/web/dist/assets/{chunk-5VM5RSS4-DqKSbGmE.js → chunk-5VM5RSS4-B7AyqkmI.js} +1 -1
  29. package/web/dist/assets/{chunk-F27PBJKO-_CDr3JbY.js → chunk-F27PBJKO-B7hVduzL.js} +1 -1
  30. package/web/dist/assets/{chunk-IMKFNOWR-BIR4H4fX.js → chunk-IMKFNOWR-DNGJqYn5.js} +1 -1
  31. package/web/dist/assets/{chunk-JWPE2WC7-CrsdBGXT.js → chunk-JWPE2WC7-B5iJgXvl.js} +1 -1
  32. package/web/dist/assets/{chunk-POPQ4Y6H-C6q9kQmf.js → chunk-POPQ4Y6H-BvWCkriR.js} +1 -1
  33. package/web/dist/assets/{chunk-SVP7TREG-l2XXTr2v.js → chunk-SVP7TREG-BcdlBuOQ.js} +1 -1
  34. package/web/dist/assets/{chunk-TICWLB2K-29I_mZgB.js → chunk-TICWLB2K-B1igqjQd.js} +1 -1
  35. package/web/dist/assets/{chunk-XXDRQBXY-htV9FBqi.js → chunk-XXDRQBXY-DKGDquaw.js} +1 -1
  36. package/web/dist/assets/classDiagram-ZZMXUADV-D9nxgF0M.js +1 -0
  37. package/web/dist/assets/classDiagram-v2-VYDZK3BY-D9nxgF0M.js +1 -0
  38. package/web/dist/assets/{cose-bilkent-JH36ORCC-Cop-ihyx.js → cose-bilkent-JH36ORCC-BU_9nu88.js} +1 -1
  39. package/web/dist/assets/{cynefin-OW5HDTMX-IEk8qBRq.js → cynefin-OW5HDTMX-DY0BDLjc.js} +1 -1
  40. package/web/dist/assets/{cynefinDiagram-5FMLGOSQ-Bmzt6Qb5.js → cynefinDiagram-5FMLGOSQ-B-zM25Fk.js} +1 -1
  41. package/web/dist/assets/{dagre-GXQ25YYZ-DiXTJYYU.js → dagre-GXQ25YYZ-BxooDyBc.js} +1 -1
  42. package/web/dist/assets/{diagram-S7CK7UJ4-BT7CLuNk.js → diagram-S7CK7UJ4-CCO-8de9.js} +1 -1
  43. package/web/dist/assets/{diagram-UQ7AKVKN-BZZ3nTCO.js → diagram-UQ7AKVKN-CmGsH525.js} +1 -1
  44. package/web/dist/assets/{diagram-VSXAHHWV-Dal8LeZh.js → diagram-VSXAHHWV-CSQJYo3m.js} +1 -1
  45. package/web/dist/assets/{diagram-VX7I27RA-D6V9FfNA.js → diagram-VX7I27RA-CwuJsF66.js} +1 -1
  46. package/web/dist/assets/{diagram-Z3DM3KII-KUAIcFiD.js → diagram-Z3DM3KII-BF13T_lj.js} +1 -1
  47. package/web/dist/assets/{ebnfDiagram-PWID7BFC-s0FEPZrV.js → ebnfDiagram-PWID7BFC-ZtoDLro6.js} +1 -1
  48. package/web/dist/assets/{erDiagram-RLTQ6QDP-CiIQPFCD.js → erDiagram-RLTQ6QDP-BBo-qmNH.js} +1 -1
  49. package/web/dist/assets/{flowDiagram-HODETNUW-CvG4MYWn.js → flowDiagram-HODETNUW-DAq9qdP8.js} +1 -1
  50. package/web/dist/assets/{ganttDiagram-EL5Y4UJY-CUf115ii.js → ganttDiagram-EL5Y4UJY-C53eRlMu.js} +1 -1
  51. package/web/dist/assets/{gitGraphDiagram-WWUBYQGX-o3K1r6fL.js → gitGraphDiagram-WWUBYQGX-BviBMJxj.js} +1 -1
  52. package/web/dist/assets/{index-C5or_GAq.js → index-Bab44wX8.js} +81 -81
  53. package/web/dist/assets/{infoDiagram-27XIBGKW-BxiBeQ8E.js → infoDiagram-27XIBGKW-DI95SO3j.js} +1 -1
  54. package/web/dist/assets/{ishikawaDiagram-5VMMS53U-B1ONuCkH.js → ishikawaDiagram-5VMMS53U-Cl8IDXwf.js} +1 -1
  55. package/web/dist/assets/{journeyDiagram-3NMN7TZE-DwmuoXcX.js → journeyDiagram-3NMN7TZE-Co6aJeTZ.js} +1 -1
  56. package/web/dist/assets/{kanban-definition-UXKFOSKX-pMKHubxH.js → kanban-definition-UXKFOSKX-CknQQpwW.js} +1 -1
  57. package/web/dist/assets/{layout-CEwfjQR0.js → layout-CFtUmtTW.js} +1 -1
  58. package/web/dist/assets/{linear-D22Gdbt1.js → linear-mRlGUAKy.js} +1 -1
  59. package/web/dist/assets/{mermaid.core-CO2nrD04.js → mermaid.core-CvQEO3ue.js} +5 -5
  60. package/web/dist/assets/{mindmap-definition-YA3MSWOX-9MQn9ZAp.js → mindmap-definition-YA3MSWOX-DpqhsxUl.js} +1 -1
  61. package/web/dist/assets/{pegDiagram-XKGWAZYB-Dy6fLjM-.js → pegDiagram-XKGWAZYB-C9eawB5u.js} +1 -1
  62. package/web/dist/assets/{pieDiagram-E7YTZNPT-EDLez6nA.js → pieDiagram-E7YTZNPT-8vaqXVD6.js} +1 -1
  63. package/web/dist/assets/{quadrantDiagram-AXDQQJYC-Cgcd9mvy.js → quadrantDiagram-AXDQQJYC-Diwr8ynm.js} +1 -1
  64. package/web/dist/assets/{railroadDiagram-O6MQD6OU-B4Td0tjj.js → railroadDiagram-O6MQD6OU-krW50Cgi.js} +1 -1
  65. package/web/dist/assets/{requirementDiagram-BXWQKSXE-aF2QNZ78.js → requirementDiagram-BXWQKSXE-BPLI6eMG.js} +1 -1
  66. package/web/dist/assets/{sankeyDiagram-P5KCCOFB-DgTYwYMa.js → sankeyDiagram-P5KCCOFB-Bix_elmH.js} +1 -1
  67. package/web/dist/assets/{sequenceDiagram-WJ2MYXX4-EUcddWUc.js → sequenceDiagram-WJ2MYXX4-0m0xaUKi.js} +1 -1
  68. package/web/dist/assets/{sizeCapture-INFHLROL-CXHOv9Sx.js → sizeCapture-INFHLROL-BtzJ_oOR.js} +1 -1
  69. package/web/dist/assets/{stateDiagram-D77RDMKH-B-xlgfaK.js → stateDiagram-D77RDMKH-Clq5bN0v.js} +1 -1
  70. package/web/dist/assets/stateDiagram-v2-MP3YSRHH-Bn1oW4gp.js +1 -0
  71. package/web/dist/assets/{swimlanes-42K2YHIH-BtFBOCDh.js → swimlanes-42K2YHIH-11MDGnYA.js} +1 -1
  72. package/web/dist/assets/swimlanesDiagram-VR7AAH4N-BW96Edgo.js +8 -0
  73. package/web/dist/assets/{timeline-definition-24CTP7MA-CZlQY6pb.js → timeline-definition-24CTP7MA-BeQfWP95.js} +1 -1
  74. package/web/dist/assets/{vennDiagram-4TSXK5OY-Cn61dJvL.js → vennDiagram-4TSXK5OY-BMYkX0KL.js} +1 -1
  75. package/web/dist/assets/{wardleyDiagram-VM6X3IG4-fiMNrWpr.js → wardleyDiagram-VM6X3IG4-BV3fTUkU.js} +1 -1
  76. package/web/dist/assets/{xychartDiagram-S5SC5T6Z-CuzM_sof.js → xychartDiagram-S5SC5T6Z-Ct7ezLnc.js} +1 -1
  77. package/web/dist/index.html +1 -1
  78. package/web/dist/assets/channel-C27Jizb6.js +0 -1
  79. package/web/dist/assets/classDiagram-ZZMXUADV-DYTBrAEP.js +0 -1
  80. package/web/dist/assets/classDiagram-v2-VYDZK3BY-DYTBrAEP.js +0 -1
  81. package/web/dist/assets/stateDiagram-v2-MP3YSRHH-kwAwAlWX.js +0 -1
  82. package/web/dist/assets/swimlanesDiagram-VR7AAH4N-D5j5Cj3S.js +0 -8
@@ -0,0 +1,165 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
+ import { dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
4
+ import { setTimeout as delay } from "node:timers/promises";
5
+ import { withFileMutationQueue } from "@earendil-works/pi-coding-agent";
6
+ import lockfile from "proper-lockfile";
7
+ import { documentDataDir } from "../document-conversion/settings.js";
8
+ const queues = new Map();
9
+ export const digest = (content) => createHash("sha256").update(content).digest("hex");
10
+ export const jsonText = (value) => JSON.stringify(value, null, 2) + "\n";
11
+ export function within(root, path) {
12
+ const part = relative(root, path);
13
+ return part === "" || (!part.startsWith(`..${sep}`) && part !== ".." && !isAbsolute(part));
14
+ }
15
+ /** Reject links at every component, including existing output parents. */
16
+ export function assertPlainPath(path) {
17
+ const absolute = resolve(path);
18
+ let current = parse(absolute).root;
19
+ for (const part of absolute.slice(current.length).split(sep).filter(Boolean)) {
20
+ current = join(current, part);
21
+ try {
22
+ if (lstatSync(current).isSymbolicLink())
23
+ throw new Error(`Symbolic links are not allowed: ${current}`);
24
+ }
25
+ catch (error) {
26
+ if (error.code !== "ENOENT")
27
+ throw error;
28
+ }
29
+ }
30
+ }
31
+ export function workspacePath(cwd) {
32
+ const result = realpathSync(cwd);
33
+ if (!lstatSync(result).isDirectory())
34
+ throw new Error("Workspace must be a directory");
35
+ return result;
36
+ }
37
+ export function safePath(root, child) {
38
+ const path = resolve(root, child);
39
+ if (!within(root, path) || path === root)
40
+ throw new Error(`Path escapes its managed root: ${child}`);
41
+ assertPlainPath(path);
42
+ return path;
43
+ }
44
+ export function privateDirectory(cwd) {
45
+ // realpath resolves platform-owned aliases such as macOS /var before checking our subtree.
46
+ const configured = documentDataDir();
47
+ mkdirSync(configured, { recursive: true, mode: 0o700 });
48
+ const root = join(realpathSync(configured), "document-jobs", digest(cwd).slice(0, 24));
49
+ assertPlainPath(root);
50
+ mkdirSync(root, { recursive: true, mode: 0o700 });
51
+ return root;
52
+ }
53
+ export function readJson(path, limit = 16 * 1024 * 1024) {
54
+ assertPlainPath(path);
55
+ const stat = lstatSync(path);
56
+ if (!stat.isFile() || stat.size > limit)
57
+ throw new Error(`Invalid or oversized state file: ${path}`);
58
+ return JSON.parse(readFileSync(path, "utf8"));
59
+ }
60
+ export function fileHash(path) {
61
+ assertPlainPath(path);
62
+ try {
63
+ const stat = lstatSync(path);
64
+ if (!stat.isFile() || stat.size > 256 * 1024 * 1024)
65
+ throw new Error(`Expected a bounded regular file: ${path}`);
66
+ return digest(readFileSync(path));
67
+ }
68
+ catch (error) {
69
+ if (error.code === "ENOENT")
70
+ return null;
71
+ throw error;
72
+ }
73
+ }
74
+ export function atomicWrite(path, contents) {
75
+ assertPlainPath(path);
76
+ mkdirSync(dirname(path), { recursive: true });
77
+ const temporary = `${path}.${randomUUID()}.tmp`;
78
+ try {
79
+ writeFileSync(temporary, contents, { encoding: "utf8", flag: "wx", mode: 0o600 });
80
+ assertPlainPath(path);
81
+ renameSync(temporary, path);
82
+ }
83
+ finally {
84
+ rmSync(temporary, { force: true });
85
+ }
86
+ }
87
+ /** Manifest is the final write. Replay accepts only the old content or our exact new content. */
88
+ export async function recoverTransaction(cwd) {
89
+ const journal = join(privateDirectory(cwd), "transaction.json");
90
+ if (!existsSync(journal))
91
+ return;
92
+ const transaction = readJson(journal, 64 * 1024 * 1024);
93
+ if (transaction.version !== 1 || transaction.cwd !== cwd || !Array.isArray(transaction.writes))
94
+ throw new Error("Invalid ingestion recovery journal");
95
+ if (!within(cwd, transaction.outputDirectory) || cwd === transaction.outputDirectory)
96
+ throw new Error("Recovery output is outside the workspace");
97
+ for (const item of transaction.writes) {
98
+ const path = safePath(transaction.outputDirectory, item.path);
99
+ await withFileMutationQueue(path, async () => {
100
+ const current = fileHash(path);
101
+ if (current === digest(item.contents))
102
+ return;
103
+ if (current !== item.expectedHash)
104
+ throw new Error(`Recovery preserved an externally modified file: ${item.path}. Restore the expected version or resolve this ingestion transaction before retrying.`);
105
+ atomicWrite(path, item.contents);
106
+ });
107
+ }
108
+ rmSync(journal);
109
+ }
110
+ export async function commitTransaction(cwd, writes, outputDirectory = join(cwd, "knowledge")) {
111
+ if (!writes.length)
112
+ return;
113
+ const journal = join(privateDirectory(cwd), "transaction.json");
114
+ if (existsSync(journal))
115
+ throw new Error("An ingestion transaction already needs recovery");
116
+ const contents = jsonText({ version: 1, cwd, outputDirectory, writes });
117
+ if (Buffer.byteLength(contents) > 64 * 1024 * 1024)
118
+ throw new Error("Ingestion transaction exceeds 64 MiB; publish a smaller batch. Previous state was preserved.");
119
+ atomicWrite(journal, contents);
120
+ await recoverTransaction(cwd);
121
+ }
122
+ function waitWithSignal(task, signal) {
123
+ if (!signal)
124
+ return task;
125
+ if (signal.aborted)
126
+ return Promise.reject(signal.reason ?? new Error("Ingestion cancelled"));
127
+ return new Promise((resolve, reject) => {
128
+ const abort = () => reject(signal.reason ?? new Error("Ingestion cancelled"));
129
+ signal.addEventListener("abort", abort, { once: true });
130
+ task.then(value => { signal.removeEventListener("abort", abort); resolve(value); }, error => { signal.removeEventListener("abort", abort); reject(error); });
131
+ });
132
+ }
133
+ export async function withKnowledgeLock(inputCwd, action, signal) {
134
+ signal?.throwIfAborted();
135
+ const cwd = workspacePath(inputCwd);
136
+ const prior = queues.get(cwd) ?? Promise.resolve();
137
+ const task = prior.catch(() => undefined).then(async () => {
138
+ signal?.throwIfAborted();
139
+ const folder = privateDirectory(cwd);
140
+ let release;
141
+ for (let attempt = 0; !release; attempt++) {
142
+ signal?.throwIfAborted();
143
+ try {
144
+ release = await lockfile.lock(folder, { realpath: false, stale: 120_000, retries: 0 });
145
+ }
146
+ catch (error) {
147
+ if (error.code !== "ELOCKED" || attempt >= 40)
148
+ throw error;
149
+ await delay(100, undefined, { signal });
150
+ }
151
+ }
152
+ try {
153
+ signal?.throwIfAborted();
154
+ await recoverTransaction(cwd);
155
+ return await action(cwd);
156
+ }
157
+ finally {
158
+ await release();
159
+ }
160
+ });
161
+ queues.set(cwd, task);
162
+ void task.finally(() => { if (queues.get(cwd) === task)
163
+ queues.delete(cwd); }).catch(() => undefined);
164
+ return waitWithSignal(task, signal);
165
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -98,6 +98,30 @@ export function wikiLinkIndex(paths) {
98
98
  }
99
99
  return { paths: new Set(paths), byName };
100
100
  }
101
+ /** Explicit relative file links can address evidence excluded from background indexing.
102
+ * The document/media endpoint still verifies existence and real workspace ownership. */
103
+ export function explicitWikiFilePath(source, target) {
104
+ let raw;
105
+ try {
106
+ raw = decodeURIComponent(target.split("#")[0]).replaceAll("\\", "/");
107
+ }
108
+ catch {
109
+ return;
110
+ }
111
+ if (!/^(?:\.\/|\.\.\/)/.test(raw) || /[\0\r\n?:]/.test(raw) || !/\.[a-z0-9]+$/i.test(raw))
112
+ return;
113
+ const parts = source.split("/").slice(0, -1);
114
+ for (const part of raw.split("/")) {
115
+ if (part === "..") {
116
+ if (!parts.length)
117
+ return;
118
+ parts.pop();
119
+ }
120
+ else if (part && part !== ".")
121
+ parts.push(part);
122
+ }
123
+ return parts.join("/") || undefined;
124
+ }
101
125
  export function resolveWikiLink(source, target, paths) {
102
126
  let raw;
103
127
  try {
@@ -11,8 +11,31 @@ const IGNORED = new Set([".git", "node_modules", ".pi-web", ".DS_Store"]);
11
11
  // Generated dependencies and duplicate checkouts must not consume the main
12
12
  // workspace's index or undo budget. Explicit directory/file requests stay usable.
13
13
  const TRAVERSAL_IGNORED_DIRS = new Set([".venv", "__pycache__", ".pytest_cache", ".mypy_cache", ".ruff_cache"]);
14
+ function isKnowledgeManifest(contents) {
15
+ try {
16
+ const manifest = JSON.parse(contents.toString());
17
+ return manifest?.kind === "pi-harness-knowledge" && manifest.version === 1 && manifest.evidenceDirectory === "evidence";
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
14
23
  function skipTraversalDirectory(parent, name) {
15
- return TRAVERSAL_IGNORED_DIRS.has(name) || (name === "worktrees" && basename(parent) === ".claude");
24
+ if (TRAVERSAL_IGNORED_DIRS.has(name) || (name === "worktrees" && basename(parent) === ".claude"))
25
+ return true;
26
+ if (name !== "evidence")
27
+ return false;
28
+ // Only the immutable evidence of a declared knowledge export is excluded.
29
+ // Ordinary user folders named evidence remain searchable and undoable.
30
+ try {
31
+ const marker = join(parent, "manifest.json"), info = lstatSync(marker);
32
+ if (!info.isFile() || info.size > 16 * 1024 * 1024)
33
+ return false;
34
+ return isKnowledgeManifest(readFileSync(marker));
35
+ }
36
+ catch {
37
+ return false;
38
+ }
16
39
  }
17
40
  const hash = (data) => createHash("sha256").update(data).digest("hex");
18
41
  export class WikiConflictError extends Error {
@@ -45,6 +68,10 @@ export function wikiPath(cwd, path) {
45
68
  }
46
69
  return absolute;
47
70
  }
71
+ function isKnowledgeEvidence(cwd, path) {
72
+ const root = realpathSync(cwd), parts = relative(root, wikiPath(cwd, path)).split(sep);
73
+ return parts.some((part, index) => part === "evidence" && skipTraversalDirectory(join(root, ...parts.slice(0, index)), part));
74
+ }
48
75
  function kindOf(path, text) {
49
76
  if (/\.(md|markdown|txt)$/i.test(path))
50
77
  return "document";
@@ -161,7 +188,7 @@ export class WikiService {
161
188
  }
162
189
  children.sort((a, b) => Number(b.isDirectory()) - Number(a.isDirectory()) || a.name.localeCompare(b.name));
163
190
  for (const child of children) {
164
- if (IGNORED.has(child.name) || child.isDirectory() && skipTraversalDirectory(path, child.name))
191
+ if (IGNORED.has(child.name) || child.isDirectory() && skipTraversalDirectory(wikiPath(cwd, path), child.name))
165
192
  continue;
166
193
  if (visited >= 20000) {
167
194
  limited = true;
@@ -282,7 +309,7 @@ export class WikiService {
282
309
  const data = size <= MAX_FILE ? readFileSync(abs) : undefined;
283
310
  const text = data && !/\.pdf$/i.test(path) && previewKind(path) !== "image" && looksLikeText(data) ? decodeText(data) : undefined;
284
311
  const metadata = wikiMetadata(text ?? "");
285
- return { entry: { path, name: basename(path), size, modified: info.mtimeMs, kind: kindOf(path, text !== undefined), tags: metadata.tags, title: metadata.title }, text, version: data ? hash(data) : "", editable: text !== undefined && Buffer.from(text).equals(data) };
312
+ return { entry: { path, name: basename(path), size, modified: info.mtimeMs, kind: kindOf(path, text !== undefined), tags: metadata.tags, title: metadata.title }, text, version: data ? hash(data) : "", editable: text !== undefined && Buffer.from(text).equals(data) && !isKnowledgeEvidence(cwd, path) };
286
313
  }
287
314
  async search(cwd, query) {
288
315
  const index = await this.index(cwd), q = query.trim().toLocaleLowerCase().slice(0, 200);
@@ -355,7 +382,7 @@ export class WikiService {
355
382
  }
356
383
  children.sort((a, b) => Number(b.isDirectory()) - Number(a.isDirectory()) || a.name.localeCompare(b.name));
357
384
  for (const child of children) {
358
- if (IGNORED.has(child.name) || child.isDirectory() && skipTraversalDirectory(path, child.name))
385
+ if (IGNORED.has(child.name) || child.isDirectory() && skipTraversalDirectory(wikiPath(cwd, path), child.name))
359
386
  continue;
360
387
  if (visited++ >= 20000) {
361
388
  skip(path);
@@ -461,6 +488,8 @@ export class WikiService {
461
488
  return { path };
462
489
  }
463
490
  write(cwd, path, text, version) {
491
+ if (isKnowledgeEvidence(cwd, path))
492
+ throw new Error("Knowledge evidence snapshots are read-only; edit the source and ingest a new version");
464
493
  if (this.busy(cwd))
465
494
  throw new Error("Wait for the current Wiki request to finish");
466
495
  const abs = wikiPath(cwd, path), data = readFileSync(abs), next = Buffer.from(text);
@@ -491,7 +520,10 @@ export class WikiService {
491
520
  if ((current ? hash(current) : null) !== (undo ? blob.after : blob.before))
492
521
  throw new Error(`File changed since this request: ${c.path}`);
493
522
  const target = undo ? blob.before : blob.after;
494
- return { abs, current, next: target ? readFileSync(join(this.folder(cwd), "blobs", target)) : null, c };
523
+ const next = target ? readFileSync(join(this.folder(cwd), "blobs", target)) : null;
524
+ if (basename(abs) === "manifest.json" && (current && isKnowledgeManifest(current) || next && isKnowledgeManifest(next)))
525
+ throw new Error("Knowledge ingestion contains versioned evidence and cannot be undone as a Wiki request. Use a new ingestion or restore the complete knowledge directory with version control.");
526
+ return { abs, current, next, c };
495
527
  });
496
528
  const done = [];
497
529
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youweichen/pi-harness",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -51,7 +51,7 @@
51
51
  "dev:web": "vite --config web/vite.config.ts",
52
52
  "build": "npm run build:web && npm run build:server",
53
53
  "build:web": "vite build --config web/vite.config.ts",
54
- "build:server": "tsc -p tsconfig.server.json",
54
+ "build:server": "tsc -p tsconfig.server.json && node scripts/copy-server-assets.mjs",
55
55
  "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
56
56
  "test": "node --test tests/check-design-tokens-test.mjs && npm run check:design && vitest run",
57
57
  "test:unit": "vitest run",
@@ -1,3 +1,3 @@
1
- import{a as r,j as e,M as Pn,b as Dn}from"./markdown-BhJ_LInD.js";import{u as Ee,b as jn,T as fn,r as je}from"./index-C5or_GAq.js";import{D as En,o as $n}from"./xterm-D1D2FVe3.js";/* empty css */import"./react-BddUxV-9.js";const Mn=r.memo(function({text:w}){return e.jsx(Pn,{remarkPlugins:[Dn],components:{a:({href:t,children:s})=>/^https?:\/\//.test(t??"")?e.jsx("a",{href:t,target:"_blank",rel:"noreferrer",children:s}):e.jsx("span",{children:s}),img:({alt:t})=>e.jsx("span",{children:t})},children:w})});function Rn({nodeId:P,defaultDir:w,connected:t,agent:s,request:ne,draft:T,setDraft:$,consumedEditors:J}){var oe;const u=Ee(),[te,se]=r.useState(w),[C,y]=r.useState({}),[b,G]=r.useState(""),[M,q]=r.useState(""),[z,le]=r.useState("followUp"),D=r.useRef(null),W=r.useRef(!0),x=s==null?void 0:s.dialogs[0],A=Object.keys(C).length>0,Q=Object.values(C).some(d=>d.action==="agent_dialog");r.useEffect(()=>{q((x==null?void 0:x.prefill)??"")},[x==null?void 0:x.id]),r.useEffect(()=>{s!=null&&s.editorText&&J[P]!==s.editorText.id&&(J[P]=s.editorText.id,$(s.editorText.text))},[s==null?void 0:s.editorText]),r.useEffect(()=>{W.current&&D.current&&(D.current.scrollTop=D.current.scrollHeight)},[s==null?void 0:s.messages,s==null?void 0:s.streamingMessage,s==null?void 0:s.tools]),r.useEffect(()=>{const d=a=>{var E;const S=a.detail,N=S.requestId?C[S.requestId]:void 0;S.nodeId!==P||!N||(S.event==="failure"&&(G(String(((E=S.data)==null?void 0:E.message)??"")),y(k=>{const R={...k};return delete R[S.requestId],R})),S.event==="result"&&(N.text!==void 0&&$(k=>k===N.text?"":k),y(k=>{const R={...k};return delete R[S.requestId],R})))};return window.addEventListener("pi-node-event",d),()=>window.removeEventListener("pi-node-event",d)},[P,C]),r.useEffect(()=>{t||y({})},[t]);const H=(d,a,S)=>{G("");const N=ne(d,P,a,void 0,s==null?void 0:s.id);N?y(E=>({...E,[N]:{action:d,text:S}})):G(u("nodeAgentOffline"))},ae=()=>{!T.trim()||A||!t||(s==null?void 0:s.phase)!=="ready"||(W.current=!0,H("agent_prompt",{text:T,...s.running?{queue:z}:{}},T))},U=[...(s==null?void 0:s.messages)??[],...s!=null&&s.streamingMessage?[s.streamingMessage]:[]],ce=new Map(U.filter(d=>d.role==="toolResult").map(d=>[d.toolCallId,d])),fe=d=>e.jsxs("article",{className:`node-agent-message ${d.role}`,children:[e.jsx("small",{children:d.role==="user"?u("nodeAgentYou"):"pi"}),d.errorMessage&&e.jsx("p",{role:"alert",className:"node-agent-error",children:d.errorMessage}),d.content.map((a,S)=>{if(a.type==="text"&&"text"in a&&typeof a.text=="string")return e.jsx(Mn,{text:a.text},S);if(a.type==="thinking"&&"thinking"in a&&typeof a.thinking=="string")return e.jsxs("details",{children:[e.jsx("summary",{children:u("nodeAgentThinking")}),e.jsx("pre",{children:a.thinking})]},S);if(a.type==="toolCall"&&"id"in a&&"name"in a){const N=ce.get(String(a.id)),E=s==null?void 0:s.tools.find(k=>k.id===a.id);return e.jsxs("details",{className:"node-agent-tool",children:[e.jsxs("summary",{children:[e.jsx("code",{children:String(a.name)}),e.jsx("span",{children:u(N!=null&&N.isError||E!=null&&E.isError?"error":N||E&&!E.running?"done":s!=null&&s.running?"running":"toolQueued")})]}),e.jsx("pre",{children:String(a.argumentsText??"")}),N==null?void 0:N.content.map((k,R)=>"text"in k&&typeof k.text=="string"?e.jsx("pre",{children:k.text},R):null)]},S)}return a.type==="image"&&"dataUrl"in a&&typeof a.dataUrl=="string"&&a.dataUrl.startsWith("data:image/")?e.jsx("img",{src:a.dataUrl,alt:u("toolResultImage")},S):null})]},d.id);return e.jsxs("section",{className:"node-agent","aria-label":u("nodeAgentTitle"),children:[e.jsxs("header",{children:[e.jsx("strong",{children:u("nodeAgentTitle")}),e.jsx("span",{children:s!=null&&s.model?`${s.model.provider} / ${s.model.name}`:u("nodeAgentRemote")}),(s==null?void 0:s.phase)==="ready"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{disabled:A||s.running||!t,onClick:()=>H("agent_new"),children:u("nodeAgentNew")}),e.jsx("button",{disabled:!t,onClick:()=>H("agent_close"),children:u("nodeAgentClose")})]})]}),(!s||s.phase==="closed")&&e.jsxs("div",{className:"node-agent-setup",children:[e.jsx("p",{children:u("nodeAgentSetup")}),e.jsxs("label",{children:[u("nodeDefaultDir"),e.jsx("input",{value:te,onChange:d=>se(d.target.value)})]}),e.jsx("button",{disabled:!t||A,onClick:()=>H("agent_start",{cwd:te}),children:u(A?"nodeAgentStarting":"nodeAgentStart")}),e.jsx("p",{className:"node-muted",children:u("nodeAgentInstall")}),e.jsx("code",{children:"npm install -g @earendil-works/pi-coding-agent@1.0.4"})]}),(s==null?void 0:s.phase)==="starting"&&e.jsx("p",{role:"status",children:u("nodeAgentStarting")}),!t&&e.jsx("p",{role:"status",children:u("nodeAgentOffline")}),(b||(s==null?void 0:s.error))&&e.jsx("p",{role:"alert",className:"node-agent-error",children:b||(s==null?void 0:s.error)}),(s==null?void 0:s.notice)&&e.jsx("p",{role:"status",className:"node-muted",children:s.notice}),e.jsxs("div",{className:"node-agent-feed",ref:D,onScroll:d=>{const a=d.currentTarget;W.current=a.scrollHeight-a.scrollTop-a.clientHeight<100},children:[U.filter(d=>d.role!=="toolResult"&&(d.errorMessage||d.content.some(a=>a.type==="toolCall"||a.type==="image"||"text"in a&&typeof a.text=="string"&&a.text.trim()||"thinking"in a&&typeof a.thinking=="string"&&a.thinking.trim()))).map(fe),(s==null?void 0:s.running)&&e.jsxs("p",{className:"node-agent-working",role:"status",children:[u("nodeAgentWorking"),s.tools.filter(d=>d.running).map(d=>e.jsx("code",{children:d.name},d.id))]})]}),x&&e.jsxs("form",{className:"node-agent-dialog",onSubmit:d=>{d.preventDefault(),H("agent_dialog",{id:x.id,value:M,confirmed:!0})},children:[e.jsx("strong",{children:x.title}),x.message&&e.jsx("p",{children:x.message}),x.method==="select"?e.jsxs("select",{"aria-label":x.title,required:!0,value:M,onChange:d=>q(d.target.value),children:[e.jsx("option",{value:"",disabled:!0,children:u("nodeAgentSelect")}),(oe=x.options)==null?void 0:oe.map(d=>e.jsx("option",{children:d},d))]}):x.method!=="confirm"&&e.jsx("textarea",{"aria-label":x.title,value:M,onChange:d=>q(d.target.value),rows:x.method==="editor"?6:2}),e.jsx("button",{disabled:Q||!t,type:"submit",children:u("confirm")}),e.jsx("button",{disabled:Q||!t,type:"button",onClick:()=>H("agent_dialog",{id:x.id,cancelled:!0}),children:u("cancel")})]}),(s==null?void 0:s.phase)==="ready"&&e.jsxs("form",{className:"node-agent-input",onSubmit:d=>{d.preventDefault(),ae()},children:[e.jsx("textarea",{"aria-label":u("nodeAgentPrompt"),placeholder:u("nodeAgentPrompt"),value:T,onChange:d=>$(d.target.value),rows:3,onKeyDown:d=>{d.key==="Enter"&&!d.shiftKey&&!d.nativeEvent.isComposing&&(d.preventDefault(),ae())}}),e.jsxs("div",{children:[e.jsxs("select",{"aria-label":u("nodeAgentModel"),value:s.model?JSON.stringify([s.model.provider,s.model.id]):"",disabled:s.running||A||!t,onChange:d=>{const[a,S]=JSON.parse(d.target.value);H("agent_model",{provider:a,modelId:S})},children:[e.jsx("option",{value:"",disabled:!0,children:u("nodeAgentModel")}),s.models.map(d=>e.jsxs("option",{value:JSON.stringify([d.provider,d.id]),children:[d.provider," / ",d.name]},`${d.provider}/${d.id}`))]}),s.running&&e.jsxs(e.Fragment,{children:[e.jsxs("select",{"aria-label":u("nodeAgentQueue"),value:z,onChange:d=>le(d.target.value),children:[e.jsx("option",{value:"followUp",children:u("nodeAgentFollowUp")}),e.jsx("option",{value:"steer",children:u("nodeAgentSteer")})]}),e.jsx("button",{type:"button",disabled:!t,onClick:()=>H("agent_abort"),children:u("stop")})]}),e.jsx("button",{type:"submit",disabled:!T.trim()||A||!t,children:u("nodeAgentSend")})]})]})]})}function Tn({nodeId:P,tab:w,active:t,send:s,initialOutput:ne}){const T=Ee(),$=r.useRef(null),J=r.useRef(w.closed);J.current=w.closed;const[u,te]=r.useState(""),[se,C]=r.useState("");return r.useEffect(()=>{if(!$.current)return;const y=getComputedStyle($.current),b=new En({theme:{...jn(),background:y.getPropertyValue("--node-terminal-bg").trim(),foreground:y.getPropertyValue("--node-terminal-fg").trim()},fontFamily:'"JetBrains Mono", Consolas, monospace',fontSize:13,scrollback:8e3,allowProposedApi:!0}),G=()=>{b.options.theme={...jn(),background:y.getPropertyValue("--node-terminal-bg").trim(),foreground:y.getPropertyValue("--node-terminal-fg").trim()}};window.addEventListener(fn,G);const M=new $n;b.loadAddon(M),b.open($.current),ne&&b.write(ne);const q=(x,A={})=>s({type:"node_request",action:x,requestId:je(),nodeId:P,terminalId:w.id,conversationId:w.conversationId,payload:A}),z=b.onData(x=>{J.current||q(x===""?"interrupt":"terminal_input",{data:x})}),le=b.onSelectionChange(()=>te(b.getSelection().slice(0,32e3))),D=x=>{var Q;const A=x.detail;A.nodeId!==P||A.terminalId!==w.id||A.event==="terminal_output"&&b.write(String(((Q=A.data)==null?void 0:Q.text)??""))};window.addEventListener("pi-node-event",D);const W=new ResizeObserver(()=>{var x;if(!(!((x=$.current)!=null&&x.clientWidth)||!$.current.clientHeight))try{M.fit(),J.current||q("terminal_resize",{cols:b.cols,rows:b.rows})}catch{}});return W.observe($.current),()=>{window.removeEventListener(fn,G),W.disconnect(),z.dispose(),le.dispose(),window.removeEventListener("pi-node-event",D),b.dispose()}},[P,w.id,w.conversationId,s]),e.jsxs("div",{className:"node-terminal-wrap",style:{display:t?"block":"none"},children:[e.jsx("div",{ref:$,className:"node-xterm"}),u&&e.jsxs("div",{className:"node-selection-menu",children:[e.jsx("button",{onClick:()=>void navigator.clipboard.writeText(u).then(()=>C(T("nodeCopied"))).catch(y=>C(String(y))),children:T("nodeCopy")}),se&&e.jsx("span",{role:"status",children:se})]})]})}const qn=()=>({name:"",group:"默认",host:"",port:22,username:"root",auth:"password",defaultDir:"/"});function Un({send:P,active:w}){var Be,Je,Ge,Ve;const t=Ee(),[s,ne]=r.useState([]),[T,$]=r.useState([]),[J,u]=r.useState(!1),[te,se]=r.useState(!1),[C,y]=r.useState(null),[b,G]=r.useState(""),[M,q]=r.useState(!1),[z,le]=r.useState(!1),[D,W]=r.useState("agent"),[x,A]=r.useState({}),Q=r.useRef({}),[H,ae]=r.useState({}),[U,ce]=r.useState("password"),[fe,oe]=r.useState(""),[d,a]=r.useState(null),[S,N]=r.useState(!0),[E,k]=r.useState(!1),[R,ge]=r.useState(!1),re=r.useRef(null),Y=r.useRef(new Set),$e=r.useRef(new Set),[Me,ve]=r.useState(""),[de,gn]=r.useState([]),[Se,vn]=r.useState({}),[Re,Sn]=r.useState(Date.now()),[K,yn]=r.useState({}),[Ie,ue]=r.useState({}),[c,ye]=r.useState(localStorage.getItem("pi-node-selected")??""),[bn,Te]=r.useState({}),[v,B]=r.useState(null),[be,F]=r.useState(""),[qe,he]=r.useState(""),[we,Ae]=r.useState("/"),[Ke,wn]=r.useState({}),[L,ke]=r.useState(null),Z=r.useRef(new Map),Fe=r.useRef(new Map),Le=r.useRef(new Map),me=r.useRef(null),j=r.useCallback((n,i,o,h,I)=>{const ie=je();return P({type:"node_request",requestId:ie,action:n,nodeId:i,terminalId:h,conversationId:I,payload:o})?ie:null},[P]);r.useEffect(()=>{if(!w||!M)return;const n=setInterval(()=>Sn(Date.now()),1e3);return()=>clearInterval(n)},[w,M]);const l=de.find(n=>n.id===c),pe=Ie[c]??[],g=pe.find(n=>n.id===bn[c])??pe.at(-1),V=de.find(n=>n.id===d),X=s.find(n=>n.id===(l==null?void 0:l.sourceId)),kn=((Be=Ke[c])==null?void 0:Be.path)===we?Ke[c].entries:[];r.useEffect(()=>{w&&(j("state"),j("source_detect"))},[w,j]),r.useEffect(()=>{l&&Ae(l.defaultDir)},[c,l==null?void 0:l.defaultDir]),r.useEffect(()=>{const n=i=>{var ie,_e,Pe,Ne,Xe,ze,Qe,Ye,Ze,en,nn,tn,sn,on,rn,dn,ln,an,cn,un,hn,mn,pn,xn;const o=i.detail,h=o.nodeId??"";if(o.event==="state"){const p=((ie=o.data)==null?void 0:ie.nodes)??[];gn(p),ae(m=>{var xe;const f=Object.fromEntries(Object.entries(m).map(([O,_])=>[O,{..._,phase:"closed",running:!1,dialogs:[]}]));for(const O of((xe=o.data)==null?void 0:xe.connections)??[])O.agent&&(f[O.nodeId]=O.agent);for(const O of Object.keys(f))p.some(_=>_.id===O)||delete f[O];return f}),vn(Object.fromEntries((((_e=o.data)==null?void 0:_e.connections)??[]).map(m=>[m.nodeId,m]))),ne(((Pe=o.data)==null?void 0:Pe.sources)??[]),yn(Object.fromEntries((((Ne=o.data)==null?void 0:Ne.connections)??[]).map(m=>[m.nodeId,m.status])));for(const m of((Xe=o.data)==null?void 0:Xe.connections)??[])for(const f of m.terminals)Z.current.set(`${m.nodeId}:${f.id}`,f.output??"");ue(m=>{var xe,O;const f={...m};for(const _ of((xe=o.data)==null?void 0:xe.connections)??[]){const ee=(m[_.nodeId]??[]).filter(De=>!_.terminals.some(_n=>_n.id===De.id)).map(De=>({...De,closed:!0}));f[_.nodeId]=[...ee,..._.terminals]}for(const _ of Object.keys(f))(((O=o.data)==null?void 0:O.connections)??[]).some(ee=>ee.nodeId===_)||(f[_]=f[_].map(ee=>({...ee,closed:!0})));for(const _ of Object.keys(f))p.some(ee=>ee.id===_)||delete f[_];return f});return}if(o.event==="agent_state"&&((ze=o.data)!=null&&ze.agent)){const p=o.data.agent;ae(m=>({...m,[h]:p}));return}if(o.event==="terminal_output"){const p=`${h}:${o.terminalId}`;Z.current.set(p,((Z.current.get(p)??"")+String(((Qe=o.data)==null?void 0:Qe.text)??"")).slice(-65536));return}if(o.event==="trust_required"){if(o.requestId&&$e.current.add(o.requestId),window.confirm(t("nodeTrust",{name:String(((Ye=o.data)==null?void 0:Ye.name)??""),host:String(((Ze=o.data)==null?void 0:Ze.host)??""),fingerprint:String(((en=o.data)==null?void 0:en.fingerprint)??"")}))){const p=re.current;(p==null?void 0:p.nodeId)===h?j("credential_test",h,{...p.payload,fingerprint:(nn=o.data)==null?void 0:nn.fingerprint}):j("trust",h,{fingerprint:(tn=o.data)==null?void 0:tn.fingerprint})}else Y.current.delete(h),re.current=null,ge(!1);return}if(o.event==="failure"&&String(((sn=o.data)==null?void 0:sn.action)??"").startsWith("agent_"))return;if(o.event==="failure"){o.requestId===me.current&&(me.current=null);const p=String(((on=o.data)==null?void 0:on.message)??"");o.requestId&&$e.current.delete(o.requestId)||(he(p),ge(!1),((rn=o.data)==null?void 0:rn.action)==="credential_test"&&(re.current=null),Y.current.delete(h));return}if(o.event==="terminal_busy"){ue(p=>({...p,[h]:(p[h]??[]).map(m=>{var f;return m.id===o.terminalId?{...m,busy:!!((f=o.data)!=null&&f.busy)}:m})}));return}if(o.event==="terminal_exit"){const p=`${h}:${o.terminalId}`;Z.current.set(p,(Z.current.get(p)??"")+`\r
1
+ import{a as r,j as e,M as Pn,b as Dn}from"./markdown-BhJ_LInD.js";import{u as Ee,b as jn,T as fn,r as je}from"./index-Bab44wX8.js";import{D as En,o as $n}from"./xterm-D1D2FVe3.js";/* empty css */import"./react-BddUxV-9.js";const Mn=r.memo(function({text:w}){return e.jsx(Pn,{remarkPlugins:[Dn],components:{a:({href:t,children:s})=>/^https?:\/\//.test(t??"")?e.jsx("a",{href:t,target:"_blank",rel:"noreferrer",children:s}):e.jsx("span",{children:s}),img:({alt:t})=>e.jsx("span",{children:t})},children:w})});function Rn({nodeId:P,defaultDir:w,connected:t,agent:s,request:ne,draft:T,setDraft:$,consumedEditors:J}){var oe;const u=Ee(),[te,se]=r.useState(w),[C,y]=r.useState({}),[b,G]=r.useState(""),[M,q]=r.useState(""),[z,le]=r.useState("followUp"),D=r.useRef(null),W=r.useRef(!0),x=s==null?void 0:s.dialogs[0],A=Object.keys(C).length>0,Q=Object.values(C).some(d=>d.action==="agent_dialog");r.useEffect(()=>{q((x==null?void 0:x.prefill)??"")},[x==null?void 0:x.id]),r.useEffect(()=>{s!=null&&s.editorText&&J[P]!==s.editorText.id&&(J[P]=s.editorText.id,$(s.editorText.text))},[s==null?void 0:s.editorText]),r.useEffect(()=>{W.current&&D.current&&(D.current.scrollTop=D.current.scrollHeight)},[s==null?void 0:s.messages,s==null?void 0:s.streamingMessage,s==null?void 0:s.tools]),r.useEffect(()=>{const d=a=>{var E;const S=a.detail,N=S.requestId?C[S.requestId]:void 0;S.nodeId!==P||!N||(S.event==="failure"&&(G(String(((E=S.data)==null?void 0:E.message)??"")),y(k=>{const R={...k};return delete R[S.requestId],R})),S.event==="result"&&(N.text!==void 0&&$(k=>k===N.text?"":k),y(k=>{const R={...k};return delete R[S.requestId],R})))};return window.addEventListener("pi-node-event",d),()=>window.removeEventListener("pi-node-event",d)},[P,C]),r.useEffect(()=>{t||y({})},[t]);const H=(d,a,S)=>{G("");const N=ne(d,P,a,void 0,s==null?void 0:s.id);N?y(E=>({...E,[N]:{action:d,text:S}})):G(u("nodeAgentOffline"))},ae=()=>{!T.trim()||A||!t||(s==null?void 0:s.phase)!=="ready"||(W.current=!0,H("agent_prompt",{text:T,...s.running?{queue:z}:{}},T))},U=[...(s==null?void 0:s.messages)??[],...s!=null&&s.streamingMessage?[s.streamingMessage]:[]],ce=new Map(U.filter(d=>d.role==="toolResult").map(d=>[d.toolCallId,d])),fe=d=>e.jsxs("article",{className:`node-agent-message ${d.role}`,children:[e.jsx("small",{children:d.role==="user"?u("nodeAgentYou"):"pi"}),d.errorMessage&&e.jsx("p",{role:"alert",className:"node-agent-error",children:d.errorMessage}),d.content.map((a,S)=>{if(a.type==="text"&&"text"in a&&typeof a.text=="string")return e.jsx(Mn,{text:a.text},S);if(a.type==="thinking"&&"thinking"in a&&typeof a.thinking=="string")return e.jsxs("details",{children:[e.jsx("summary",{children:u("nodeAgentThinking")}),e.jsx("pre",{children:a.thinking})]},S);if(a.type==="toolCall"&&"id"in a&&"name"in a){const N=ce.get(String(a.id)),E=s==null?void 0:s.tools.find(k=>k.id===a.id);return e.jsxs("details",{className:"node-agent-tool",children:[e.jsxs("summary",{children:[e.jsx("code",{children:String(a.name)}),e.jsx("span",{children:u(N!=null&&N.isError||E!=null&&E.isError?"error":N||E&&!E.running?"done":s!=null&&s.running?"running":"toolQueued")})]}),e.jsx("pre",{children:String(a.argumentsText??"")}),N==null?void 0:N.content.map((k,R)=>"text"in k&&typeof k.text=="string"?e.jsx("pre",{children:k.text},R):null)]},S)}return a.type==="image"&&"dataUrl"in a&&typeof a.dataUrl=="string"&&a.dataUrl.startsWith("data:image/")?e.jsx("img",{src:a.dataUrl,alt:u("toolResultImage")},S):null})]},d.id);return e.jsxs("section",{className:"node-agent","aria-label":u("nodeAgentTitle"),children:[e.jsxs("header",{children:[e.jsx("strong",{children:u("nodeAgentTitle")}),e.jsx("span",{children:s!=null&&s.model?`${s.model.provider} / ${s.model.name}`:u("nodeAgentRemote")}),(s==null?void 0:s.phase)==="ready"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{disabled:A||s.running||!t,onClick:()=>H("agent_new"),children:u("nodeAgentNew")}),e.jsx("button",{disabled:!t,onClick:()=>H("agent_close"),children:u("nodeAgentClose")})]})]}),(!s||s.phase==="closed")&&e.jsxs("div",{className:"node-agent-setup",children:[e.jsx("p",{children:u("nodeAgentSetup")}),e.jsxs("label",{children:[u("nodeDefaultDir"),e.jsx("input",{value:te,onChange:d=>se(d.target.value)})]}),e.jsx("button",{disabled:!t||A,onClick:()=>H("agent_start",{cwd:te}),children:u(A?"nodeAgentStarting":"nodeAgentStart")}),e.jsx("p",{className:"node-muted",children:u("nodeAgentInstall")}),e.jsx("code",{children:"npm install -g @earendil-works/pi-coding-agent@1.0.4"})]}),(s==null?void 0:s.phase)==="starting"&&e.jsx("p",{role:"status",children:u("nodeAgentStarting")}),!t&&e.jsx("p",{role:"status",children:u("nodeAgentOffline")}),(b||(s==null?void 0:s.error))&&e.jsx("p",{role:"alert",className:"node-agent-error",children:b||(s==null?void 0:s.error)}),(s==null?void 0:s.notice)&&e.jsx("p",{role:"status",className:"node-muted",children:s.notice}),e.jsxs("div",{className:"node-agent-feed",ref:D,onScroll:d=>{const a=d.currentTarget;W.current=a.scrollHeight-a.scrollTop-a.clientHeight<100},children:[U.filter(d=>d.role!=="toolResult"&&(d.errorMessage||d.content.some(a=>a.type==="toolCall"||a.type==="image"||"text"in a&&typeof a.text=="string"&&a.text.trim()||"thinking"in a&&typeof a.thinking=="string"&&a.thinking.trim()))).map(fe),(s==null?void 0:s.running)&&e.jsxs("p",{className:"node-agent-working",role:"status",children:[u("nodeAgentWorking"),s.tools.filter(d=>d.running).map(d=>e.jsx("code",{children:d.name},d.id))]})]}),x&&e.jsxs("form",{className:"node-agent-dialog",onSubmit:d=>{d.preventDefault(),H("agent_dialog",{id:x.id,value:M,confirmed:!0})},children:[e.jsx("strong",{children:x.title}),x.message&&e.jsx("p",{children:x.message}),x.method==="select"?e.jsxs("select",{"aria-label":x.title,required:!0,value:M,onChange:d=>q(d.target.value),children:[e.jsx("option",{value:"",disabled:!0,children:u("nodeAgentSelect")}),(oe=x.options)==null?void 0:oe.map(d=>e.jsx("option",{children:d},d))]}):x.method!=="confirm"&&e.jsx("textarea",{"aria-label":x.title,value:M,onChange:d=>q(d.target.value),rows:x.method==="editor"?6:2}),e.jsx("button",{disabled:Q||!t,type:"submit",children:u("confirm")}),e.jsx("button",{disabled:Q||!t,type:"button",onClick:()=>H("agent_dialog",{id:x.id,cancelled:!0}),children:u("cancel")})]}),(s==null?void 0:s.phase)==="ready"&&e.jsxs("form",{className:"node-agent-input",onSubmit:d=>{d.preventDefault(),ae()},children:[e.jsx("textarea",{"aria-label":u("nodeAgentPrompt"),placeholder:u("nodeAgentPrompt"),value:T,onChange:d=>$(d.target.value),rows:3,onKeyDown:d=>{d.key==="Enter"&&!d.shiftKey&&!d.nativeEvent.isComposing&&(d.preventDefault(),ae())}}),e.jsxs("div",{children:[e.jsxs("select",{"aria-label":u("nodeAgentModel"),value:s.model?JSON.stringify([s.model.provider,s.model.id]):"",disabled:s.running||A||!t,onChange:d=>{const[a,S]=JSON.parse(d.target.value);H("agent_model",{provider:a,modelId:S})},children:[e.jsx("option",{value:"",disabled:!0,children:u("nodeAgentModel")}),s.models.map(d=>e.jsxs("option",{value:JSON.stringify([d.provider,d.id]),children:[d.provider," / ",d.name]},`${d.provider}/${d.id}`))]}),s.running&&e.jsxs(e.Fragment,{children:[e.jsxs("select",{"aria-label":u("nodeAgentQueue"),value:z,onChange:d=>le(d.target.value),children:[e.jsx("option",{value:"followUp",children:u("nodeAgentFollowUp")}),e.jsx("option",{value:"steer",children:u("nodeAgentSteer")})]}),e.jsx("button",{type:"button",disabled:!t,onClick:()=>H("agent_abort"),children:u("stop")})]}),e.jsx("button",{type:"submit",disabled:!T.trim()||A||!t,children:u("nodeAgentSend")})]})]})]})}function Tn({nodeId:P,tab:w,active:t,send:s,initialOutput:ne}){const T=Ee(),$=r.useRef(null),J=r.useRef(w.closed);J.current=w.closed;const[u,te]=r.useState(""),[se,C]=r.useState("");return r.useEffect(()=>{if(!$.current)return;const y=getComputedStyle($.current),b=new En({theme:{...jn(),background:y.getPropertyValue("--node-terminal-bg").trim(),foreground:y.getPropertyValue("--node-terminal-fg").trim()},fontFamily:'"JetBrains Mono", Consolas, monospace',fontSize:13,scrollback:8e3,allowProposedApi:!0}),G=()=>{b.options.theme={...jn(),background:y.getPropertyValue("--node-terminal-bg").trim(),foreground:y.getPropertyValue("--node-terminal-fg").trim()}};window.addEventListener(fn,G);const M=new $n;b.loadAddon(M),b.open($.current),ne&&b.write(ne);const q=(x,A={})=>s({type:"node_request",action:x,requestId:je(),nodeId:P,terminalId:w.id,conversationId:w.conversationId,payload:A}),z=b.onData(x=>{J.current||q(x===""?"interrupt":"terminal_input",{data:x})}),le=b.onSelectionChange(()=>te(b.getSelection().slice(0,32e3))),D=x=>{var Q;const A=x.detail;A.nodeId!==P||A.terminalId!==w.id||A.event==="terminal_output"&&b.write(String(((Q=A.data)==null?void 0:Q.text)??""))};window.addEventListener("pi-node-event",D);const W=new ResizeObserver(()=>{var x;if(!(!((x=$.current)!=null&&x.clientWidth)||!$.current.clientHeight))try{M.fit(),J.current||q("terminal_resize",{cols:b.cols,rows:b.rows})}catch{}});return W.observe($.current),()=>{window.removeEventListener(fn,G),W.disconnect(),z.dispose(),le.dispose(),window.removeEventListener("pi-node-event",D),b.dispose()}},[P,w.id,w.conversationId,s]),e.jsxs("div",{className:"node-terminal-wrap",style:{display:t?"block":"none"},children:[e.jsx("div",{ref:$,className:"node-xterm"}),u&&e.jsxs("div",{className:"node-selection-menu",children:[e.jsx("button",{onClick:()=>void navigator.clipboard.writeText(u).then(()=>C(T("nodeCopied"))).catch(y=>C(String(y))),children:T("nodeCopy")}),se&&e.jsx("span",{role:"status",children:se})]})]})}const qn=()=>({name:"",group:"默认",host:"",port:22,username:"root",auth:"password",defaultDir:"/"});function Un({send:P,active:w}){var Be,Je,Ge,Ve;const t=Ee(),[s,ne]=r.useState([]),[T,$]=r.useState([]),[J,u]=r.useState(!1),[te,se]=r.useState(!1),[C,y]=r.useState(null),[b,G]=r.useState(""),[M,q]=r.useState(!1),[z,le]=r.useState(!1),[D,W]=r.useState("agent"),[x,A]=r.useState({}),Q=r.useRef({}),[H,ae]=r.useState({}),[U,ce]=r.useState("password"),[fe,oe]=r.useState(""),[d,a]=r.useState(null),[S,N]=r.useState(!0),[E,k]=r.useState(!1),[R,ge]=r.useState(!1),re=r.useRef(null),Y=r.useRef(new Set),$e=r.useRef(new Set),[Me,ve]=r.useState(""),[de,gn]=r.useState([]),[Se,vn]=r.useState({}),[Re,Sn]=r.useState(Date.now()),[K,yn]=r.useState({}),[Ie,ue]=r.useState({}),[c,ye]=r.useState(localStorage.getItem("pi-node-selected")??""),[bn,Te]=r.useState({}),[v,B]=r.useState(null),[be,F]=r.useState(""),[qe,he]=r.useState(""),[we,Ae]=r.useState("/"),[Ke,wn]=r.useState({}),[L,ke]=r.useState(null),Z=r.useRef(new Map),Fe=r.useRef(new Map),Le=r.useRef(new Map),me=r.useRef(null),j=r.useCallback((n,i,o,h,I)=>{const ie=je();return P({type:"node_request",requestId:ie,action:n,nodeId:i,terminalId:h,conversationId:I,payload:o})?ie:null},[P]);r.useEffect(()=>{if(!w||!M)return;const n=setInterval(()=>Sn(Date.now()),1e3);return()=>clearInterval(n)},[w,M]);const l=de.find(n=>n.id===c),pe=Ie[c]??[],g=pe.find(n=>n.id===bn[c])??pe.at(-1),V=de.find(n=>n.id===d),X=s.find(n=>n.id===(l==null?void 0:l.sourceId)),kn=((Be=Ke[c])==null?void 0:Be.path)===we?Ke[c].entries:[];r.useEffect(()=>{w&&(j("state"),j("source_detect"))},[w,j]),r.useEffect(()=>{l&&Ae(l.defaultDir)},[c,l==null?void 0:l.defaultDir]),r.useEffect(()=>{const n=i=>{var ie,_e,Pe,Ne,Xe,ze,Qe,Ye,Ze,en,nn,tn,sn,on,rn,dn,ln,an,cn,un,hn,mn,pn,xn;const o=i.detail,h=o.nodeId??"";if(o.event==="state"){const p=((ie=o.data)==null?void 0:ie.nodes)??[];gn(p),ae(m=>{var xe;const f=Object.fromEntries(Object.entries(m).map(([O,_])=>[O,{..._,phase:"closed",running:!1,dialogs:[]}]));for(const O of((xe=o.data)==null?void 0:xe.connections)??[])O.agent&&(f[O.nodeId]=O.agent);for(const O of Object.keys(f))p.some(_=>_.id===O)||delete f[O];return f}),vn(Object.fromEntries((((_e=o.data)==null?void 0:_e.connections)??[]).map(m=>[m.nodeId,m]))),ne(((Pe=o.data)==null?void 0:Pe.sources)??[]),yn(Object.fromEntries((((Ne=o.data)==null?void 0:Ne.connections)??[]).map(m=>[m.nodeId,m.status])));for(const m of((Xe=o.data)==null?void 0:Xe.connections)??[])for(const f of m.terminals)Z.current.set(`${m.nodeId}:${f.id}`,f.output??"");ue(m=>{var xe,O;const f={...m};for(const _ of((xe=o.data)==null?void 0:xe.connections)??[]){const ee=(m[_.nodeId]??[]).filter(De=>!_.terminals.some(_n=>_n.id===De.id)).map(De=>({...De,closed:!0}));f[_.nodeId]=[...ee,..._.terminals]}for(const _ of Object.keys(f))(((O=o.data)==null?void 0:O.connections)??[]).some(ee=>ee.nodeId===_)||(f[_]=f[_].map(ee=>({...ee,closed:!0})));for(const _ of Object.keys(f))p.some(ee=>ee.id===_)||delete f[_];return f});return}if(o.event==="agent_state"&&((ze=o.data)!=null&&ze.agent)){const p=o.data.agent;ae(m=>({...m,[h]:p}));return}if(o.event==="terminal_output"){const p=`${h}:${o.terminalId}`;Z.current.set(p,((Z.current.get(p)??"")+String(((Qe=o.data)==null?void 0:Qe.text)??"")).slice(-65536));return}if(o.event==="trust_required"){if(o.requestId&&$e.current.add(o.requestId),window.confirm(t("nodeTrust",{name:String(((Ye=o.data)==null?void 0:Ye.name)??""),host:String(((Ze=o.data)==null?void 0:Ze.host)??""),fingerprint:String(((en=o.data)==null?void 0:en.fingerprint)??"")}))){const p=re.current;(p==null?void 0:p.nodeId)===h?j("credential_test",h,{...p.payload,fingerprint:(nn=o.data)==null?void 0:nn.fingerprint}):j("trust",h,{fingerprint:(tn=o.data)==null?void 0:tn.fingerprint})}else Y.current.delete(h),re.current=null,ge(!1);return}if(o.event==="failure"&&String(((sn=o.data)==null?void 0:sn.action)??"").startsWith("agent_"))return;if(o.event==="failure"){o.requestId===me.current&&(me.current=null);const p=String(((on=o.data)==null?void 0:on.message)??"");o.requestId&&$e.current.delete(o.requestId)||(he(p),ge(!1),((rn=o.data)==null?void 0:rn.action)==="credential_test"&&(re.current=null),Y.current.delete(h));return}if(o.event==="terminal_busy"){ue(p=>({...p,[h]:(p[h]??[]).map(m=>{var f;return m.id===o.terminalId?{...m,busy:!!((f=o.data)!=null&&f.busy)}:m})}));return}if(o.event==="terminal_exit"){const p=`${h}:${o.terminalId}`;Z.current.set(p,(Z.current.get(p)??"")+`\r
2
2
  [SSH 已断开]\r
3
3
  `),ue(m=>({...m,[h]:(m[h]??[]).map(f=>f.id===o.terminalId?{...f,closed:!0}:f)}));return}if(o.event!=="result")return;const I=(dn=o.data)==null?void 0:dn.action;if(I==="source_detect"&&($(((ln=o.data)==null?void 0:ln.sources)??[]),se(!0)),I==="source_add"&&(y(null),u(!1)),I==="credential_test"&&(re.current=null,ge(!1),a(null),F(""),ve(t("nodeCredentialsSaved",{n:Number(((an=o.data)==null?void 0:an.count)??1)}))),(I==="connect"||I==="trust"||I==="credential_test")&&Y.current.has(h)&&(Y.current.delete(h),j("terminal_open",h,{},je()),q(!0)),I==="terminal_open"){const p={id:String((cn=o.data)==null?void 0:cn.terminalId),conversationId:String((un=o.data)==null?void 0:un.conversationId),busy:!1};ue(m=>({...m,[h]:(m[h]??[]).some(f=>f.id===p.id)?m[h]:[...m[h]??[],p]})),Te(m=>({...m,[h]:p.id}))}I==="list"&&o.requestId===Fe.current.get(h)&&wn(p=>{var m,f;return{...p,[h]:{path:String(((m=o.data)==null?void 0:m.path)??""),entries:((f=o.data)==null?void 0:f.entries)??[]}}}),I==="read"&&o.requestId===Le.current.get(h)&&ke({nodeId:h,path:String(((hn=o.data)==null?void 0:hn.path)??""),text:String(((mn=o.data)==null?void 0:mn.text)??"")}),I==="write"&&o.requestId===me.current&&(me.current=null,ke(p=>{var m;return(p==null?void 0:p.nodeId)===h&&p.path===((m=o.data)==null?void 0:m.path)?null:p})),I==="save"&&(B(null),F(""),(pn=o.data)!=null&&pn.id&&ye(String(o.data.id))),(I==="import_legacy"||I==="import")&&ve(t("nodeImported",{n:Number(((xn=o.data)==null?void 0:xn.count)??0)}))};return window.addEventListener("pi-node-event",n),()=>window.removeEventListener("pi-node-event",n)},[j,t]);const Ce=r.useMemo(()=>de.filter(n=>`${n.name} ${n.host} ${n.username}`.toLowerCase().includes(b.toLowerCase())),[de,b]),Cn=r.useMemo(()=>[...new Set(Ce.map(n=>n.group))],[Ce]),Oe=n=>{const i=j("list",c,{path:n},g==null?void 0:g.id,g==null?void 0:g.conversationId);i&&Fe.current.set(c,i)},Nn=n=>{const i=j("read",c,{path:n},g==null?void 0:g.id,g==null?void 0:g.conversationId);i&&Le.current.set(c,i)},In=()=>{!L||L.nodeId!==c||(me.current=j("write",L.nodeId,{path:L.path,text:L.text},g==null?void 0:g.id,g==null?void 0:g.conversationId))},He=n=>{var i;if(ye(n.id),he(""),n.auth==="password"&&!n.hasSecret||n.auth==="key"&&(!n.keyPath||(i=n.unsupported)!=null&&i.includes("key"))&&!n.localKeyPath){ce(n.auth==="key"?"key":"password"),oe(n.localKeyPath||n.keyPath||""),a(n.id),F(""),k(!1),Y.current.add(n.id);return}q(!0),u(!1),K[n.id]==="connected"?(Ie[n.id]??[]).some(o=>!o.closed)||j("terminal_open",n.id,{},je()):(Y.current.add(n.id),j("connect",n.id))},Ue=e.jsx("button",{onClick:()=>{B(qn()),F("")},"aria-label":t("nodeAdd"),children:"+"}),We=e.jsxs("label",{className:"node-secondary",children:[t("nodeImportJson"),e.jsx("input",{type:"file",accept:"application/json,.json",hidden:!0,onChange:async n=>{var o;const i=(o=n.target.files)==null?void 0:o[0];if(i){try{const h=JSON.parse(await i.text());j("import",void 0,{nodes:h.nodes})}catch{he(t("nodeInvalidJson"))}n.target.value=""}}})]}),An=e.jsxs("div",{className:"node-source-page",children:[e.jsx("div",{className:"node-eyebrow",children:t("nodeSources")}),e.jsx("h2",{children:t("nodeAdd")}),e.jsx("p",{className:"node-muted",children:t("nodeSourceIntro")}),te&&!T.length&&!s.length&&e.jsx("p",{className:"node-muted",children:t("nodeNoSources")}),[...s,...T.filter(n=>!s.some(i=>i.path===n.path))].map(n=>e.jsxs("section",{className:"node-source-card",children:[e.jsxs("header",{children:[e.jsx("span",{className:"node-source-icon",children:n.kind==="xshell"?"X":"~/"}),e.jsxs("div",{children:[e.jsx("strong",{children:n.kind==="xshell"?"Xshell 8":"SSH config"}),e.jsx("small",{children:t("nodeSyncInfo",{n:n.count??0,g:n.groups??0})})]})]}),e.jsx("code",{children:n.path}),e.jsxs("p",{children:["✓ ",t("nodeSyncFields")]}),e.jsxs("p",{className:"node-muted",children:["— ",t("nodeSyncPassword"),e.jsx("br",{}),"— ",t("nodeSyncUnsupported")]}),n.error&&e.jsx("p",{className:"node-error",role:"alert",children:n.error}),n.lastSync&&e.jsx("small",{children:t("nodeSyncTime",{time:new Date(n.lastSync).toLocaleString()})}),e.jsxs("div",{className:"node-actions",children:[n.id?e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>j("source_sync",void 0,{id:n.id}),children:t("nodeSyncNow")}),e.jsx("button",{onClick:()=>j("source_toggle",void 0,{id:n.id,enabled:!n.enabled}),children:t(n.enabled?"nodeSyncPause":"nodeSyncResume")})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"node-primary",onClick:()=>j("source_add",void 0,{kind:n.kind,path:n.path,enabled:!0}),children:t("nodeSyncKeep")}),e.jsx("button",{onClick:()=>j("source_add",void 0,{kind:n.kind,path:n.path,enabled:!1}),children:t("nodeImportOnce")})]}),e.jsx("button",{onClick:()=>y({kind:n.kind??"xshell",path:n.path??""}),children:t("nodeChangePath")})]})]},n.path)),e.jsxs("div",{className:"node-actions",children:[e.jsx("button",{onClick:()=>y({kind:"xshell",path:""}),children:t("nodeAddSource")}),e.jsx("button",{onClick:()=>j("source_detect"),children:t("nodeDetect")}),Ue,We]})]});return e.jsxs("div",{className:`node-workbench ${D==="agent"?"node-agent-open":""} ${M&&l?"node-workspace-open":""}`,children:[qe&&e.jsxs("div",{className:"node-global-message node-error",role:"alert",children:[qe,e.jsx("button",{"aria-label":t("close"),onClick:()=>he(""),children:"×"})]}),Me&&e.jsxs("div",{className:"node-global-message node-notice",role:"status",children:[Me,e.jsx("button",{"aria-label":t("close"),onClick:()=>ve(""),children:"×"})]}),!M&&e.jsxs("aside",{className:"node-sidebar",children:[e.jsxs("header",{children:[e.jsx("strong",{children:t("nodeWorkbench")}),Ue]}),e.jsx("input",{"aria-label":t("nodeSearch"),placeholder:t("nodeSearch"),value:b,onChange:n=>G(n.target.value)}),s.map(n=>e.jsxs("button",{className:"node-source-status",onClick:()=>u(!0),children:[e.jsx("span",{className:`node-dot ${n.error?"connecting":n.enabled?"connected":"offline"}`}),n.kind==="xshell"?"Xshell 8":"SSH config",e.jsx("small",{children:n.error||(n.lastSync?new Date(n.lastSync).toLocaleTimeString():"…")})]},n.id)),e.jsx("div",{className:"node-list",children:Cn.map(n=>e.jsxs("section",{children:[e.jsxs("h3",{children:[n,e.jsx("span",{children:Ce.filter(i=>i.group===n).length})]}),Ce.filter(i=>i.group===n).map(i=>{var o,h;return e.jsxs("div",{className:`node-item ${c===i.id?"selected":""}`,children:[e.jsxs("button",{onClick:()=>{ye(i.id),u(!1)},children:[e.jsx("span",{className:`node-dot ${K[i.id]??"offline"}`}),i.name,e.jsxs("small",{children:[i.username,"@",i.host,":",i.port]})]}),(i.sourceMissing||((o=i.unsupported)==null?void 0:o.length)||i.auth==="password"&&!i.hasSecret)&&e.jsx("span",{className:"node-badge",children:t(i.sourceMissing?"nodeSourceMissing":(h=i.unsupported)!=null&&h.length?"nodeUnsupported":"nodeMissingSecret")}),!i.sourceId&&e.jsx("button",{title:t("nodeEdit"),onClick:()=>{B(i),F("")},children:"⋯"})]},i.id)})]},n))}),e.jsxs("footer",{children:[e.jsx("button",{onClick:()=>u(!0),children:t("nodeSources")}),We,e.jsxs("details",{children:[e.jsx("summary",{children:"⋯"}),e.jsx("button",{onClick:()=>j("import_legacy"),children:t("nodeImportLegacy")}),e.jsx("button",{onClick:()=>{const n=de.map(({hasSecret:h,fingerprint:I,sourceId:ie,sourceKey:_e,sourceMissing:Pe,...Ne})=>Ne),i=URL.createObjectURL(new Blob([JSON.stringify({nodes:n},null,2)],{type:"application/json"})),o=document.createElement("a");o.href=i,o.download="pi-nodes.json",o.click(),setTimeout(()=>URL.revokeObjectURL(i),1e3)},children:t("nodeExport")})]})]})]}),!M&&(J||!l?An:e.jsxs("section",{className:"node-detail",children:[e.jsxs("header",{className:"node-detail-head",children:[e.jsxs("div",{children:[e.jsx("div",{className:"node-eyebrow",children:l.group}),e.jsx("h2",{children:l.name}),e.jsxs("code",{children:[l.username,"@",l.host,":",l.port]})]}),e.jsxs("div",{className:"node-actions",children:[X&&e.jsx("button",{onClick:()=>j("source_reveal",void 0,{id:X.id}),children:t("nodeRevealSource")}),!l.sourceId&&e.jsx("button",{onClick:()=>{B(l),F("")},children:t("nodeEdit")}),e.jsx("button",{className:"node-primary",disabled:!!((Je=l.unsupported)!=null&&Je.some(n=>n!=="key"))||l.sourceMissing||K[l.id]==="connecting",onClick:()=>He(l),children:t("nodeOpenWorkbench")})]})]}),l.sourceMissing&&e.jsx("p",{className:"node-warning",children:t("nodeSourceMissing")}),!!((Ge=l.unsupported)!=null&&Ge.length)&&e.jsxs("p",{className:"node-warning",children:[t("nodeUnsupported"),": ",l.unsupported.join(", ")]}),e.jsxs("div",{className:l.hasSecret?"node-credential-note":"node-warning",children:[e.jsxs("div",{children:[e.jsxs("strong",{children:[t(l.auth==="agent"?"nodeAgentAuth":l.auth==="password"?"nodePassword":"nodePassphrase"),!l.hasSecret&&l.auth==="password"&&` · ${t("nodeMissingSecret")}`]}),e.jsx("p",{children:t("nodeCredentialHint")})]}),e.jsx("button",{onClick:()=>{ce(l.auth==="key"?"key":"password"),oe(l.localKeyPath||l.keyPath||""),a(l.id),F(""),k(!1)},children:t("nodeFillSecret")})]}),e.jsxs("dl",{children:[e.jsx("dt",{children:t("nodeAuth")}),e.jsx("dd",{children:t(l.auth==="key"?"nodeKey":l.auth==="agent"?"nodeAgentAuth":"nodePassword")}),(l.localKeyPath||l.keyPath)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:t("nodeKeyPath")}),e.jsx("dd",{children:e.jsx("code",{children:l.localKeyPath||l.keyPath})})]}),X&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:t("nodeSourceLocation")}),e.jsxs("dd",{children:[e.jsxs("code",{children:[X.path,X.kind==="xshell"?`/${l.sourceKey}`:` · ${l.sourceKey}`]}),e.jsx("small",{children:t("nodeSourceReadonly")}),e.jsx("button",{title:t("nodeSourceOpenHint"),onClick:()=>void navigator.clipboard.writeText(X.kind==="xshell"?`${X.path}/${l.sourceKey}`:X.path).then(()=>ve(t("nodeCopied"))).catch(n=>he(String(n))),children:t("nodeCopy")})]})]}),e.jsx("dt",{children:t("nodeLastConnected")}),e.jsx("dd",{children:l.lastConnected?new Date(l.lastConnected).toLocaleString():t("nodeNever")}),e.jsx("dt",{children:t("nodeDefaultDir")}),e.jsx("dd",{children:e.jsx("code",{children:l.defaultDir})})]})]})),M&&l&&e.jsxs("div",{className:"node-connected",children:[e.jsxs("nav",{className:"node-connection-tabs",children:[e.jsx("button",{onClick:()=>q(!1),children:t("nodeBackList")}),de.filter(n=>{var i;return n.id===c||K[n.id]||((i=Ie[n.id])==null?void 0:i.length)}).map(n=>e.jsxs("button",{className:n.id===c?"active":"",onClick:()=>ye(n.id),children:[e.jsx("span",{className:`node-dot ${K[n.id]??"offline"}`}),n.name]},n.id)),e.jsx("button",{onClick:()=>{q(!1),u(!0)},"aria-label":t("nodeAdd"),children:"+"}),((Ve=Se[c])==null?void 0:Ve.connectedAt)&&e.jsx("span",{className:"node-connection-timing",children:t("nodeConnectionTiming",{ms:Se[c].latencyMs??0,duration:`${Math.floor(Math.max(0,Re-Se[c].connectedAt)/6e4)}:${String(Math.floor(Math.max(0,Re-Se[c].connectedAt)/1e3)%60).padStart(2,"0")}`})})]}),e.jsx("div",{className:"node-connected-body",children:e.jsxs("section",{className:"node-main",children:[e.jsxs("header",{className:"node-main-head",children:[e.jsx("strong",{children:l.name}),e.jsxs("span",{children:[l.username,"@",l.host,":",l.port]}),e.jsx("em",{children:t(K[c]==="connected"?"nodeConnected":"nodeDisconnected")}),e.jsx("button",{onClick:()=>K[c]==="connected"?j("disconnect",c):He(l),children:t(K[c]==="connected"?"nodeDisconnect":"nodeConnect")})]}),e.jsxs("nav",{className:"node-workbench-modes","aria-label":t("nodeWorkbench"),children:[e.jsx("button",{className:D==="agent"?"active":"",onClick:()=>W("agent"),children:t("nodeAgentTitle")}),e.jsx("button",{className:D==="terminal"?"active":"",onClick:()=>W("terminal"),children:t("nodeAgentTerminal")})]}),e.jsx("div",{className:"node-agent-container",hidden:D!=="agent",children:e.jsx(Rn,{nodeId:c,defaultDir:l.defaultDir,connected:K[c]==="connected",agent:H[c],request:j,draft:x[c]??"",setDraft:n=>A(i=>({...i,[c]:typeof n=="function"?n(i[c]??""):n})),consumedEditors:Q.current},c)}),e.jsxs("div",{className:"node-manual-workbench",hidden:D!=="terminal",children:[e.jsxs("div",{className:"node-tabs",children:[pe.map((n,i)=>e.jsxs("div",{className:(g==null?void 0:g.id)===n.id?"active":"",children:[e.jsxs("button",{onClick:()=>Te(o=>({...o,[c]:n.id})),children:[t("nodeTab",{n:i+1}),n.closed?` · ${t("nodeTabClosed")}`:n.busy?` · ${t("nodeTabBusy")}`:""]}),e.jsx("button",{"aria-label":t("nodeCloseTab"),onClick:()=>{n.closed||j("terminal_close",c,{},n.id,n.conversationId),Z.current.delete(`${c}:${n.id}`),ue(o=>({...o,[c]:(o[c]??[]).filter(h=>h.id!==n.id)}))},children:"×"})]},n.id)),e.jsx("button",{disabled:K[c]!=="connected",onClick:()=>j("terminal_open",c,{},je()),children:"+"})]}),e.jsxs("div",{className:"node-terminals",children:[pe.map(n=>e.jsx(Tn,{nodeId:c,tab:n,active:w&&D==="terminal"&&(g==null?void 0:g.id)===n.id,send:P,initialOutput:Z.current.get(`${c}:${n.id}`)??n.output},`${c}:${n.id}`)),!pe.length&&e.jsx("div",{className:"node-empty",children:t("nodeOpenHint")})]}),e.jsxs("div",{className:"node-terminal-footer",children:[e.jsx("span",{children:t("nodeTerminalHint")}),e.jsx("button",{onClick:()=>le(!z),children:t("nodeShowFiles")})]}),z&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"node-filebar",children:[e.jsx("input",{value:we,onChange:n=>Ae(n.target.value),"aria-label":t("nodeDefaultDir")}),e.jsx("button",{disabled:K[c]!=="connected",onClick:()=>Oe(we),children:t("nodeBrowse")})]}),e.jsx("div",{className:"node-files",children:kn.map(n=>{const i=`${we.replace(/\/$/,"")}/${n.name}`;return e.jsxs("button",{onClick:()=>n.type==="dir"?(Ae(i),Oe(i)):Nn(i),children:[n.type==="dir"?"▸":"·"," ",n.name]},n.name)})})]}),(L==null?void 0:L.nodeId)===c&&e.jsxs("div",{className:"node-file-editor",children:[e.jsx("span",{children:L.path}),e.jsx("button",{onClick:In,children:t("save")}),e.jsx("button",{onClick:()=>ke(null),children:t("close")}),e.jsx("textarea",{value:L.text,onChange:n=>ke({...L,text:n.target.value})})]})]})]})})]}),C&&e.jsx("div",{className:"node-modal-backdrop",children:e.jsxs("form",{className:"node-modal",onSubmit:n=>{n.preventDefault(),j("source_add",void 0,{...C,enabled:!0})},children:[e.jsx("h2",{children:t("nodeAddSource")}),e.jsxs("label",{children:[t("nodeSources"),e.jsxs("select",{value:C.kind,onChange:n=>y({...C,kind:n.target.value}),children:[e.jsx("option",{value:"xshell",children:"Xshell 8"}),e.jsx("option",{value:"ssh",children:"SSH config"})]})]}),e.jsxs("label",{children:[t("nodeSourcePath"),e.jsx("input",{required:!0,autoFocus:!0,value:C.path,onChange:n=>y({...C,path:n.target.value})})]}),e.jsxs("div",{className:"node-modal-actions",children:[e.jsx("button",{type:"button",onClick:()=>y(null),children:t("cancel")}),e.jsx("button",{type:"submit",children:t("nodeSyncKeep")}),e.jsx("button",{type:"button",disabled:!C.path.trim(),onClick:()=>j("source_add",void 0,{...C,enabled:!1}),children:t("nodeImportOnce")})]})]})}),V&&e.jsx("div",{className:"node-modal-backdrop",children:e.jsxs("form",{className:"node-modal",onSubmit:n=>{n.preventDefault();const i={auth:U,secret:be,persist:S,sameGroup:E,...U==="key"?{keyPath:fe}:{}};re.current={nodeId:V.id,payload:i},ge(!0),j("credential_test",V.id,i)},children:[e.jsx("h2",{children:V.name}),e.jsxs("code",{children:[V.username,"@",V.host,":",V.port]}),e.jsxs("label",{children:[t("nodeAuth"),e.jsxs("select",{disabled:R,value:U,onChange:n=>{ce(n.target.value),F(""),k(!1)},children:[e.jsx("option",{value:"password",children:t("nodePassword")}),e.jsx("option",{value:"key",children:t("nodeKey")})]})]}),e.jsx("p",{className:"node-muted",children:t("nodeLocalAuthHint")}),e.jsx(e.Fragment,{children:U==="key"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{children:[t("nodeKeyPath"),e.jsx("input",{required:!0,value:fe,onChange:n=>oe(n.target.value)})]}),e.jsx("p",{className:"node-muted",children:t("nodePrivateKeyHint")})]})}),e.jsxs("label",{children:[t(U==="key"?"nodePassphrase":"nodePassword"),e.jsx("input",{autoFocus:!0,type:"password",autoComplete:"new-password",required:U==="password",value:be,onChange:n=>F(n.target.value)})]}),e.jsxs("label",{className:"node-checkbox",children:[e.jsx("input",{type:"checkbox",checked:S,onChange:n=>N(n.target.checked)}),t("nodePersistSecret")]}),U==="password"&&e.jsxs("label",{className:"node-checkbox",children:[e.jsx("input",{type:"checkbox",checked:E,onChange:n=>k(n.target.checked)}),t("nodeGroupSecret")]}),E&&e.jsx("p",{className:"node-muted",children:t("nodeGroupHint")}),e.jsx("p",{className:"node-muted",children:t("nodeCredentialHint")}),e.jsxs("div",{className:"node-modal-actions",children:[e.jsx("button",{type:"button",disabled:R,onClick:()=>{Y.current.delete(V.id),a(null),F(""),re.current=null},children:t("cancel")}),e.jsx("button",{disabled:R,className:"node-primary",children:t(R?"nodeTesting":"nodeTestSave")})]})]})}),v&&e.jsx("div",{className:"node-modal-backdrop",children:e.jsxs("form",{className:"node-modal",onSubmit:n=>{n.preventDefault(),j("save",v.id,{...v,secret:be||void 0})},children:[e.jsx("h2",{children:v.id?t("nodeEdit"):t("nodeAdd")}),[["group",t("nodeGroup")],["name",t("nodeName")],["host",t("nodeAddress")],["port",t("nodePort")],["username",t("nodeUsername")],["defaultDir",t("nodeDefaultDir")]].map(([n,i])=>e.jsxs("label",{children:[i,e.jsx("input",{required:n!=="group",value:String(v[n]??""),onChange:o=>B({...v,[n]:n==="port"?Number(o.target.value):o.target.value})})]},n)),e.jsxs("label",{children:[t("nodeAuth"),e.jsxs("select",{value:v.auth,onChange:n=>B({...v,auth:n.target.value}),children:[e.jsx("option",{value:"password",children:t("nodePassword")}),e.jsx("option",{value:"key",children:t("nodeKey")}),e.jsx("option",{value:"agent",children:t("nodeAgentAuth")})]})]}),v.auth==="key"&&e.jsxs("label",{children:[t("nodeKeyPath"),e.jsx("input",{value:v.keyPath??"",onChange:n=>B({...v,keyPath:n.target.value})})]}),v.auth!=="agent"&&e.jsxs("label",{children:[v.auth==="key"?t("nodePassphrase"):t("nodePassword"),e.jsx("input",{type:"password",value:be,onChange:n=>F(n.target.value),placeholder:v.hasSecret?t("nodeKeepSecret"):""})]}),e.jsxs("div",{className:"node-modal-actions",children:[v.id&&v.fingerprint&&e.jsx("button",{type:"button",onClick:()=>{window.confirm(t("nodeForgetHostKeyConfirm",{name:v.name??""}))&&j("forget_host_key",v.id)},children:t("nodeForgetHostKey")}),v.id&&e.jsx("button",{type:"button",onClick:()=>{window.confirm(t("nodeDeleteConfirm",{name:v.name??""}))&&(j("delete",v.id),B(null))},children:t("nodeDelete")}),e.jsx("button",{type:"button",onClick:()=>B(null),children:t("cancel")}),e.jsx("button",{type:"submit",children:t("save")})]})]})})," "]})}export{Un as NodeWorkbench};
@@ -1,2 +1,2 @@
1
- import{a as m,j as n}from"./markdown-BhJ_LInD.js";import{b as $,T as K,u as P,F as q,a as A,c as L,d as B,e as J,f as W,g as X,h as G,r as Q}from"./index-C5or_GAq.js";import{D as U,o as V}from"./xterm-D1D2FVe3.js";/* empty css */import"./react-BddUxV-9.js";function Y({conversationId:s,terminalId:r,command:f,cwd:R,active:t,send:u,register:x}){const v=m.useRef(null),w=m.useRef(t);w.current=t;const N=m.useRef(null),b=f?JSON.stringify(f):"";return m.useEffect(()=>{const d=v.current;if(!d)return;const a=new U({theme:$(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),l=new V;a.loadAddon(l),a.open(d),N.current={term:a,fit:l},t&&a.focus();const j=()=>{a.options.theme=$()};window.addEventListener(K,j),a.attachCustomKeyEventHandler(o=>{var F;if(o.type!=="keydown")return!0;const E=(F=o.key)==null?void 0:F.toLowerCase();if((o.ctrlKey||o.metaKey)&&E==="v")return!1;if(o.ctrlKey&&!o.shiftKey&&!o.altKey&&E==="c"&&a.hasSelection()){const T=a.textarea;return T&&(T.value=a.getSelection(),T.select()),!1}return!0});const g=x(s,r,{write:o=>a.write(o),dispose:()=>a.dispose()}),C=()=>{if(!(!w.current||!d.clientWidth||!d.clientHeight))try{l.fit(),u({type:"terminal_resize",terminalId:r,conversationId:s,cols:a.cols,rows:a.rows})}catch{}},h=requestAnimationFrame(()=>{try{l.fit()}catch{}u(f?{type:"run_command",terminalId:r,conversationId:s,command:f,cols:a.cols,rows:a.rows}:{type:"terminal_create",terminalId:r,conversationId:s,cwd:R,cols:a.cols,rows:a.rows})}),k=a.onData(o=>{u({type:"terminal_input",terminalId:r,conversationId:s,data:o})});let y=null;return typeof ResizeObserver<"u"&&(y=new ResizeObserver(()=>{d.offsetWidth>0&&d.offsetHeight>0&&C()}),y.observe(d)),()=>{cancelAnimationFrame(h),k.dispose(),window.removeEventListener(K,j),y==null||y.disconnect(),g(),a.dispose(),N.current=null}},[s,r,b,u,x]),m.useEffect(()=>{if(!t)return;const d=requestAnimationFrame(()=>{const a=N.current;if(a){try{a.fit.fit(),u({type:"terminal_resize",terminalId:r,conversationId:s,cols:a.term.cols,rows:a.term.rows})}catch{}a.term.focus()}});return()=>cancelAnimationFrame(d)},[t]),n.jsx("div",{ref:v,className:`term-xterm ${t?"":"hidden"}`})}const H={name:"",command:"",cwd:"${pwd}"};function ae({chat:s,send:r,terminal:f,active:R}){const t=P(),[u,x]=m.useState(null),[v,w]=m.useState(!1),[N,b]=m.useState(!1),[d,a]=m.useState(null),[l,j]=m.useState(H),[g,C]=m.useState(null),h=m.useRef(null);m.useEffect(()=>{s.terminals.length===0?x(null):s.terminals.some(e=>e.id===u)||x(s.terminals[s.terminals.length-1].id)},[s.terminals,u]),m.useEffect(()=>()=>{h.current&&clearTimeout(h.current)},[]);const k=e=>{var p;if(!s.ready)return;const i=Q(),c=s.activeConversationId||((p=s.state)==null?void 0:p.conversationId)||"";f.create({...e,id:i,conversationId:c,cols:e.cols??80,rows:e.rows??24,running:!0,exitCode:null}),x(i),w(!1)},y=()=>{var e;return k({title:t("terminalTitle",{n:s.terminals.length+1}),cwd:((e=s.state)==null?void 0:e.cwd)??""})},o=e=>{var p;const i=e.name||e.command,c=s.terminals.find(_=>_.title===i);if(c){f.restart(c.id),x(c.id),r({type:"run_command",terminalId:c.id,conversationId:c.conversationId,command:e,cols:80,rows:24});return}k({title:i,cwd:((p=s.state)==null?void 0:p.cwd)??"",command:e})},E=e=>{const i=s.terminals.find(c=>c.id===e);if(i&&r({type:"terminal_kill",terminalId:e,conversationId:i.conversationId}),f.close(e),u===e){const c=s.terminals.filter(p=>p.id!==e);x(c.length>0?c[c.length-1].id:null)}},F=()=>{b(!0),a(null),j(H)},T=e=>{const i=s.commands[e];i&&(b(!1),a(e),j({name:i.name,command:i.command,cwd:i.cwd??""}))},D=()=>{b(!1),a(null)},S=()=>{const e=l.name.trim(),i=l.command.trim();if(!e||!i)return;const c=l.cwd.trim(),p={name:e,command:i,cwd:c||void 0},_=N?[...s.commands,p]:d!==null?s.commands.map((z,O)=>O===d?p:z):s.commands;r({type:"save_commands",commands:_}),D()},I=e=>{if(g===e){const i=s.commands.filter((c,p)=>p!==e);r({type:"save_commands",commands:i}),C(null),h.current&&clearTimeout(h.current)}else C(e),h.current&&clearTimeout(h.current),h.current=setTimeout(()=>C(null),2500)},M=N||d!==null;return n.jsxs("div",{className:"terminal-view",children:[n.jsxs("aside",{className:`term-side term-commands ${v?"open":""}`,children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:t("commands")}),n.jsxs("div",{className:"panel-header-actions",children:[n.jsx("button",{type:"button",className:"panel-refresh",title:t("rerun"),onClick:()=>r({type:"list_commands"}),children:n.jsx(q,{})}),n.jsx("button",{type:"button",className:"panel-new",title:t("newCommand"),onClick:F,children:n.jsx(A,{})})]})]}),n.jsx("div",{className:"panel-body",children:M?n.jsxs("div",{className:"cmd-form",children:[n.jsx("label",{htmlFor:"cmd-name",children:t("name")}),n.jsx("input",{id:"cmd-name",className:"cmd-input",value:l.name,placeholder:t("exampleName"),autoFocus:!0,onChange:e=>j({...l,name:e.target.value})}),n.jsx("label",{htmlFor:"cmd-command",children:t("command")}),n.jsx("input",{id:"cmd-command",className:"cmd-input",value:l.command,placeholder:t("exampleCommand"),onChange:e=>j({...l,command:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("label",{htmlFor:"cmd-cwd",children:[t("directory")," ",n.jsx("span",{className:"cmd-hint",children:t("cwdHint")})]}),n.jsx("input",{id:"cmd-cwd",className:"cmd-input",value:l.cwd,placeholder:"${pwd}",onChange:e=>j({...l,cwd:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("div",{className:"cmd-form-actions",children:[n.jsx("button",{type:"button",className:"btn",onClick:D,children:t("cancel")}),n.jsx("button",{type:"button",className:"btn primary",disabled:!l.name.trim()||!l.command.trim(),onClick:S,children:t("save")})]})]}):n.jsxs(n.Fragment,{children:[s.commands.length===0&&n.jsx("div",{className:"panel-empty",children:t("noCommands")}),s.commands.map((e,i)=>n.jsxs("div",{className:"cmd-item",children:[n.jsx("button",{type:"button",className:"cmd-run",title:t("clickToRun"),onClick:()=>o(e),children:n.jsx(L,{})}),n.jsxs("button",{type:"button",className:"cmd-main",title:t("clickToRun"),onClick:()=>o(e),children:[n.jsx("span",{className:"cmd-name",children:e.name}),n.jsx("span",{className:"cmd-command",children:e.command}),e.cwd&&n.jsx("span",{className:"cmd-cwd",children:e.cwd})]}),n.jsx("button",{type:"button",className:"cmd-act",title:t("edit"),onClick:()=>T(i),children:n.jsx(B,{})}),n.jsx("button",{type:"button",className:`cmd-act del ${g===i?"confirm":""}`,title:t("delete"),onClick:()=>I(i),children:g===i?t("confirmQ"):n.jsx(J,{})})]},i))]})}),n.jsxs("div",{className:"term-tabs-block",children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:t("terminal")}),n.jsx("button",{type:"button",className:"panel-new",title:t("newTerminal"),onClick:y,children:n.jsx(A,{})})]}),n.jsxs("div",{className:"panel-body",children:[s.terminals.length===0&&n.jsx("div",{className:"panel-empty",children:t("noTerminal")}),s.terminals.map(e=>n.jsxs("div",{className:`term-tab ${e.id===u?"active":""}`,children:[n.jsxs("button",{type:"button",className:"term-tab-main",title:`${e.cwd}${e.command?`
1
+ import{a as m,j as n}from"./markdown-BhJ_LInD.js";import{b as $,T as K,u as P,F as q,a as A,c as L,d as B,e as J,f as W,g as X,h as G,r as Q}from"./index-Bab44wX8.js";import{D as U,o as V}from"./xterm-D1D2FVe3.js";/* empty css */import"./react-BddUxV-9.js";function Y({conversationId:s,terminalId:r,command:f,cwd:R,active:t,send:u,register:x}){const v=m.useRef(null),w=m.useRef(t);w.current=t;const N=m.useRef(null),b=f?JSON.stringify(f):"";return m.useEffect(()=>{const d=v.current;if(!d)return;const a=new U({theme:$(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),l=new V;a.loadAddon(l),a.open(d),N.current={term:a,fit:l},t&&a.focus();const j=()=>{a.options.theme=$()};window.addEventListener(K,j),a.attachCustomKeyEventHandler(o=>{var F;if(o.type!=="keydown")return!0;const E=(F=o.key)==null?void 0:F.toLowerCase();if((o.ctrlKey||o.metaKey)&&E==="v")return!1;if(o.ctrlKey&&!o.shiftKey&&!o.altKey&&E==="c"&&a.hasSelection()){const T=a.textarea;return T&&(T.value=a.getSelection(),T.select()),!1}return!0});const g=x(s,r,{write:o=>a.write(o),dispose:()=>a.dispose()}),C=()=>{if(!(!w.current||!d.clientWidth||!d.clientHeight))try{l.fit(),u({type:"terminal_resize",terminalId:r,conversationId:s,cols:a.cols,rows:a.rows})}catch{}},h=requestAnimationFrame(()=>{try{l.fit()}catch{}u(f?{type:"run_command",terminalId:r,conversationId:s,command:f,cols:a.cols,rows:a.rows}:{type:"terminal_create",terminalId:r,conversationId:s,cwd:R,cols:a.cols,rows:a.rows})}),k=a.onData(o=>{u({type:"terminal_input",terminalId:r,conversationId:s,data:o})});let y=null;return typeof ResizeObserver<"u"&&(y=new ResizeObserver(()=>{d.offsetWidth>0&&d.offsetHeight>0&&C()}),y.observe(d)),()=>{cancelAnimationFrame(h),k.dispose(),window.removeEventListener(K,j),y==null||y.disconnect(),g(),a.dispose(),N.current=null}},[s,r,b,u,x]),m.useEffect(()=>{if(!t)return;const d=requestAnimationFrame(()=>{const a=N.current;if(a){try{a.fit.fit(),u({type:"terminal_resize",terminalId:r,conversationId:s,cols:a.term.cols,rows:a.term.rows})}catch{}a.term.focus()}});return()=>cancelAnimationFrame(d)},[t]),n.jsx("div",{ref:v,className:`term-xterm ${t?"":"hidden"}`})}const H={name:"",command:"",cwd:"${pwd}"};function ae({chat:s,send:r,terminal:f,active:R}){const t=P(),[u,x]=m.useState(null),[v,w]=m.useState(!1),[N,b]=m.useState(!1),[d,a]=m.useState(null),[l,j]=m.useState(H),[g,C]=m.useState(null),h=m.useRef(null);m.useEffect(()=>{s.terminals.length===0?x(null):s.terminals.some(e=>e.id===u)||x(s.terminals[s.terminals.length-1].id)},[s.terminals,u]),m.useEffect(()=>()=>{h.current&&clearTimeout(h.current)},[]);const k=e=>{var p;if(!s.ready)return;const i=Q(),c=s.activeConversationId||((p=s.state)==null?void 0:p.conversationId)||"";f.create({...e,id:i,conversationId:c,cols:e.cols??80,rows:e.rows??24,running:!0,exitCode:null}),x(i),w(!1)},y=()=>{var e;return k({title:t("terminalTitle",{n:s.terminals.length+1}),cwd:((e=s.state)==null?void 0:e.cwd)??""})},o=e=>{var p;const i=e.name||e.command,c=s.terminals.find(_=>_.title===i);if(c){f.restart(c.id),x(c.id),r({type:"run_command",terminalId:c.id,conversationId:c.conversationId,command:e,cols:80,rows:24});return}k({title:i,cwd:((p=s.state)==null?void 0:p.cwd)??"",command:e})},E=e=>{const i=s.terminals.find(c=>c.id===e);if(i&&r({type:"terminal_kill",terminalId:e,conversationId:i.conversationId}),f.close(e),u===e){const c=s.terminals.filter(p=>p.id!==e);x(c.length>0?c[c.length-1].id:null)}},F=()=>{b(!0),a(null),j(H)},T=e=>{const i=s.commands[e];i&&(b(!1),a(e),j({name:i.name,command:i.command,cwd:i.cwd??""}))},D=()=>{b(!1),a(null)},S=()=>{const e=l.name.trim(),i=l.command.trim();if(!e||!i)return;const c=l.cwd.trim(),p={name:e,command:i,cwd:c||void 0},_=N?[...s.commands,p]:d!==null?s.commands.map((z,O)=>O===d?p:z):s.commands;r({type:"save_commands",commands:_}),D()},I=e=>{if(g===e){const i=s.commands.filter((c,p)=>p!==e);r({type:"save_commands",commands:i}),C(null),h.current&&clearTimeout(h.current)}else C(e),h.current&&clearTimeout(h.current),h.current=setTimeout(()=>C(null),2500)},M=N||d!==null;return n.jsxs("div",{className:"terminal-view",children:[n.jsxs("aside",{className:`term-side term-commands ${v?"open":""}`,children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:t("commands")}),n.jsxs("div",{className:"panel-header-actions",children:[n.jsx("button",{type:"button",className:"panel-refresh",title:t("rerun"),onClick:()=>r({type:"list_commands"}),children:n.jsx(q,{})}),n.jsx("button",{type:"button",className:"panel-new",title:t("newCommand"),onClick:F,children:n.jsx(A,{})})]})]}),n.jsx("div",{className:"panel-body",children:M?n.jsxs("div",{className:"cmd-form",children:[n.jsx("label",{htmlFor:"cmd-name",children:t("name")}),n.jsx("input",{id:"cmd-name",className:"cmd-input",value:l.name,placeholder:t("exampleName"),autoFocus:!0,onChange:e=>j({...l,name:e.target.value})}),n.jsx("label",{htmlFor:"cmd-command",children:t("command")}),n.jsx("input",{id:"cmd-command",className:"cmd-input",value:l.command,placeholder:t("exampleCommand"),onChange:e=>j({...l,command:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("label",{htmlFor:"cmd-cwd",children:[t("directory")," ",n.jsx("span",{className:"cmd-hint",children:t("cwdHint")})]}),n.jsx("input",{id:"cmd-cwd",className:"cmd-input",value:l.cwd,placeholder:"${pwd}",onChange:e=>j({...l,cwd:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("div",{className:"cmd-form-actions",children:[n.jsx("button",{type:"button",className:"btn",onClick:D,children:t("cancel")}),n.jsx("button",{type:"button",className:"btn primary",disabled:!l.name.trim()||!l.command.trim(),onClick:S,children:t("save")})]})]}):n.jsxs(n.Fragment,{children:[s.commands.length===0&&n.jsx("div",{className:"panel-empty",children:t("noCommands")}),s.commands.map((e,i)=>n.jsxs("div",{className:"cmd-item",children:[n.jsx("button",{type:"button",className:"cmd-run",title:t("clickToRun"),onClick:()=>o(e),children:n.jsx(L,{})}),n.jsxs("button",{type:"button",className:"cmd-main",title:t("clickToRun"),onClick:()=>o(e),children:[n.jsx("span",{className:"cmd-name",children:e.name}),n.jsx("span",{className:"cmd-command",children:e.command}),e.cwd&&n.jsx("span",{className:"cmd-cwd",children:e.cwd})]}),n.jsx("button",{type:"button",className:"cmd-act",title:t("edit"),onClick:()=>T(i),children:n.jsx(B,{})}),n.jsx("button",{type:"button",className:`cmd-act del ${g===i?"confirm":""}`,title:t("delete"),onClick:()=>I(i),children:g===i?t("confirmQ"):n.jsx(J,{})})]},i))]})}),n.jsxs("div",{className:"term-tabs-block",children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:t("terminal")}),n.jsx("button",{type:"button",className:"panel-new",title:t("newTerminal"),onClick:y,children:n.jsx(A,{})})]}),n.jsxs("div",{className:"panel-body",children:[s.terminals.length===0&&n.jsx("div",{className:"panel-empty",children:t("noTerminal")}),s.terminals.map(e=>n.jsxs("div",{className:`term-tab ${e.id===u?"active":""}`,children:[n.jsxs("button",{type:"button",className:"term-tab-main",title:`${e.cwd}${e.command?`
2
2
  > ${e.command.command}`:""}`,onClick:()=>{x(e.id),w(!1)},children:[n.jsx("span",{className:`term-tab-dot ${e.running?"run":"exit"}`}),n.jsxs("span",{className:"term-tab-title",children:[e.title,!e.running&&n.jsx("span",{className:"term-tab-exit",children:t("exited",{code:e.exitCode===null?"":` ${e.exitCode}`})})]})]}),n.jsx("button",{type:"button",className:"term-tab-close",title:t("closeTerminal"),onClick:()=>E(e.id),children:n.jsx(W,{})})]},e.id))]})]})]}),n.jsxs("div",{className:"term-main",children:[v&&n.jsx("div",{className:"drawer-backdrop",onClick:()=>w(!1)}),n.jsx("button",{type:"button",className:"term-side-toggle",title:t("commands"),onClick:()=>w(e=>!e),children:n.jsx(X,{})}),s.terminals.length===0?n.jsxs("div",{className:"term-empty",children:[n.jsx(G,{className:"term-empty-icon"}),n.jsx("div",{className:"term-empty-title",children:t("builtinTerminal")}),n.jsx("div",{className:"term-empty-sub",children:t("termEmptySub")})]}):s.terminals.map(e=>n.jsx(Y,{conversationId:e.conversationId,terminalId:e.id,command:e.command,cwd:e.cwd,active:R&&e.id===u,send:r,register:f.register},`${e.conversationId}:${e.id}`))]})]})}export{ae as TerminalPanel};
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-SVP7TREG-l2XXTr2v.js";import{p as f}from"./chunk-JWPE2WC7-CrsdBGXT.js";import{_ as n,l as o}from"./mermaid.core-CO2nrD04.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-IEk8qBRq.js";import"./index-C5or_GAq.js";import"./markdown-BhJ_LInD.js";import"./react-BddUxV-9.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},I={parser:R,db:a,renderer:u,styles:p};export{I as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-SVP7TREG-BcdlBuOQ.js";import{p as f}from"./chunk-JWPE2WC7-B5iJgXvl.js";import{_ as n,l as o}from"./mermaid.core-CvQEO3ue.js";import{M as c,b as d}from"./cynefin-OW5HDTMX-DY0BDLjc.js";import"./index-Bab44wX8.js";import"./markdown-BhJ_LInD.js";import"./react-BddUxV-9.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},I={parser:R,db:a,renderer:u,styles:p};export{I as diagram};
@@ -1 +1 @@
1
- import{a0 as ln,a1 as an,a2 as y,a3 as tn,a4 as H,a5 as q,a6 as _,a7 as un,a8 as rn,a9 as L,aa as o,ab as B,ac as sn,ad as on,ae as fn}from"./mermaid.core-CO2nrD04.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,C,a){var O=I-l,i=D-h,n=C-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function W(l,h,I,D,v,A,C){var a=l-I,O=h-D,i=(C?A:-A)/L(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,F=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*L(fn(0,T*T*R-P*P)),j=(P*g-m*S)/R,z=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=j-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(j=w,z=p),{cx:j,cy:z,x01:-n,y01:-d,x11:j*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=yn,I=B(0),D=null,v=gn,A=dn,C=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-an,c=A.apply(this,arguments)-an,F=un(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(F>tn-y)a.moveTo(s*H(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*H(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=F,S=F,j=C.apply(this,arguments)/2,z=j>y&&(D?+D.apply(this,arguments):L(u*u+s*s)),w=_(un(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if(z>y){var G=sn(z/u*q(j)),M=sn(z/s*q(j));(P-=G*2)>y?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(S-=M*2)>y?(M*=t?1:-1,m+=M,g-=M):(S=0,m=g=(f+c)/2)}var J=s*H(m),K=s*q(m),N=u*H(T),Q=u*q(T);if(w>y){var U=s*H(g),V=s*q(g),X=u*H(R),Y=u*q(R),E;if(F<rn)if(E=pn(J,K,X,Y,U,V,N,Q)){var Z=J-E[0],$=K-E[1],b=U-E[0],k=V-E[1],nn=1/q(on((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,g,!t)):a.moveTo(J,K),!(u>y)||!(P>y)?a.lineTo(N,Q):p>y?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-rn/2;return[H(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:B(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:B(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{a0 as ln,a1 as an,a2 as y,a3 as tn,a4 as H,a5 as q,a6 as _,a7 as un,a8 as rn,a9 as L,aa as o,ab as B,ac as sn,ad as on,ae as fn}from"./mermaid.core-CvQEO3ue.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,C,a){var O=I-l,i=D-h,n=C-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function W(l,h,I,D,v,A,C){var a=l-I,O=h-D,i=(C?A:-A)/L(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,F=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*L(fn(0,T*T*R-P*P)),j=(P*g-m*S)/R,z=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=j-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(j=w,z=p),{cx:j,cy:z,x01:-n,y01:-d,x11:j*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=yn,I=B(0),D=null,v=gn,A=dn,C=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-an,c=A.apply(this,arguments)-an,F=un(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(F>tn-y)a.moveTo(s*H(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*H(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=F,S=F,j=C.apply(this,arguments)/2,z=j>y&&(D?+D.apply(this,arguments):L(u*u+s*s)),w=_(un(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if(z>y){var G=sn(z/u*q(j)),M=sn(z/s*q(j));(P-=G*2)>y?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(S-=M*2)>y?(M*=t?1:-1,m+=M,g-=M):(S=0,m=g=(f+c)/2)}var J=s*H(m),K=s*q(m),N=u*H(T),Q=u*q(T);if(w>y){var U=s*H(g),V=s*q(g),X=u*H(R),Y=u*q(R),E;if(F<rn)if(E=pn(J,K,X,Y,U,V,N,Q)){var Z=J-E[0],$=K-E[1],b=U-E[0],k=V-E[1],nn=1/q(on((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,g,!t)):a.moveTo(J,K),!(u>y)||!(P>y)?a.lineTo(N,Q):p>y?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-rn/2;return[H(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:B(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:B(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};