@chainingintention/pi-web-cn 1.202606.3

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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +364 -0
  3. package/dist/cli.js +960 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/client/apple-touch-icon.png +0 -0
  6. package/dist/client/assets/CodeViewer-B4nxYc0g.js +4 -0
  7. package/dist/client/assets/TerminalPanel-htr2dU1I.js +122 -0
  8. package/dist/client/assets/index-BjUH4a8R.js +1994 -0
  9. package/dist/client/assets/vendor-editor-core-B4Sq6exx.js +12 -0
  10. package/dist/client/assets/vendor-editor-languages-DznYbTkJ.js +26 -0
  11. package/dist/client/assets/vendor-editor-legacy-B4QLsWF8.js +1 -0
  12. package/dist/client/assets/vendor-terminal-DDGTF8rc.css +1 -0
  13. package/dist/client/assets/vendor-terminal-DjQ08hXu.js +16 -0
  14. package/dist/client/favicon.svg +11 -0
  15. package/dist/client/index.html +60 -0
  16. package/dist/client/manifest.webmanifest +24 -0
  17. package/dist/client/pwa-icon-192.png +0 -0
  18. package/dist/client/pwa-icon-512.png +0 -0
  19. package/dist/config.js +154 -0
  20. package/dist/config.js.map +1 -0
  21. package/dist/pi-web-plugins/info/package.json +9 -0
  22. package/dist/pi-web-plugins/info/pi-web-plugin.js +51 -0
  23. package/dist/pi-web-plugins/updates/package.json +9 -0
  24. package/dist/pi-web-plugins/updates/pi-web-plugin.js +181 -0
  25. package/dist/pi-web-plugins/workspace-tasks/config.js +91 -0
  26. package/dist/pi-web-plugins/workspace-tasks/package.json +9 -0
  27. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +48 -0
  28. package/dist/pi-web-plugins/workspace-tasks/taskRunner.js +12 -0
  29. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +292 -0
  30. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +47 -0
  31. package/dist/piWebVersionReport.js +221 -0
  32. package/dist/piWebVersionReport.js.map +1 -0
  33. package/dist/plugin-api/unstable.d.ts +22 -0
  34. package/dist/plugin-api.d.ts +163 -0
  35. package/dist/server/activity/workspaceActivityRoutes.js +4 -0
  36. package/dist/server/activity/workspaceActivityRoutes.js.map +1 -0
  37. package/dist/server/activity/workspaceActivityService.js +98 -0
  38. package/dist/server/activity/workspaceActivityService.js.map +1 -0
  39. package/dist/server/app.js +115 -0
  40. package/dist/server/app.js.map +1 -0
  41. package/dist/server/configRoutes.js +123 -0
  42. package/dist/server/configRoutes.js.map +1 -0
  43. package/dist/server/diagnostics/nodePtySpawnHelper.js +135 -0
  44. package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -0
  45. package/dist/server/git/gitEnv.js +15 -0
  46. package/dist/server/git/gitEnv.js.map +1 -0
  47. package/dist/server/git/gitService.js +119 -0
  48. package/dist/server/git/gitService.js.map +1 -0
  49. package/dist/server/gitRoutes.js +23 -0
  50. package/dist/server/gitRoutes.js.map +1 -0
  51. package/dist/server/index.js +7 -0
  52. package/dist/server/index.js.map +1 -0
  53. package/dist/server/machines/machineClient.js +134 -0
  54. package/dist/server/machines/machineClient.js.map +1 -0
  55. package/dist/server/machines/machineProxyRoutes.js +92 -0
  56. package/dist/server/machines/machineProxyRoutes.js.map +1 -0
  57. package/dist/server/machines/machineRoutes.js +50 -0
  58. package/dist/server/machines/machineRoutes.js.map +1 -0
  59. package/dist/server/machines/machineService.js +168 -0
  60. package/dist/server/machines/machineService.js.map +1 -0
  61. package/dist/server/machines/machineStore.js +128 -0
  62. package/dist/server/machines/machineStore.js.map +1 -0
  63. package/dist/server/piWebPluginService.js +235 -0
  64. package/dist/server/piWebPluginService.js.map +1 -0
  65. package/dist/server/piWebStatus.js +462 -0
  66. package/dist/server/piWebStatus.js.map +1 -0
  67. package/dist/server/projects/directorySuggestions.js +37 -0
  68. package/dist/server/projects/directorySuggestions.js.map +1 -0
  69. package/dist/server/projects/projectService.js +31 -0
  70. package/dist/server/projects/projectService.js.map +1 -0
  71. package/dist/server/realtime/sessionEventHub.js +39 -0
  72. package/dist/server/realtime/sessionEventHub.js.map +1 -0
  73. package/dist/server/sessiond/sessionProxyRoutes.js +60 -0
  74. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -0
  75. package/dist/server/sessiond.js +61 -0
  76. package/dist/server/sessiond.js.map +1 -0
  77. package/dist/server/sessions/authProviderOptions.js +56 -0
  78. package/dist/server/sessions/authProviderOptions.js.map +1 -0
  79. package/dist/server/sessions/authRoutes.js +59 -0
  80. package/dist/server/sessions/authRoutes.js.map +1 -0
  81. package/dist/server/sessions/authService.js +74 -0
  82. package/dist/server/sessions/authService.js.map +1 -0
  83. package/dist/server/sessions/builtinCommands.js +27 -0
  84. package/dist/server/sessions/builtinCommands.js.map +1 -0
  85. package/dist/server/sessions/editPreview.js +196 -0
  86. package/dist/server/sessions/editPreview.js.map +1 -0
  87. package/dist/server/sessions/messagePaging.js +43 -0
  88. package/dist/server/sessions/messagePaging.js.map +1 -0
  89. package/dist/server/sessions/oauthLoginFlowService.js +219 -0
  90. package/dist/server/sessions/oauthLoginFlowService.js.map +1 -0
  91. package/dist/server/sessions/piSessionService.js +1054 -0
  92. package/dist/server/sessions/piSessionService.js.map +1 -0
  93. package/dist/server/sessions/sessionArchiveStore.js +216 -0
  94. package/dist/server/sessions/sessionArchiveStore.js.map +1 -0
  95. package/dist/server/sessions/sessionArchiveTree.js +35 -0
  96. package/dist/server/sessions/sessionArchiveTree.js.map +1 -0
  97. package/dist/server/sessions/sessionCommandService.js +234 -0
  98. package/dist/server/sessions/sessionCommandService.js.map +1 -0
  99. package/dist/server/sessions/sessionNameGenerator.js +68 -0
  100. package/dist/server/sessions/sessionNameGenerator.js.map +1 -0
  101. package/dist/server/sessions/sessionRoutes.js +184 -0
  102. package/dist/server/sessions/sessionRoutes.js.map +1 -0
  103. package/dist/server/sessions/sessionRuntimeStore.js +2 -0
  104. package/dist/server/sessions/sessionRuntimeStore.js.map +1 -0
  105. package/dist/server/storage/projectStore.js +88 -0
  106. package/dist/server/storage/projectStore.js.map +1 -0
  107. package/dist/server/terminalProxyRoutes.js +130 -0
  108. package/dist/server/terminalProxyRoutes.js.map +1 -0
  109. package/dist/server/terminals/terminalRoutes.js +138 -0
  110. package/dist/server/terminals/terminalRoutes.js.map +1 -0
  111. package/dist/server/terminals/terminalService.js +293 -0
  112. package/dist/server/terminals/terminalService.js.map +1 -0
  113. package/dist/server/terminals/terminalSize.js +17 -0
  114. package/dist/server/terminals/terminalSize.js.map +1 -0
  115. package/dist/server/types.js +2 -0
  116. package/dist/server/types.js.map +1 -0
  117. package/dist/server/webSocketBridge.js +32 -0
  118. package/dist/server/webSocketBridge.js.map +1 -0
  119. package/dist/server/workspaceExplorerRoutes.js +42 -0
  120. package/dist/server/workspaceExplorerRoutes.js.map +1 -0
  121. package/dist/server/workspaces/fileContentService.js +70 -0
  122. package/dist/server/workspaces/fileContentService.js.map +1 -0
  123. package/dist/server/workspaces/fileSuggestions.js +148 -0
  124. package/dist/server/workspaces/fileSuggestions.js.map +1 -0
  125. package/dist/server/workspaces/fileTreeService.js +26 -0
  126. package/dist/server/workspaces/fileTreeService.js.map +1 -0
  127. package/dist/server/workspaces/gitWorktreeDiscovery.js +34 -0
  128. package/dist/server/workspaces/gitWorktreeDiscovery.js.map +1 -0
  129. package/dist/server/workspaces/imagePreviewService.js +40 -0
  130. package/dist/server/workspaces/imagePreviewService.js.map +1 -0
  131. package/dist/server/workspaces/pathSafety.js +45 -0
  132. package/dist/server/workspaces/pathSafety.js.map +1 -0
  133. package/dist/server/workspaces/workspaceContext.js +8 -0
  134. package/dist/server/workspaces/workspaceContext.js.map +1 -0
  135. package/dist/server/workspaces/workspaceService.js +39 -0
  136. package/dist/server/workspaces/workspaceService.js.map +1 -0
  137. package/dist/sessiond/config.js +9 -0
  138. package/dist/sessiond/config.js.map +1 -0
  139. package/dist/sessiond/sessionDaemonClient.js +65 -0
  140. package/dist/sessiond/sessionDaemonClient.js.map +1 -0
  141. package/dist/shared/activity.js +26 -0
  142. package/dist/shared/activity.js.map +1 -0
  143. package/dist/shared/apiTypes.d.ts +464 -0
  144. package/dist/shared/apiTypes.js +2 -0
  145. package/dist/shared/apiTypes.js.map +1 -0
  146. package/dist/shared/federatedRoutes.js +57 -0
  147. package/dist/shared/federatedRoutes.js.map +1 -0
  148. package/dist/shared/piWebStatusParsing.js +62 -0
  149. package/dist/shared/piWebStatusParsing.js.map +1 -0
  150. package/dist/shared/pluginIds.js +5 -0
  151. package/dist/shared/pluginIds.js.map +1 -0
  152. package/dist/shared/workspaceFiles.js +3 -0
  153. package/dist/shared/workspaceFiles.js.map +1 -0
  154. package/docs/assets/favicon.svg +11 -0
  155. package/docs/assets/pi-web-banner.png +0 -0
  156. package/docs/assets/pi-web-demo.gif +0 -0
  157. package/docs/assets/pi-web-demo.webm +0 -0
  158. package/docs/plugins.md +762 -0
  159. package/extensions/pi-web.ts +133 -0
  160. package/install.sh +5 -0
  161. package/package.json +127 -0
  162. package/plugin-api/unstable.d.ts +1 -0
  163. package/plugin-api.d.ts +1 -0
@@ -0,0 +1,48 @@
1
+ // Generated from pi-web-plugins\workspace-tasks\pi-web-plugin.ts. Do not edit directly.
2
+ import { TASKS_CONFIG_PATH } from "./config.js";
3
+ import { defineTasksPanelElement, tasksPanelBadge } from "./tasksPanelElement.js";
4
+ const plugin = {
5
+ apiVersion: 1,
6
+ name: "工作区任务",
7
+ activate: ({ pluginId, html, svg }) => {
8
+ defineTasksPanelElement();
9
+ return {
10
+ contributions: {
11
+ actions: [
12
+ {
13
+ id: "workspace.open-tasks",
14
+ title: "打开工作区任务",
15
+ description: `打开工作区任务标签页。在 ${TASKS_CONFIG_PATH} 中配置任务。`,
16
+ group: "工作区",
17
+ enabled: (context) => context.state.selectedWorkspace !== undefined,
18
+ run: (context) => {
19
+ if (context.state.selectedWorkspace === undefined)
20
+ return;
21
+ context.selectWorkspaceTool(`${pluginId}:workspace.tasks`);
22
+ },
23
+ },
24
+ ],
25
+ workspacePanels: [
26
+ {
27
+ id: "workspace.tasks",
28
+ title: "任务",
29
+ icon: svg `
30
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
31
+ <path d="M9 6h11"></path>
32
+ <path d="M9 12h11"></path>
33
+ <path d="M9 18h11"></path>
34
+ <path d="m4 6 .8 .8L6.5 5"></path>
35
+ <path d="m4 12 .8 .8 1.7-1.8"></path>
36
+ <path d="m4 18 .8 .8 1.7-1.8"></path>
37
+ </svg>
38
+ `,
39
+ order: 40,
40
+ badge: (context) => tasksPanelBadge(context),
41
+ render: (context) => html `<pi-web-workspace-tasks-panel .context=${context}></pi-web-workspace-tasks-panel>`,
42
+ },
43
+ ],
44
+ },
45
+ };
46
+ },
47
+ };
48
+ export default plugin;
@@ -0,0 +1,12 @@
1
+ // Generated from pi-web-plugins\workspace-tasks\taskRunner.ts. Do not edit directly.
2
+ export function runWorkspaceTaskInTerminal(terminal, task) {
3
+ return terminal.runCommand({
4
+ title: task.title,
5
+ command: task.command,
6
+ open: true,
7
+ metadata: {
8
+ "pi.plugin": "workspace-tasks",
9
+ "task.id": task.id,
10
+ },
11
+ });
12
+ }
@@ -0,0 +1,292 @@
1
+ // Generated from pi-web-plugins\workspace-tasks\tasksPanelElement.ts. Do not edit directly.
2
+ import { TASKS_CONFIG_PATH } from "./config.js";
3
+ import { runWorkspaceTaskInTerminal } from "./taskRunner.js";
4
+ import { loadWorkspaceTasksConfig, tasksConfigRefreshHint, tasksConfigUnavailableMessage } from "./workspaceTasksClient.js";
5
+ export const tasksPanelTagName = "pi-web-workspace-tasks-panel";
6
+ const configChangedEvent = "pi-web-workspace-tasks-config-changed";
7
+ const configCache = new Map();
8
+ export function defineTasksPanelElement() {
9
+ if (!customElements.get(tasksPanelTagName))
10
+ customElements.define(tasksPanelTagName, PiWebTasksPanel);
11
+ }
12
+ export function tasksPanelBadge(context) {
13
+ const state = getCachedWorkspaceConfig(context);
14
+ if (state?.kind === "unavailable")
15
+ return "!";
16
+ if (state?.kind === "loaded" && state.config.tasks.length > 0)
17
+ return state.config.tasks.length;
18
+ return undefined;
19
+ }
20
+ class PiWebTasksPanel extends HTMLElement {
21
+ contextValue;
22
+ runningTaskId;
23
+ status;
24
+ root;
25
+ onConfigChanged = () => {
26
+ this.render();
27
+ };
28
+ constructor() {
29
+ super();
30
+ this.root = this.attachShadow({ mode: "open" });
31
+ }
32
+ set context(value) {
33
+ const previousKey = this.contextValue === undefined ? undefined : cacheKeyForContext(this.contextValue);
34
+ const nextKey = value === undefined ? undefined : cacheKeyForContext(value);
35
+ this.contextValue = value;
36
+ // Parent app updates should not rebuild this shadow DOM for the same workspace:
37
+ // doing so resets the mobile scroll position and can replace buttons mid-click.
38
+ if (previousKey === nextKey)
39
+ return;
40
+ this.runningTaskId = undefined;
41
+ this.status = undefined;
42
+ this.render();
43
+ }
44
+ connectedCallback() {
45
+ window.addEventListener(configChangedEvent, this.onConfigChanged);
46
+ this.render();
47
+ }
48
+ disconnectedCallback() {
49
+ window.removeEventListener(configChangedEvent, this.onConfigChanged);
50
+ }
51
+ render() {
52
+ const context = this.contextValue;
53
+ if (context === undefined) {
54
+ this.root.innerHTML = `${taskStyles()}<section class="empty">请选择一个工作区。</section>`;
55
+ return;
56
+ }
57
+ const state = getOrLoadWorkspaceConfig(context);
58
+ this.root.innerHTML = `
59
+ ${taskStyles()}
60
+ <section class="toolbar">
61
+ <strong>工作区任务</strong>
62
+ <span class="toolbar-tasks">
63
+ <button class="secondary" data-refresh-config ${state.kind === "loading" ? "disabled" : ""}>刷新</button>
64
+ <button class="secondary" data-open-terminal>打开终端</button>
65
+ </span>
66
+ </section>
67
+ ${this.renderStatus()}
68
+ <section class="viewer tasks-viewer">
69
+ ${this.renderConfigState(state)}
70
+ </section>
71
+ `;
72
+ this.root.querySelector("button[data-refresh-config]")?.addEventListener("click", () => {
73
+ void this.refreshConfig(context);
74
+ });
75
+ for (const button of this.root.querySelectorAll("button[data-task-id]")) {
76
+ button.addEventListener("click", () => {
77
+ void this.dispatchTaskById(context, button.getAttribute("data-task-id"));
78
+ });
79
+ }
80
+ this.root.querySelector("button[data-open-terminal]")?.addEventListener("click", () => {
81
+ this.openWorkspaceTerminal();
82
+ });
83
+ }
84
+ dispatchTaskById(context, taskId) {
85
+ if (!this.isCurrentContext(context))
86
+ return Promise.resolve();
87
+ const task = taskFromConfigState(getCachedWorkspaceConfig(context), taskId);
88
+ if (task === undefined) {
89
+ this.status = { kind: "error", message: "该任务已不可用。请点击刷新后重试。" };
90
+ this.render();
91
+ return Promise.resolve();
92
+ }
93
+ return this.dispatchTask(context, task);
94
+ }
95
+ isCurrentContext(context) {
96
+ return this.contextValue !== undefined && cacheKeyForContext(this.contextValue) === cacheKeyForContext(context);
97
+ }
98
+ renderConfigState(state) {
99
+ if (state.kind === "loading")
100
+ return `<p class="muted">正在加载 ${escapeHtml(TASKS_CONFIG_PATH)}…</p>`;
101
+ if (state.kind === "missing")
102
+ return renderMissingState(state);
103
+ if (state.kind === "unavailable")
104
+ return renderUnavailableState(state);
105
+ if (state.config.tasks.length === 0)
106
+ return `<p class="muted">${escapeHtml(state.path)} 中没有定义任务。请在文件中添加任务,然后点击刷新。</p>`;
107
+ return `
108
+ <p class="muted">任务会在专用工作区终端中运行,并切换到该终端。编辑 ${escapeHtml(state.path)} 后点击刷新重新加载。</p>
109
+ ${renderTaskGroups(state.config.tasks, this.runningTaskId)}
110
+ `;
111
+ }
112
+ renderStatus() {
113
+ if (this.status === undefined)
114
+ return "";
115
+ const detail = this.status.detail === undefined ? "" : `<pre>${escapeHtml(this.status.detail)}</pre>`;
116
+ return `<div class="status panel-status ${escapeAttr(this.status.kind)}">${escapeHtml(this.status.message)}${detail}</div>`;
117
+ }
118
+ async refreshConfig(context) {
119
+ this.status = { kind: "info", message: `正在刷新 ${TASKS_CONFIG_PATH}…` };
120
+ configCache.set(cacheKeyForContext(context), { kind: "loading" });
121
+ this.render();
122
+ const state = await refreshWorkspaceConfig(context);
123
+ if (!this.isCurrentContext(context))
124
+ return;
125
+ this.status = state.kind === "loaded"
126
+ ? { kind: "success", message: `已加载 ${String(state.config.tasks.length)} 个任务。` }
127
+ : undefined;
128
+ this.render();
129
+ }
130
+ async dispatchTask(context, task) {
131
+ if (this.runningTaskId !== undefined) {
132
+ this.status = { kind: "info", message: "已有其他任务正在启动。请等待其分发完成后重试。" };
133
+ this.render();
134
+ return;
135
+ }
136
+ if (task.confirm && !window.confirm(`运行 ${task.title}?\n\n${task.command}`)) {
137
+ this.status = { kind: "info", message: `已取消 ${task.title}。` };
138
+ this.render();
139
+ return;
140
+ }
141
+ this.runningTaskId = task.id;
142
+ this.status = { kind: "info", message: `正在启动 ${task.title}…` };
143
+ this.render();
144
+ try {
145
+ const handle = await runWorkspaceTaskInTerminal(context.terminal, task);
146
+ if (!this.isCurrentContext(context))
147
+ return;
148
+ this.status = {
149
+ kind: "success",
150
+ message: `已启动终端命令“${handle.run.title}”。`,
151
+ detail: task.command,
152
+ };
153
+ this.runningTaskId = undefined;
154
+ this.render();
155
+ }
156
+ catch (error) {
157
+ if (!this.isCurrentContext(context))
158
+ return;
159
+ this.runningTaskId = undefined;
160
+ this.status = { kind: "error", message: error instanceof Error ? error.message : String(error) };
161
+ this.render();
162
+ }
163
+ }
164
+ openWorkspaceTerminal(terminalId) {
165
+ const context = this.contextValue;
166
+ if (context === undefined) {
167
+ this.status = { kind: "error", message: "打开终端前请先选择工作区。" };
168
+ this.render();
169
+ return;
170
+ }
171
+ if (terminalId === undefined)
172
+ context.terminal.open();
173
+ else
174
+ context.terminal.open({ terminalId });
175
+ }
176
+ }
177
+ function getCachedWorkspaceConfig(context) {
178
+ return configCache.get(cacheKeyForContext(context));
179
+ }
180
+ function getOrLoadWorkspaceConfig(context) {
181
+ const cached = getCachedWorkspaceConfig(context);
182
+ if (cached !== undefined)
183
+ return cached;
184
+ const loading = { kind: "loading" };
185
+ configCache.set(cacheKeyForContext(context), loading);
186
+ void refreshWorkspaceConfig(context);
187
+ return loading;
188
+ }
189
+ async function refreshWorkspaceConfig(context) {
190
+ const key = cacheKeyForContext(context);
191
+ const state = await loadWorkspaceTasksConfig(context.files).catch((error) => ({
192
+ kind: "unavailable",
193
+ message: tasksConfigUnavailableMessage,
194
+ hint: tasksConfigRefreshHint,
195
+ detail: error instanceof Error ? error.message : String(error),
196
+ }));
197
+ configCache.set(key, state);
198
+ context.host.requestRender();
199
+ window.dispatchEvent(new Event(configChangedEvent));
200
+ return state;
201
+ }
202
+ function cacheKeyForContext(context) {
203
+ return `${context.machine.id}:${context.workspace.projectId}:${context.workspace.id}`;
204
+ }
205
+ function renderMissingState(state) {
206
+ return `<div class="empty-state"><strong>${escapeHtml(state.message)}</strong><p>${escapeHtml(state.hint)}</p></div>`;
207
+ }
208
+ function renderUnavailableState(state) {
209
+ const detail = state.detail === undefined ? "" : `<pre>${escapeHtml(state.detail)}</pre>`;
210
+ return `<div class="status error"><strong>${escapeHtml(state.message)}</strong><p>${escapeHtml(state.hint)}</p>${detail}</div>`;
211
+ }
212
+ function renderTaskGroups(tasks, runningTaskId) {
213
+ return `<div class="tasks">${groupTasks(tasks).map((group) => renderTaskGroup(group, runningTaskId)).join("")}</div>`;
214
+ }
215
+ function groupTasks(tasks) {
216
+ const groups = [];
217
+ for (const task of tasks) {
218
+ const title = task.group;
219
+ let group = groups.find((candidate) => candidate.title === title);
220
+ if (group === undefined) {
221
+ group = { title, tasks: [] };
222
+ groups.push(group);
223
+ }
224
+ group.tasks.push(task);
225
+ }
226
+ return groups;
227
+ }
228
+ function renderTaskGroup(group, runningTaskId) {
229
+ const title = group.title === undefined ? "" : `<h3>${escapeHtml(group.title)}</h3>`;
230
+ return `<section class="task-group">${title}${group.tasks.map((task) => renderTask(task, runningTaskId)).join("")}</section>`;
231
+ }
232
+ function renderTask(task, runningTaskId) {
233
+ const running = runningTaskId === task.id;
234
+ const disabled = runningTaskId !== undefined;
235
+ const description = task.description === undefined ? "" : `<span>${escapeHtml(task.description)}</span>`;
236
+ return `
237
+ <article class="task-card">
238
+ <div class="task-copy">
239
+ <strong>${escapeHtml(task.title)}</strong>
240
+ ${description}
241
+ <code>${escapeHtml(task.command)}</code>
242
+ </div>
243
+ <button data-task-id="${escapeAttr(task.id)}" ${disabled ? "disabled" : ""}>${running ? "正在分发…" : "运行"}</button>
244
+ </article>
245
+ `;
246
+ }
247
+ function taskFromConfigState(state, taskId) {
248
+ if (state?.kind !== "loaded" || taskId === null)
249
+ return undefined;
250
+ return state.config.tasks.find((task) => task.id === taskId);
251
+ }
252
+ function taskStyles() {
253
+ return `
254
+ <style>
255
+ :host { display: contents; }
256
+ .toolbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--pi-border-muted); }
257
+ .toolbar-tasks { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
258
+ .viewer { box-sizing: border-box; min-height: 0; overflow: auto; padding: 12px; }
259
+ .tasks-viewer { display: grid; align-content: start; gap: 12px; }
260
+ .tasks { display: grid; gap: 14px; }
261
+ .task-group { display: grid; gap: 10px; }
262
+ .task-group h3 { margin: 4px 0 0; color: var(--pi-text-secondary); font-size: 13px; text-transform: uppercase; letter-spacing: 0.04em; }
263
+ .task-card { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: center; border: 1px solid var(--pi-border); border-radius: 10px; background: var(--pi-surface); padding: 12px; }
264
+ .task-copy { display: grid; min-width: 0; gap: 5px; }
265
+ .task-copy span, .muted { color: var(--pi-muted); }
266
+ code, pre { border: 1px solid var(--pi-border-muted); border-radius: 6px; background: var(--pi-bg); color: var(--pi-text-secondary); font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
267
+ code { overflow: auto; padding: 5px 7px; white-space: nowrap; }
268
+ pre { margin: 8px 0 0; overflow: auto; padding: 8px; white-space: pre-wrap; }
269
+ button { border: 1px solid var(--pi-accent-border); border-radius: 7px; background: var(--pi-accent); color: var(--pi-bg); cursor: pointer; padding: 6px 10px; font: inherit; }
270
+ button.secondary { border-color: var(--pi-border); background: var(--pi-surface); color: var(--pi-text); }
271
+ button:disabled { cursor: wait; opacity: 0.65; }
272
+ .empty-state { border: 1px dashed var(--pi-border-muted); border-radius: 8px; color: var(--pi-muted); padding: 12px; }
273
+ .empty-state p { margin: 6px 0 0; }
274
+ .panel-status { margin: 12px 12px 0; }
275
+ .status { border: 1px solid var(--pi-border); border-radius: 8px; padding: 10px; }
276
+ .status.info { border-color: var(--pi-accent-border); background: var(--pi-bg-overlay-soft); }
277
+ .status.success { border-color: var(--pi-success-border); background: var(--pi-success-surface); color: var(--pi-success); }
278
+ .status.error { border-color: var(--pi-danger); color: var(--pi-danger); }
279
+ .empty { padding: 16px; color: var(--pi-muted); }
280
+ @media (max-width: 760px) {
281
+ .task-card { grid-template-columns: 1fr; }
282
+ .task-card button { justify-self: start; }
283
+ }
284
+ </style>
285
+ `;
286
+ }
287
+ function escapeHtml(value) {
288
+ return String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
289
+ }
290
+ function escapeAttr(value) {
291
+ return escapeHtml(value).replaceAll('"', "&quot;");
292
+ }
@@ -0,0 +1,47 @@
1
+ // Generated from pi-web-plugins\workspace-tasks\workspaceTasksClient.ts. Do not edit directly.
2
+ import { TASKS_CONFIG_PATH, parseTasksConfigText } from "./config.js";
3
+ export const tasksConfigMissingMessage = "这里还没有配置工作区任务。";
4
+ export const tasksConfigMissingHint = `${TASKS_CONFIG_PATH} 是可选文件。如果需要自定义任务,请在当前工作区创建它。`;
5
+ export const tasksConfigUnavailableMessage = "无法加载工作区任务。";
6
+ export const tasksConfigRefreshHint = `修复 ${TASKS_CONFIG_PATH} 后点击刷新。`;
7
+ const missingWorkspaceFileError = "Path does not exist";
8
+ export async function loadWorkspaceTasksConfig(files) {
9
+ let file;
10
+ try {
11
+ file = await files.readFile(TASKS_CONFIG_PATH);
12
+ }
13
+ catch (error) {
14
+ if (errorMessage(error) === missingWorkspaceFileError)
15
+ return missing();
16
+ return unavailable(`无法读取 ${TASKS_CONFIG_PATH}: ${formatUnknownError(error)}`);
17
+ }
18
+ if (file.binary)
19
+ return unavailable(`${TASKS_CONFIG_PATH} 必须是文本文件`);
20
+ if (file.truncated)
21
+ return unavailable(`${TASKS_CONFIG_PATH} 过大,内容已被截断`);
22
+ const result = parseTasksConfigText(file.content);
23
+ if (!result.ok)
24
+ return unavailable(result.error);
25
+ return { kind: "loaded", config: result.config, path: TASKS_CONFIG_PATH };
26
+ }
27
+ function missing() {
28
+ return {
29
+ kind: "missing",
30
+ message: tasksConfigMissingMessage,
31
+ hint: tasksConfigMissingHint,
32
+ };
33
+ }
34
+ function unavailable(detail) {
35
+ return {
36
+ kind: "unavailable",
37
+ message: tasksConfigUnavailableMessage,
38
+ hint: tasksConfigRefreshHint,
39
+ detail,
40
+ };
41
+ }
42
+ function errorMessage(error) {
43
+ return error instanceof Error ? error.message : undefined;
44
+ }
45
+ function formatUnknownError(error) {
46
+ return error instanceof Error ? error.message : String(error);
47
+ }
@@ -0,0 +1,221 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { effectivePiWebConfig } from "./config.js";
5
+ import { SessionDaemonClient } from "./sessiond/sessionDaemonClient.js";
6
+ import { parsePiWebComponentStatus, parsePiWebVersionResponse } from "./shared/piWebStatusParsing.js";
7
+ const PI_WEB_PACKAGE_NAME = "@chainingintention/pi-web-cn";
8
+ const PI_WEB_VERSION_TIMEOUT_MS = 2000;
9
+ const PI_WEB_VERSION_ENDPOINT_PATH = "/api/pi-web/version";
10
+ const PI_WEB_STATUS_ENDPOINT_PATH = "/api/pi-web/status";
11
+ const DEFAULT_PACKAGE_VERSION = "0.0.0-dev";
12
+ export function packageVersion() {
13
+ return readPackageInfo()?.version ?? DEFAULT_PACKAGE_VERSION;
14
+ }
15
+ export async function printPiWebVersionReport() {
16
+ console.log("PI WEB version");
17
+ printInstalledPackageVersions();
18
+ printRunningVersionInfo(await collectRunningVersionInfo());
19
+ }
20
+ function packageRootPath() {
21
+ return dirname(dirname(fileURLToPath(import.meta.url)));
22
+ }
23
+ function packageJsonPath() {
24
+ return join(packageRootPath(), "package.json");
25
+ }
26
+ function readPackageInfo() {
27
+ const path = packageJsonPath();
28
+ try {
29
+ return parsePackageInfo(JSON.parse(readFileSync(path, "utf8")), path);
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ }
35
+ function parsePackageInfo(value, path) {
36
+ if (!isRecord(value))
37
+ return undefined;
38
+ const name = value["name"];
39
+ const version = value["version"];
40
+ if (typeof name !== "string" || name === "" || typeof version !== "string" || version === "")
41
+ return undefined;
42
+ return { name, version, path };
43
+ }
44
+ function webVersionEndpoint() {
45
+ try {
46
+ const { config } = effectivePiWebConfig();
47
+ const host = httpClientHost(config.host);
48
+ const port = config.port ?? 8504;
49
+ return { endpoint: `http://${urlHost(host)}:${String(port)}${PI_WEB_VERSION_ENDPOINT_PATH}` };
50
+ }
51
+ catch (error) {
52
+ return { error: `could not read PI WEB config: ${errorMessage(error)}` };
53
+ }
54
+ }
55
+ function httpClientHost(configuredHost) {
56
+ const host = configuredHost === undefined || configuredHost === "" ? "127.0.0.1" : configuredHost;
57
+ if (host === "0.0.0.0" || host === "::" || host === "[::]")
58
+ return "127.0.0.1";
59
+ return host;
60
+ }
61
+ function urlHost(host) {
62
+ if (host.startsWith("[") || !host.includes(":"))
63
+ return host;
64
+ return `[${host}]`;
65
+ }
66
+ function statusEndpointFor(versionEndpoint) {
67
+ if (!versionEndpoint.endsWith(PI_WEB_VERSION_ENDPOINT_PATH))
68
+ return versionEndpoint;
69
+ return `${versionEndpoint.slice(0, -PI_WEB_VERSION_ENDPOINT_PATH.length)}${PI_WEB_STATUS_ENDPOINT_PATH}`;
70
+ }
71
+ async function fetchPiWebVersionResponse(endpoint) {
72
+ const response = await fetch(endpoint, {
73
+ headers: { accept: "application/json" },
74
+ signal: AbortSignal.timeout(PI_WEB_VERSION_TIMEOUT_MS),
75
+ });
76
+ if (!response.ok)
77
+ throw new Error(`HTTP ${String(response.status)}`);
78
+ const parsed = await response.json();
79
+ const status = parsePiWebVersionResponse(parsed);
80
+ if (status === undefined)
81
+ throw new Error("response did not include PI WEB version information");
82
+ return status;
83
+ }
84
+ async function collectRunningVersionInfo() {
85
+ const endpoint = webVersionEndpoint();
86
+ if (endpoint.endpoint !== undefined) {
87
+ try {
88
+ const status = await fetchPiWebVersionResponse(endpoint.endpoint);
89
+ return { generatedAt: status.generatedAt, web: status.components.web, sessiond: status.components.sessiond };
90
+ }
91
+ catch (error) {
92
+ let webError = `${endpoint.endpoint}: ${errorMessage(error)}`;
93
+ const statusEndpoint = statusEndpointFor(endpoint.endpoint);
94
+ if (statusEndpoint !== endpoint.endpoint && isHttpNotFound(error)) {
95
+ try {
96
+ const status = await fetchPiWebVersionResponse(statusEndpoint);
97
+ return { generatedAt: status.generatedAt, web: status.components.web, sessiond: status.components.sessiond };
98
+ }
99
+ catch (statusError) {
100
+ webError = `${webError}; ${statusEndpoint}: ${errorMessage(statusError)}`;
101
+ }
102
+ }
103
+ return runningVersionInfoWithSessiondFallback({ webError });
104
+ }
105
+ }
106
+ return runningVersionInfoWithSessiondFallback({ webError: endpoint.error ?? "web/API status endpoint unavailable" });
107
+ }
108
+ async function runningVersionInfoWithSessiondFallback(base) {
109
+ const sessiond = await collectRunningSessiondInfo();
110
+ return {
111
+ webError: base.webError,
112
+ ...(sessiond.component === undefined ? {} : { sessiond: sessiond.component }),
113
+ ...(sessiond.error === undefined ? {} : { sessiondError: sessiond.error }),
114
+ };
115
+ }
116
+ async function collectRunningSessiondInfo() {
117
+ try {
118
+ const response = await withTimeout(new SessionDaemonClient().request("GET", "/health"), PI_WEB_VERSION_TIMEOUT_MS, "session daemon health check timed out");
119
+ if (response.statusCode < 200 || response.statusCode >= 300)
120
+ throw new Error(`HTTP ${String(response.statusCode)}`);
121
+ const parsed = response.body === "" ? undefined : JSON.parse(response.body);
122
+ const version = isRecord(parsed) ? parsed["version"] : undefined;
123
+ const component = parsePiWebComponentStatus(version);
124
+ if (component === undefined)
125
+ throw new Error("health response did not include version information");
126
+ return { component };
127
+ }
128
+ catch (error) {
129
+ return { error: errorMessage(error) };
130
+ }
131
+ }
132
+ async function withTimeout(promise, timeoutMs, timeoutMessage) {
133
+ let timeout;
134
+ try {
135
+ return await Promise.race([
136
+ promise,
137
+ new Promise((_, reject) => {
138
+ timeout = setTimeout(() => {
139
+ reject(new Error(timeoutMessage));
140
+ }, timeoutMs);
141
+ }),
142
+ ]);
143
+ }
144
+ finally {
145
+ if (timeout !== undefined)
146
+ clearTimeout(timeout);
147
+ }
148
+ }
149
+ function isHttpNotFound(error) {
150
+ return error instanceof Error && error.message === "HTTP 404";
151
+ }
152
+ function printInstalledPackageVersions() {
153
+ const info = readPackageInfo();
154
+ console.log("Installed packages:");
155
+ if (info === undefined) {
156
+ console.log(`? ${PI_WEB_PACKAGE_NAME}: unknown`);
157
+ console.log(` missing package metadata: ${packageJsonPath()}`);
158
+ return;
159
+ }
160
+ console.log(`✓ ${info.name}: ${info.version}`);
161
+ console.log(` ${info.path}`);
162
+ }
163
+ function printRunningVersionInfo(info) {
164
+ console.log("Running services:");
165
+ if (info.web === undefined)
166
+ printUnavailableComponent("Web/UI", info.webError);
167
+ else
168
+ printComponentVersion(info.web);
169
+ if (info.sessiond === undefined)
170
+ printUnavailableComponent("Session daemon", info.sessiondError);
171
+ else
172
+ printComponentVersion(info.sessiond);
173
+ if (info.generatedAt !== undefined)
174
+ console.log(` reported by web/API at ${info.generatedAt}`);
175
+ }
176
+ function printComponentVersion(component) {
177
+ const icon = component.available ? component.stale ? "!" : "✓" : "?";
178
+ const status = !component.available ? "unavailable" : component.stale ? "restart needed" : "current";
179
+ console.log(`${icon} ${component.label}: ${status}`);
180
+ if (component.available || component.runtimeVersion !== undefined || component.installedVersion !== undefined) {
181
+ console.log(` running: ${formatVersion(component.runtimeVersion)}; installed: ${formatVersion(component.installedVersion)}`);
182
+ }
183
+ const installation = installationLabel(component.installation);
184
+ if (installation !== undefined)
185
+ console.log(` installation: ${installation}`);
186
+ if (component.error !== undefined)
187
+ console.log(` ${component.error}`);
188
+ }
189
+ function printUnavailableComponent(label, error) {
190
+ console.log(`? ${label}: unavailable`);
191
+ if (error !== undefined && error !== "")
192
+ console.log(` ${error}`);
193
+ }
194
+ function installationLabel(installation) {
195
+ if (installation === undefined)
196
+ return undefined;
197
+ if (installation.kind === "pi-package") {
198
+ const source = installation.source ?? "Pi package";
199
+ const scope = installation.scope === undefined ? "" : ` · ${installation.scope}`;
200
+ const path = installation.path === undefined ? "" : ` · ${installation.path}`;
201
+ return `${source}${scope}${path}`;
202
+ }
203
+ if (installation.kind === "npm-global") {
204
+ const npmRoot = installation.npmRoot === undefined ? "" : ` · ${installation.npmRoot}`;
205
+ const path = installation.path === undefined ? "" : ` · ${installation.path}`;
206
+ return `global npm package${npmRoot}${path}`;
207
+ }
208
+ if (installation.kind === "local")
209
+ return installation.path === undefined ? "local checkout" : `local checkout · ${installation.path}`;
210
+ return installation.path === undefined ? "installation unknown" : `installation unknown · ${installation.path}`;
211
+ }
212
+ function formatVersion(version) {
213
+ return version === undefined || version === "" ? "unknown" : version;
214
+ }
215
+ function errorMessage(error) {
216
+ return error instanceof Error ? error.message : String(error);
217
+ }
218
+ function isRecord(value) {
219
+ return typeof value === "object" && value !== null && !Array.isArray(value);
220
+ }
221
+ //# sourceMappingURL=piWebVersionReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piWebVersionReport.js","sourceRoot":"","sources":["../src/piWebVersionReport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { TerminalCommandRun, TerminalCommandRunFilter, TerminalCommandRunHandle, Workspace, WorkspaceTerminalCommandInput } from "../plugin-api.js";
2
+ export interface UnstableRunTerminalCommandInput extends WorkspaceTerminalCommandInput {
3
+ workspace: Workspace;
4
+ }
5
+ export interface UnstableTerminalCommandRunsRuntime {
6
+ runCommand(input: UnstableRunTerminalCommandInput): Promise<TerminalCommandRunHandle>;
7
+ listCommandRuns(filter?: TerminalCommandRunFilter): Promise<TerminalCommandRun[]>;
8
+ getCommandRun(runId: string): Promise<TerminalCommandRun | undefined>;
9
+ open(options?: {
10
+ terminalId?: string | undefined;
11
+ }): void;
12
+ }
13
+ export interface UnstableRuntimeCapabilities {
14
+ terminalCommandRuns: UnstableTerminalCommandRunsRuntime;
15
+ openSettings?: (section?: string) => void;
16
+ }
17
+ export interface UnstablePluginRuntimeContext {
18
+ piWebUnstable?: UnstableRuntimeCapabilities;
19
+ }
20
+ export interface UnstableWorkspacePanelContext {
21
+ piWebUnstable?: Pick<UnstableRuntimeCapabilities, "terminalCommandRuns">;
22
+ }