@chainingintention/pi-web-cn 1.202610.2 → 1.202610.4

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 (202) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +129 -122
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client/assets/PiWebApp-CN3g7SqA.js +4362 -0
  5. package/dist/client/assets/external-DUGCSDhZ.js +2 -0
  6. package/dist/client/assets/index-JduZlbIF.js +2 -0
  7. package/dist/client/index.html +4 -4
  8. package/dist/client/manifest.webmanifest +2 -1
  9. package/dist/localization.js +24 -0
  10. package/dist/localization.js.map +1 -0
  11. package/dist/nativeServices/serviceDoctor.js +45 -44
  12. package/dist/nativeServices/serviceDoctor.js.map +1 -1
  13. package/dist/pi-packages/captains-log/dist/browser/index.js +46 -45
  14. package/dist/pi-packages/captains-log/dist/browser/markdown.js +2 -1
  15. package/dist/pi-packages/captains-log/dist/browser/panel.js +56 -55
  16. package/dist/pi-packages/captains-log/i18n.js +7 -0
  17. package/dist/pi-packages/relays/i18n.js +7 -0
  18. package/dist/pi-packages/relays/markdownDocument.js +2 -1
  19. package/dist/pi-packages/relays/pi-web-plugin.js +8 -6
  20. package/dist/pi-packages/relays/relaysPanelElement.js +24 -23
  21. package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +124 -124
  22. package/dist/pi-web-plugins/git/browser/git-contract.js +13 -12
  23. package/dist/pi-web-plugins/git/browser/git-panel.js +25 -24
  24. package/dist/pi-web-plugins/git/browser/i18n.js +7 -0
  25. package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +7 -3
  26. package/dist/pi-web-plugins/git/git-backend.js +10 -9
  27. package/dist/pi-web-plugins/git/i18n.js +7 -0
  28. package/dist/pi-web-plugins/git/server-plugin.js +21 -19
  29. package/dist/pi-web-plugins/info/i18n.js +7 -0
  30. package/dist/pi-web-plugins/info/infoInternals.js +57 -62
  31. package/dist/pi-web-plugins/info/pi-web-plugin.js +34 -36
  32. package/dist/pi-web-plugins/mermaid/browser/pi-web-plugin.js +3 -3
  33. package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +55 -52
  34. package/dist/pi-web-plugins/terminal/i18n.js +7 -0
  35. package/dist/pi-web-plugins/terminal/server-plugin.js +23 -21
  36. package/dist/pi-web-plugins/terminal/terminalService.js +22 -21
  37. package/dist/pi-web-plugins/updates/i18n.js +7 -0
  38. package/dist/pi-web-plugins/updates/pi-web-plugin.js +58 -54
  39. package/dist/pi-web-plugins/updates/updatesLogic.js +21 -20
  40. package/dist/pi-web-plugins/workspace-tasks/config.js +12 -11
  41. package/dist/pi-web-plugins/workspace-tasks/i18n.js +7 -0
  42. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +8 -6
  43. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +20 -19
  44. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +12 -11
  45. package/dist/pi-web-plugins/zh-cn/auth.json +9 -0
  46. package/dist/pi-web-plugins/zh-cn/bundled.json +176 -0
  47. package/dist/pi-web-plugins/zh-cn/cli.json +171 -0
  48. package/dist/pi-web-plugins/zh-cn/client.json +219 -0
  49. package/dist/pi-web-plugins/zh-cn/components.json +1002 -0
  50. package/dist/pi-web-plugins/zh-cn/config-errors.json +172 -0
  51. package/dist/pi-web-plugins/zh-cn/files.json +41 -0
  52. package/dist/pi-web-plugins/zh-cn/machines.json +28 -0
  53. package/dist/pi-web-plugins/zh-cn/main.json +459 -0
  54. package/dist/pi-web-plugins/zh-cn/management-errors.json +23 -0
  55. package/dist/pi-web-plugins/zh-cn/manifest.webmanifest +25 -0
  56. package/dist/pi-web-plugins/zh-cn/metadata.json +3 -0
  57. package/dist/pi-web-plugins/zh-cn/package.json +10 -0
  58. package/dist/pi-web-plugins/zh-cn/pi-web-plugin.js +16 -0
  59. package/dist/pi-web-plugins/zh-cn/projects.json +6 -0
  60. package/dist/pi-web-plugins/zh-cn/provider-auth.json +17 -0
  61. package/dist/pi-web-plugins/zh-cn/routing.json +68 -0
  62. package/dist/pi-web-plugins/zh-cn/server-main.json +99 -0
  63. package/dist/pi-web-plugins/zh-cn/server.json +174 -0
  64. package/dist/piWebVersionReport.js +17 -16
  65. package/dist/piWebVersionReport.js.map +1 -1
  66. package/dist/plugin-api.d.ts +4 -1
  67. package/dist/pluginRecoveryCli.js +25 -24
  68. package/dist/pluginRecoveryCli.js.map +1 -1
  69. package/dist/server/app.js +43 -28
  70. package/dist/server/app.js.map +1 -1
  71. package/dist/server/audit/normalToolAuditCli.js +45 -43
  72. package/dist/server/audit/normalToolAuditCli.js.map +1 -1
  73. package/dist/server/configRoutes.js +39 -30
  74. package/dist/server/configRoutes.js.map +1 -1
  75. package/dist/server/diagnostics/nodePtyNativeModule.js +7 -6
  76. package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -1
  77. package/dist/server/diagnostics/nodePtySpawnHelper.js +21 -20
  78. package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -1
  79. package/dist/server/knownAutoInstallPiPackages.js +2 -2
  80. package/dist/server/knownAutoInstallPiPackages.js.map +1 -1
  81. package/dist/server/knownPiPackages.js +2 -2
  82. package/dist/server/knownPiPackages.js.map +1 -1
  83. package/dist/server/machines/machineClient.js +8 -6
  84. package/dist/server/machines/machineClient.js.map +1 -1
  85. package/dist/server/machines/machinePluginProxyRoutes.js +11 -10
  86. package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
  87. package/dist/server/machines/machineProxyRoutes.js +27 -29
  88. package/dist/server/machines/machineProxyRoutes.js.map +1 -1
  89. package/dist/server/machines/machineRoutes.js +10 -12
  90. package/dist/server/machines/machineRoutes.js.map +1 -1
  91. package/dist/server/machines/machineService.js +17 -18
  92. package/dist/server/machines/machineService.js.map +1 -1
  93. package/dist/server/managementEmbed.js +26 -25
  94. package/dist/server/managementEmbed.js.map +1 -1
  95. package/dist/server/normalAuth.js +29 -26
  96. package/dist/server/normalAuth.js.map +1 -1
  97. package/dist/server/passwordVerifier.js +2 -1
  98. package/dist/server/passwordVerifier.js.map +1 -1
  99. package/dist/server/piPackageService.js +7 -5
  100. package/dist/server/piPackageService.js.map +1 -1
  101. package/dist/server/piWebPluginService.js +27 -11
  102. package/dist/server/piWebPluginService.js.map +1 -1
  103. package/dist/server/piWebStatus.js +16 -14
  104. package/dist/server/piWebStatus.js.map +1 -1
  105. package/dist/server/plugins/serverPluginRuntime.js +4 -2
  106. package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
  107. package/dist/server/projects/projectService.js +4 -3
  108. package/dist/server/projects/projectService.js.map +1 -1
  109. package/dist/server/sessiond/projectMutationRoutes.js +5 -4
  110. package/dist/server/sessiond/projectMutationRoutes.js.map +1 -1
  111. package/dist/server/sessiond/sessionProxyRoutes.js +11 -8
  112. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  113. package/dist/server/sessiond/workspaceCatalogRoutes.js +5 -3
  114. package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -1
  115. package/dist/server/sessiond.js +8 -3
  116. package/dist/server/sessiond.js.map +1 -1
  117. package/dist/server/sessions/authRoutes.js +20 -19
  118. package/dist/server/sessions/authRoutes.js.map +1 -1
  119. package/dist/server/sessions/authService.js +13 -10
  120. package/dist/server/sessions/authService.js.map +1 -1
  121. package/dist/server/sessions/builtinCommands.js +28 -21
  122. package/dist/server/sessions/builtinCommands.js.map +1 -1
  123. package/dist/server/sessions/oauthLoginFlowService.js +17 -15
  124. package/dist/server/sessions/oauthLoginFlowService.js.map +1 -1
  125. package/dist/server/sessions/piSessionService.js +229 -208
  126. package/dist/server/sessions/piSessionService.js.map +1 -1
  127. package/dist/server/sessions/projectAuthService.js +5 -3
  128. package/dist/server/sessions/projectAuthService.js.map +1 -1
  129. package/dist/server/sessions/sessionArchiveMapping.js +8 -7
  130. package/dist/server/sessions/sessionArchiveMapping.js.map +1 -1
  131. package/dist/server/sessions/sessionCleanup.js +4 -3
  132. package/dist/server/sessions/sessionCleanup.js.map +1 -1
  133. package/dist/server/sessions/sessionCommandService.js +70 -67
  134. package/dist/server/sessions/sessionCommandService.js.map +1 -1
  135. package/dist/server/sessions/sessionNotificationStore.js +12 -11
  136. package/dist/server/sessions/sessionNotificationStore.js.map +1 -1
  137. package/dist/server/sessions/sessionRoutes.js +74 -72
  138. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  139. package/dist/server/sessions/sessionTreeProjection.js +50 -49
  140. package/dist/server/sessions/sessionTreeProjection.js.map +1 -1
  141. package/dist/server/sessions/sessionUnreadStore.js +25 -2
  142. package/dist/server/sessions/sessionUnreadStore.js.map +1 -1
  143. package/dist/server/terminals/managementCommandRunService.js +13 -12
  144. package/dist/server/terminals/managementCommandRunService.js.map +1 -1
  145. package/dist/server/workbench/accessStateStore.js +9 -7
  146. package/dist/server/workbench/accessStateStore.js.map +1 -1
  147. package/dist/server/workbench/capabilitySearch.js +3 -2
  148. package/dist/server/workbench/capabilitySearch.js.map +1 -1
  149. package/dist/server/workbench/knowledgeSearch.js +8 -7
  150. package/dist/server/workbench/knowledgeSearch.js.map +1 -1
  151. package/dist/server/workbench/mcpClient.js +6 -5
  152. package/dist/server/workbench/mcpClient.js.map +1 -1
  153. package/dist/server/workbench/skillSync.js +4 -2
  154. package/dist/server/workbench/skillSync.js.map +1 -1
  155. package/dist/server/workbench/workbenchClient.js +8 -7
  156. package/dist/server/workbench/workbenchClient.js.map +1 -1
  157. package/dist/server/workbench/workbenchTools.js +8 -6
  158. package/dist/server/workbench/workbenchTools.js.map +1 -1
  159. package/dist/server/workingDirectory.js +3 -2
  160. package/dist/server/workingDirectory.js.map +1 -1
  161. package/dist/server/workspaceExplorerRoutes.js +16 -13
  162. package/dist/server/workspaceExplorerRoutes.js.map +1 -1
  163. package/dist/server/workspaces/fileContentService.js +11 -10
  164. package/dist/server/workspaces/fileContentService.js.map +1 -1
  165. package/dist/server/workspaces/fileOperationService.js +7 -6
  166. package/dist/server/workspaces/fileOperationService.js.map +1 -1
  167. package/dist/server/workspaces/filePreviewService.js +5 -4
  168. package/dist/server/workspaces/filePreviewService.js.map +1 -1
  169. package/dist/server/workspaces/fileSuggestions.js +2 -1
  170. package/dist/server/workspaces/fileSuggestions.js.map +1 -1
  171. package/dist/server/workspaces/pathAccessPolicy.js +24 -18
  172. package/dist/server/workspaces/pathAccessPolicy.js.map +1 -1
  173. package/dist/server/workspaces/pathSafety.js +6 -5
  174. package/dist/server/workspaces/pathSafety.js.map +1 -1
  175. package/dist/server/workspaces/projectPiWebConfig.js +3 -2
  176. package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
  177. package/dist/server/workspaces/workspaceRemovalService.js +4 -3
  178. package/dist/server/workspaces/workspaceRemovalService.js.map +1 -1
  179. package/dist/server/workspaces/workspaceRouteErrors.js +4 -2
  180. package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -1
  181. package/dist/server/workspaces/workspaceUserError.js +18 -0
  182. package/dist/server/workspaces/workspaceUserError.js.map +1 -0
  183. package/dist/server-plugin-api.d.ts +3 -1
  184. package/dist/server-plugin-api.js.map +1 -1
  185. package/dist/serverPluginRecovery.js +3 -2
  186. package/dist/serverPluginRecovery.js.map +1 -1
  187. package/dist/shared/apiTypes.js.map +1 -1
  188. package/dist/shared/i18n.js +41 -0
  189. package/dist/shared/i18n.js.map +1 -0
  190. package/dist/shared/piWebConfigParsing.js +52 -49
  191. package/dist/shared/piWebConfigParsing.js.map +1 -1
  192. package/dist/shared/pluginApiTypes.d.ts +7 -0
  193. package/dist/shared/requiredTerminalPlugin.js +1 -1
  194. package/dist/shared/requiredTerminalPlugin.js.map +1 -1
  195. package/dist/shared/sessionDefaults.js +7 -6
  196. package/dist/shared/sessionDefaults.js.map +1 -1
  197. package/dist/shared/thinkingLevels.js +17 -16
  198. package/dist/shared/thinkingLevels.js.map +1 -1
  199. package/docs/config.md +10 -1
  200. package/docs/plugins.md +8 -0
  201. package/package.json +1 -1
  202. package/dist/client/assets/index-CFhaGb5m.js +0 -4357
@@ -0,0 +1,7 @@
1
+ // Generated from pi-web-plugins/terminal/server/i18n.ts. Do not edit directly.
2
+ let translate;
3
+ export function setTranslator(value) {
4
+ translate = value;
5
+ }
6
+ export const t = (key, fallback, params) => translate?.(key, fallback, params)
7
+ ?? fallback.replace(/\{([A-Za-z0-9_]+)\}/g, (match, name) => String(params?.[name] ?? match));
@@ -1,4 +1,5 @@
1
1
  // Generated from pi-web-plugins/terminal/server/server-plugin.ts. Do not edit directly.
2
+ import { t, setTranslator } from "./i18n.js";
2
3
  import { TerminalService, } from "./terminalService.js";
3
4
  const TERMINAL_CHANNEL_OUTPUT_FRAME_TARGET_BYTES = 60 * 1024;
4
5
  export const TERMINAL_SERVICE_CAPABILITY = Object.freeze({
@@ -9,19 +10,20 @@ export const TERMINAL_SERVICE_CAPABILITY = Object.freeze({
9
10
  });
10
11
  const plugin = {
11
12
  apiVersion: 3,
12
- name: "终端",
13
+ name: t("client.panels.terminal.e2a76e", "Terminal"),
13
14
  activate(context) {
14
15
  return activateTerminalPlugin(context);
15
16
  },
16
17
  };
17
18
  export default plugin;
18
19
  export function activateTerminalPlugin(context) {
20
+ setTranslator(context.translate);
19
21
  if (context.pluginId !== "pi-web.terminal") {
20
- throw new Error(`终端服务端入口必须以插件标识 pi-web.terminal 激活,实际为 ${context.pluginId}`);
22
+ throw new Error(t("ui.main.4b7ba025964e", "The terminal server entry must activate as pi-web.terminal, received {arg0}", { arg0: context.pluginId }));
21
23
  }
22
24
  const notices = context.notices;
23
25
  if (notices?.version !== 1) {
24
- throw new Error("终端服务端入口需要版本 1 的服务通知报告器");
26
+ throw new Error(t("ui.main.1bf6de0c1567", "Terminal server entry requires server notice reporter version 1"));
25
27
  }
26
28
  const service = new TerminalService((input) => { notices.record(input); });
27
29
  const requiredTerminalService = Object.freeze({
@@ -38,7 +40,7 @@ export function activateTerminalPlugin(context) {
38
40
  peer: createTerminalPeer(service, context),
39
41
  provides: Object.freeze([serviceProvision]),
40
42
  health: () => stopped
41
- ? Object.freeze({ status: "unhealthy", message: "终端服务已停止" })
43
+ ? Object.freeze({ status: "unhealthy", message: t("ui.main.ee0fa7cb477f", "Terminal service is stopped") })
42
44
  : Object.freeze({ status: "healthy" }),
43
45
  dispose: () => {
44
46
  if (stopped)
@@ -50,7 +52,7 @@ export function activateTerminalPlugin(context) {
50
52
  }
51
53
  function snapshotTerminalServiceCapability(value) {
52
54
  if (!isRequiredTerminalServiceContribution(value)) {
53
- throw new Error("终端服务能力必须提供 closeForCwd、runCommand 和 bindActivitySink");
55
+ throw new Error(t("ui.main.11f40a27d612", "Terminal service capability must expose closeForCwd, runCommand, and bindActivitySink"));
54
56
  }
55
57
  return Object.freeze({
56
58
  closeForCwd: (cwd) => { value.closeForCwd(cwd); },
@@ -107,12 +109,12 @@ function terminalRequest(service, context) {
107
109
  case "terminal.cancel-run":
108
110
  return commandRunJson(service.cancelCommandRunForScope(scope, requireIdInput(context.input, context.operation, "runId")));
109
111
  default:
110
- throw new Error(`不支持的终端操作: ${context.operation}`);
112
+ throw new Error(t("ui.main.1ba4d446a5f7", "Unsupported terminal operation: {arg0}", { arg0: context.operation }));
111
113
  }
112
114
  }
113
115
  function openTerminalChannel(service, context, activationContext) {
114
116
  if (context.operation !== "terminal.attach") {
115
- throw new Error(`不支持的终端通道操作: ${context.operation}`);
117
+ throw new Error(t("ui.main.745a3a62852f", "Unsupported terminal channel operation: {arg0}", { arg0: context.operation }));
116
118
  }
117
119
  throwIfAborted(context.signal);
118
120
  const scope = terminalScope(context);
@@ -134,7 +136,7 @@ function openTerminalChannel(service, context, activationContext) {
134
136
  if (opening)
135
137
  throw error;
136
138
  detach();
137
- activationContext?.logger.error("终端通道输出失败", {
139
+ activationContext?.logger.error("Terminal channel output failed", {
138
140
  terminalId,
139
141
  message: boundedErrorMessage(error),
140
142
  });
@@ -178,7 +180,7 @@ function openTerminalChannel(service, context, activationContext) {
178
180
  service.resize(scope, terminalId, parsed.cols, parsed.rows);
179
181
  return;
180
182
  }
181
- throw new Error(`不支持的终端通道消息: ${type}`);
183
+ throw new Error(t("ui.main.8de3f24e9b34", "Unsupported terminal channel message: {arg0}", { arg0: type }));
182
184
  },
183
185
  close() {
184
186
  cleanup();
@@ -187,7 +189,7 @@ function openTerminalChannel(service, context, activationContext) {
187
189
  }
188
190
  function terminalScope(context) {
189
191
  if (context.workspace.projectId !== context.project.id) {
190
- throw new Error("终端工作区的项目作用域与宿主项目不匹配");
192
+ throw new Error(t("ui.main.0e2bca4bb08e", "Terminal workspace project scope does not match the host project"));
191
193
  }
192
194
  return Object.freeze({
193
195
  projectId: context.project.id,
@@ -261,9 +263,9 @@ function requireTerminalSize(input, label) {
261
263
  const cols = input["cols"];
262
264
  const rows = input["rows"];
263
265
  if (typeof cols !== "number" || !Number.isFinite(cols) || cols <= 0)
264
- throw new Error(`${label} cols 必须是正数`);
266
+ throw new Error(t("ui.main.4fe2e9e99007", "{arg0} cols must be positive", { arg0: label }));
265
267
  if (typeof rows !== "number" || !Number.isFinite(rows) || rows <= 0)
266
- throw new Error(`${label} rows 必须是正数`);
268
+ throw new Error(t("ui.main.8c77f7625da9", "{arg0} rows must be positive", { arg0: label }));
267
269
  return { cols: Math.floor(cols), rows: Math.floor(rows) };
268
270
  }
269
271
  function requireIdInput(input, operation, key) {
@@ -271,7 +273,7 @@ function requireIdInput(input, operation, key) {
271
273
  }
272
274
  function requireObject(value, label) {
273
275
  if (!isJsonObject(value))
274
- throw new Error(`${label} 输入必须是对象`);
276
+ throw new Error(t("ui.main.d808dc8965e3", "{arg0} input must be an object", { arg0: label }));
275
277
  return value;
276
278
  }
277
279
  function isJsonObject(value) {
@@ -282,19 +284,19 @@ function requireObjectOrEmpty(value, label) {
282
284
  }
283
285
  function requireNullishInput(value, label) {
284
286
  if (value !== null && (typeof value !== "object" || Array.isArray(value) || Object.keys(value).length > 0)) {
285
- throw new Error(`${label} 输入必须是 null 或空对象`);
287
+ throw new Error(t("ui.main.5c96c91dedb1", "{arg0} input must be null or an empty object", { arg0: label }));
286
288
  }
287
289
  }
288
290
  function requireString(record, key, label) {
289
291
  const value = record[key];
290
292
  if (typeof value !== "string" || value.trim() === "")
291
- throw new Error(`${label} ${key} 必须是非空字符串`);
293
+ throw new Error(t("bundled.workspace-tasks.must.be.a.non.empty.string.838d0a", "{value1} {value2} must be a non-empty string", { value1: label, value2: key }));
292
294
  return value;
293
295
  }
294
296
  function requireTerminalInputData(record) {
295
297
  const value = record["data"];
296
298
  if (typeof value !== "string" || value === "")
297
- throw new Error("terminal.attach input frame data 必须是非空字符串");
299
+ throw new Error(t("ui.main.5bac4f59d1de", "terminal.attach input frame data must be a non-empty string"));
298
300
  return value;
299
301
  }
300
302
  function optionalString(record, key, label) {
@@ -302,20 +304,20 @@ function optionalString(record, key, label) {
302
304
  if (value === undefined)
303
305
  return undefined;
304
306
  if (typeof value !== "string")
305
- throw new Error(`${label} ${key} 必须是字符串`);
307
+ throw new Error(t("ui.main.90ec567aed4b", "{arg0} {arg1} must be a string", { arg0: label, arg1: key }));
306
308
  return value;
307
309
  }
308
310
  function stringRecord(value, label) {
309
311
  const record = requireObject(value, label);
310
312
  return Object.fromEntries(Object.entries(record).map(([key, child]) => {
311
313
  if (typeof child !== "string")
312
- throw new Error(`${label} ${key} 必须是字符串`);
314
+ throw new Error(t("ui.main.90ec567aed4b", "{arg0} {arg1} must be a string", { arg0: label, arg1: key }));
313
315
  return [key, child];
314
316
  }));
315
317
  }
316
318
  function requireArray(value, label) {
317
319
  if (!isJsonArray(value))
318
- throw new Error(`${label} 必须是数组`);
320
+ throw new Error(t("ui.main.05dcf0046d6e", "{arg0} must be an array", { arg0: label }));
319
321
  return value;
320
322
  }
321
323
  function isJsonArray(value) {
@@ -324,7 +326,7 @@ function isJsonArray(value) {
324
326
  function parseCommandRunStatus(value) {
325
327
  if (value === "queued" || value === "running" || value === "succeeded" || value === "failed")
326
328
  return value;
327
- throw new Error(`无效的终端命令运行状态: ${JSON.stringify(value)}`);
329
+ throw new Error(t("ui.main.b302a96237f7", "Invalid terminal command run status: {arg0}", { arg0: JSON.stringify(value) }));
328
330
  }
329
331
  export function terminalOutputFrames(value, replay) {
330
332
  const emptyFrame = terminalOutputFrame("", replay, false);
@@ -357,7 +359,7 @@ function throwIfAborted(signal) {
357
359
  if (!signal.aborted)
358
360
  return;
359
361
  const reason = signal.reason;
360
- throw reason instanceof Error ? reason : new Error("终端操作已取消", { cause: reason });
362
+ throw reason instanceof Error ? reason : new Error(t("ui.main.398328b7ef67", "Terminal operation was cancelled"), { cause: reason });
361
363
  }
362
364
  function boundedErrorMessage(error) {
363
365
  const message = error instanceof Error ? error.message : String(error);
@@ -1,4 +1,5 @@
1
1
  // Generated from pi-web-plugins/terminal/server/terminalService.ts. Do not edit directly.
2
+ import { t } from "./i18n.js";
2
3
  import { randomUUID } from "node:crypto";
3
4
  import { EventEmitter } from "node:events";
4
5
  import { existsSync } from "node:fs";
@@ -17,7 +18,7 @@ export class TerminalService {
17
18
  }
18
19
  bindActivitySink(sink) {
19
20
  if (this.activitySink !== undefined)
20
- throw new Error("终端活动接收器已绑定");
21
+ throw new Error(t("ui.main.5d3c64acebaa", "Terminal activity sink is already bound"));
21
22
  this.activitySink = sink;
22
23
  }
23
24
  list(scope) {
@@ -28,7 +29,7 @@ export class TerminalService {
28
29
  }
29
30
  closeForCwd(cwd) {
30
31
  if (cwd === "")
31
- throw new Error("cwd 不能为空");
32
+ throw new Error(t("ui.main.3554e67956ef", "cwd is required"));
32
33
  for (const terminal of [...this.terminals.values()].filter((candidate) => candidate.cwd === cwd)) {
33
34
  this.closeRecord(terminal);
34
35
  }
@@ -47,7 +48,7 @@ export class TerminalService {
47
48
  const metadata = parseMetadata(options.metadata);
48
49
  const failureNotice = parseFailureNotice(options.failureNotice);
49
50
  if (failureNotice !== undefined && this.recordNotice === undefined) {
50
- throw new Error("终端命令失败通知不可用");
51
+ throw new Error(t("ui.main.e4f11dab9de6", "Terminal command failure notices are unavailable"));
51
52
  }
52
53
  const queued = {
53
54
  id: commandRunId,
@@ -110,7 +111,7 @@ export class TerminalService {
110
111
  cancelCommandRunForScope(scope, runId) {
111
112
  const run = this.getCommandRunForScope(scope, runId);
112
113
  if (run === undefined)
113
- throw new Error("此工作区中未找到终端命令运行记录");
114
+ throw new Error(t("ui.main.3bea6b3edcd2", "Terminal command run not found in this workspace"));
114
115
  return this.cancelCommandRunRecord(this.requireCommandRun(runId));
115
116
  }
116
117
  get(scope, id) {
@@ -157,7 +158,7 @@ export class TerminalService {
157
158
  delete record.exitCode;
158
159
  delete record.commandRunId;
159
160
  record.exited = false;
160
- const marker = "\r\n[已继续进入交互式终端]\r\n";
161
+ const marker = t("ui.main.7e39d66ff416", "\r\n[continued in interactive shell]\r\n");
161
162
  record.buffer = trimReplayBuffer(record.buffer + marker);
162
163
  record.events.emit("output", marker);
163
164
  const shell = interactiveShell();
@@ -185,7 +186,7 @@ export class TerminalService {
185
186
  if (terminal === undefined)
186
187
  return;
187
188
  if (!matchesScope(terminal, scope))
188
- throw new Error("此工作区中未找到终端");
189
+ throw new Error(t("ui.main.002ca07f2de5", "Terminal not found in this workspace"));
189
190
  this.closeRecord(terminal);
190
191
  }
191
192
  dispose() {
@@ -269,14 +270,14 @@ export class TerminalService {
269
270
  validateScope(scope);
270
271
  const terminal = this.terminals.get(id);
271
272
  if (terminal === undefined || !matchesScope(terminal, scope)) {
272
- throw new Error("此工作区中未找到终端");
273
+ throw new Error(t("ui.main.002ca07f2de5", "Terminal not found in this workspace"));
273
274
  }
274
275
  return terminal;
275
276
  }
276
277
  requireCommandRun(runId) {
277
278
  const run = this.commandRuns.get(runId);
278
279
  if (run === undefined)
279
- throw new Error("未找到终端命令运行记录");
280
+ throw new Error(t("ui.shared.ca71fd855ae2", "Terminal command run not found"));
280
281
  return run;
281
282
  }
282
283
  cancelCommandRunRecord(run) {
@@ -284,7 +285,7 @@ export class TerminalService {
284
285
  return copyCommandRun(run);
285
286
  const terminal = this.terminals.get(run.terminalId);
286
287
  if (terminal === undefined)
287
- throw new Error("未找到终端");
288
+ throw new Error(t("ui.main.970ebf253e68", "Terminal not found"));
288
289
  if (!terminal.exited && terminal.cancellationRequested !== true) {
289
290
  terminal.cancellationRequested = true;
290
291
  try {
@@ -308,7 +309,7 @@ export class TerminalService {
308
309
  }
309
310
  requireAvailable() {
310
311
  if (this.disposed)
311
- throw new Error("终端服务已停止");
312
+ throw new Error(t("ui.main.ee0fa7cb477f", "Terminal service is stopped"));
312
313
  }
313
314
  }
314
315
  function toInfo(record) {
@@ -364,11 +365,11 @@ function shellQuote(value) {
364
365
  }
365
366
  function validateScope(scope) {
366
367
  if (scope.projectId.trim() === "")
367
- throw new Error("projectId 不能为空");
368
+ throw new Error(t("ui.main.c785a1f6204e", "projectId is required"));
368
369
  if (scope.workspaceId.trim() === "")
369
- throw new Error("workspaceId 不能为空");
370
+ throw new Error(t("ui.main.9850b858e3ba", "workspaceId is required"));
370
371
  if (scope.cwd.trim() === "")
371
- throw new Error("cwd 不能为空");
372
+ throw new Error(t("ui.main.3554e67956ef", "cwd is required"));
372
373
  }
373
374
  function matchesScope(record, scope) {
374
375
  return record.projectId === scope.projectId
@@ -378,23 +379,23 @@ function matchesScope(record, scope) {
378
379
  function validateCommandRunOptions(options) {
379
380
  validateScope(options);
380
381
  if (options.origin.trim() === "")
381
- throw new Error("origin 不能为空");
382
+ throw new Error(t("ui.main.0b08e0eda1a4", "origin is required"));
382
383
  if (options.title.trim() === "")
383
- throw new Error("title 不能为空");
384
+ throw new Error(t("ui.main.394f110fbd2e", "title is required"));
384
385
  if (options.command.trim() === "")
385
- throw new Error("command 不能为空");
386
+ throw new Error(t("ui.main.f3029405fa76", "command is required"));
386
387
  parseMetadata(options.metadata);
387
388
  }
388
389
  function parseMetadata(value) {
389
390
  if (value === undefined || value === null)
390
391
  return {};
391
392
  if (!isRecord(value))
392
- throw new Error("metadata 必须是对象");
393
+ throw new Error(t("ui.main.8aaf09278346", "metadata must be an object"));
393
394
  return Object.fromEntries(Object.entries(value).map(([key, metadataValue]) => {
394
395
  if (key.trim() === "")
395
- throw new Error("metadata 键不能为空");
396
+ throw new Error(t("ui.main.32968c7e6565", "metadata keys must not be empty"));
396
397
  if (typeof metadataValue !== "string")
397
- throw new Error("metadata 值必须是字符串");
398
+ throw new Error(t("ui.main.ca6186d140b2", "metadata values must be strings"));
398
399
  return [key, metadataValue];
399
400
  }));
400
401
  }
@@ -402,10 +403,10 @@ function parseFailureNotice(value) {
402
403
  if (value === undefined)
403
404
  return undefined;
404
405
  if (typeof value.message !== "string" || value.message.trim() === "") {
405
- throw new Error("failureNotice message 必须是非空字符串");
406
+ throw new Error(t("ui.main.b63294884798", "failureNotice message must be a non-empty string"));
406
407
  }
407
408
  if (!isRecord(value.context) || !Object.values(value.context).every((item) => typeof item === "string")) {
408
- throw new Error("failureNotice context 只能包含字符串");
409
+ throw new Error(t("ui.main.a38dcafc6669", "failureNotice context must contain only strings"));
409
410
  }
410
411
  return Object.freeze({ message: value.message, context: Object.freeze({ ...value.context }) });
411
412
  }
@@ -0,0 +1,7 @@
1
+ // Generated from pi-web-plugins/updates/i18n.ts. Do not edit directly.
2
+ let translate;
3
+ export function setTranslator(value) {
4
+ translate = value;
5
+ }
6
+ export const t = (key, fallback, params) => translate?.(key, fallback, params)
7
+ ?? fallback.replace(/\{([A-Za-z0-9_]+)\}/g, (match, name) => String(params?.[name] ?? match));
@@ -1,4 +1,5 @@
1
1
  // Generated from pi-web-plugins/updates/pi-web-plugin.ts. Do not edit directly.
2
+ import { t, setTranslator } from "./i18n.js";
2
3
  import { additionalCommands, fallbackDockerStatus, formatVersion, installationLabel, messageCount, recommendedCommand, shouldShowUpdatesPanel, statusFor } from "./updatesLogic.js";
3
4
  function runCommandInTerminal(terminal, label, command) {
4
5
  void terminal.runCommand({
@@ -7,7 +8,7 @@ function runCommandInTerminal(terminal, label, command) {
7
8
  open: true,
8
9
  metadata: { "pi.plugin": "updates" },
9
10
  }).catch((error) => {
10
- console.error(`更新插件执行 "${label}" 失败`, error);
11
+ console.error(t("ui.main.3b3df75b9391", "Updates plugin failed to run \"{arg0}\"", { arg0: label }), error);
11
12
  });
12
13
  }
13
14
  async function copyCommandToClipboard(command, target) {
@@ -16,7 +17,7 @@ async function copyCommandToClipboard(command, target) {
16
17
  if (button === undefined)
17
18
  return;
18
19
  const original = button.textContent;
19
- button.textContent = copied ? "已复制" : "复制失败";
20
+ button.textContent = copied ? t("ui.toolExecutionView.copied", "Copied") : t("bundled.updates.copy.failed.753d8b", "Copy failed");
20
21
  window.setTimeout(() => {
21
22
  button.textContent = original;
22
23
  }, 1200);
@@ -68,17 +69,17 @@ function copyWithSelectionFallback(text) {
68
69
  }
69
70
  }
70
71
  function renderComponent(html, component) {
71
- const label = component.component === "sessiond" ? "会话守护进程" : "Web/界面";
72
+ const label = component.component === "sessiond" ? t("bundled.updates.session.daemon.757666", "Session daemon") : t("bundled.updates.web.ui.86d6a2", "Web/UI");
72
73
  const status = !component.available
73
- ? "不可用"
74
+ ? t("bundled.info.unavailable.460b35", "Unavailable")
74
75
  : component.stale
75
- ? "需要重启"
76
- : "当前版本";
76
+ ? t("bundled.info.restart.needed.1ffd00", "Restart needed")
77
+ : t("bundled.info.current.837bc9", "Current");
77
78
  return html `
78
79
  <div class="updates-version-row">
79
80
  <strong>${label}</strong>
80
81
  <span>${status}</span>
81
- <small>运行中 ${formatVersion(component.runtimeVersion)} · 已安装 ${formatVersion(component.installedVersion)}</small>
82
+ <small>${t("ui.toolExecutionView.running", "Running")} ${formatVersion(component.runtimeVersion)}${t("ui.main.b2a2f69aef6f", " · installed ")}${formatVersion(component.installedVersion)}</small>
82
83
  <small>${installationLabel(component.installation)}${component.installation?.path === undefined ? "" : ` · ${component.installation.path}`}</small>
83
84
  </div>
84
85
  `;
@@ -86,8 +87,8 @@ function renderComponent(html, component) {
86
87
  function renderCommandActions(html, terminal, label, command) {
87
88
  return html `
88
89
  <span class="updates-command-actions">
89
- <button @click=${(event) => { void copyCommandToClipboard(command, event?.currentTarget); }}>复制</button>
90
- ${terminal === undefined ? null : html `<button class="primary" @click=${() => { runCommandInTerminal(terminal, label, command); }}>运行</button>`}
90
+ <button @click=${(event) => { void copyCommandToClipboard(command, event?.currentTarget); }}>${t("bundled.updates.copy.63d90d", "Copy")}</button>
91
+ ${terminal === undefined ? null : html `<button class="primary" @click=${() => { runCommandInTerminal(terminal, label, command); }}>${t("bundled.workspace-tasks.run.75b269", "Run")}</button>`}
91
92
  </span>
92
93
  `;
93
94
  }
@@ -119,13 +120,13 @@ function renderNotice(html, message) {
119
120
  `;
120
121
  }
121
122
  function renderNotices(html, messages) {
122
- return html `<section>${messages.length === 0 ? html `<p class="muted">没有 PI WEB 更新或重启消息。</p>` : messages.map((message) => renderNotice(html, message))}</section>`;
123
+ return html `<section>${messages.length === 0 ? html `<p class="muted">${t("bundled.updates.no.pi.web.update.or.restart.messages.a2f50d", "No PI WEB update or restart messages.")}</p>` : messages.map((message) => renderNotice(html, message))}</section>`;
123
124
  }
124
125
  function renderRecommended(html, terminal, recommended, messages) {
125
126
  return html `
126
127
  <section class="updates-recommended">
127
- <strong>推荐</strong>
128
- ${messages.length === 0 ? html `<p class="muted">运行这一条命令即可将当前安装更新到最新状态。不需要其他操作。</p>` : messages.map((message) => renderNotice(html, message))}
128
+ <strong>${t("bundled.updates.recommended.1452de", "Recommended")}</strong>
129
+ ${messages.length === 0 ? html `<p class="muted">${t("bundled.updates.run.this.command.to.bring.the.current.installation.up.to.date.no..99197c", "Run this command to bring the current installation up to date. No other steps are required.")}</p>` : messages.map((message) => renderNotice(html, message))}
129
130
  ${renderCommand(html, terminal, recommended.label, recommended.command)}
130
131
  </section>
131
132
  `;
@@ -135,8 +136,8 @@ function renderAdditionalCommands(html, terminal, additional, hasRecommended) {
135
136
  return undefined;
136
137
  return html `
137
138
  <section>
138
- <strong>${hasRecommended ? "其他命令(可选)" : "建议命令"}</strong>
139
- ${hasRecommended ? html `<p class="muted">仅在需要更细粒度控制时使用,例如只重启某个服务。</p>` : null}
139
+ <strong>${hasRecommended ? t("ui.main.7ccbaa176fa0", "Additional commands (optional)") : t("bundled.updates.suggested.commands.d22916", "Suggested commands")}</strong>
140
+ ${hasRecommended ? html `<p class="muted">${t("bundled.updates.use.only.for.finer.control.such.as.restarting.a.single.service.f2c8d9", "Use only for finer control, such as restarting a single service.")}</p>` : null}
140
141
  ${additional.map((entry) => renderCommand(html, terminal, entry.label, entry.command))}
141
142
  </section>
142
143
  `;
@@ -145,8 +146,8 @@ function renderUpdatesPanel(html, terminal, state) {
145
146
  const status = statusFor(state) ?? fallbackDockerStatus(runtimeHint);
146
147
  if (status === undefined) {
147
148
  return html `
148
- <section class="toolbar"><strong>更新</strong></section>
149
- <section class="viewer"><p class="muted">正在检查 PI WEB 更新状态…</p></section>
149
+ <section class="toolbar"><strong>${t("bundled.updates.updates.3055a0", "Updates")}</strong></section>
150
+ <section class="viewer"><p class="muted">${t("bundled.updates.checking.pi.web.update.status.24e243", "Checking PI WEB update status...")}</p></section>
150
151
  `;
151
152
  }
152
153
  const messages = status.messages;
@@ -176,12 +177,12 @@ function renderUpdatesPanel(html, terminal, state) {
176
177
  .updates-command > span { grid-column: 1 / -1; }
177
178
  }
178
179
  </style>
179
- <section class="toolbar"><strong>更新</strong>${messages.length > 0 ? html `<span class="stale">${String(messages.length)}</span>` : null}</section>
180
+ <section class="toolbar"><strong>${t("bundled.updates.updates.3055a0", "Updates")}</strong>${messages.length > 0 ? html `<span class="stale">${String(messages.length)}</span>` : null}</section>
180
181
  <section class="viewer updates-status">
181
182
  ${recommended === undefined ? renderNotices(html, messages) : renderRecommended(html, terminal, recommended, messages)}
182
183
 
183
184
  <section>
184
- <strong>已安装服务</strong>
185
+ <strong>${t("bundled.updates.installed.services.ef70c6", "Installed services")}</strong>
185
186
  ${renderComponent(html, status.components.web)}
186
187
  ${renderComponent(html, status.components.sessiond)}
187
188
  </section>
@@ -189,43 +190,45 @@ function renderUpdatesPanel(html, terminal, state) {
189
190
  ${renderAdditionalCommands(html, terminal, additional, recommended !== undefined)}
190
191
 
191
192
  <section class="updates-meta">
192
- <span>生成时间 ${status.generatedAt}</span>
193
- ${status.release.latestVersion === undefined ? null : html `<span>最新 npm 版本 ${status.release.latestVersion}</span>`}
194
- ${status.release.checkedAt === undefined || status.release.skipped === true ? null : html `<span>发布检查时间 ${status.release.checkedAt}</span>`}
195
- ${status.release.skipped === true ? html `<span>远程版本检查已跳过。</span>` : null}
196
- ${status.release.error === undefined ? null : html `<span>远程版本检查失败:${status.release.error}</span>`}
193
+ <span>${t("ui.main.2213d2e64aff", "Generated")} ${status.generatedAt}</span>
194
+ ${status.release.latestVersion === undefined ? null : html `<span>${t("ui.main.f7047c4cb0e0", "Latest npm release")} ${status.release.latestVersion}</span>`}
195
+ ${status.release.checkedAt === undefined || status.release.skipped === true ? null : html `<span>${t("ui.main.58006f4511ed", "Release checked")} ${status.release.checkedAt}</span>`}
196
+ ${status.release.skipped === true ? html `<span>${t("bundled.updates.remote.version.check.skipped.66de71", "Remote version check skipped.")}</span>` : null}
197
+ ${status.release.error === undefined ? null : html `<span>${t("ui.main.30c7a262a7d1", "Remote version check failed:")}${status.release.error}</span>`}
197
198
  </section>
198
199
  </section>
199
200
  `;
200
201
  }
201
202
  function severityLabel(severity) {
202
203
  if (severity === "warning")
203
- return "警告";
204
+ return t("client.sessionNotifications.warning.a8b7a4", "Warning");
204
205
  if (severity === "error")
205
- return "错误";
206
+ return t("client.sessionNotifications.error.0bc1fb", "Error");
206
207
  return severity;
207
208
  }
208
209
  const plugin = {
209
210
  apiVersion: 4,
210
- name: "更新",
211
- activate: ({ html, svg }) => ({
212
- contributions: {
213
- actions: [
214
- {
215
- id: "check",
216
- title: "检查 PI WEB 更新",
217
- description: "忽略缓存的发布信息,立即检查所选机器",
218
- group: "更新",
219
- enabled: (context) => context.checkForPiWebUpdates !== undefined,
220
- disabledReason: () => "检查更新需要较新版本的 PI WEB 网关",
221
- run: (context) => context.checkForPiWebUpdates?.(),
222
- },
223
- ],
224
- workspacePanels: [
225
- {
226
- id: "workspace.updates",
227
- title: "更新",
228
- icon: svg `
211
+ name: t("bundled.updates.updates.3055a0", "Updates"),
212
+ activate: ({ html, svg, translate }) => {
213
+ setTranslator(translate);
214
+ return ({
215
+ contributions: {
216
+ actions: [
217
+ {
218
+ id: "check",
219
+ title: t("bundled.updates.check.for.pi.web.updates.2062d8", "Check for PI WEB updates"),
220
+ description: t("bundled.updates.check.the.selected.machine.now.ignoring.cached.release.informatio.e12ea5", "Check the selected machine now, ignoring cached release information"),
221
+ group: t("bundled.updates.updates.3055a0", "Updates"),
222
+ enabled: (context) => context.checkForPiWebUpdates !== undefined,
223
+ disabledReason: () => t("bundled.updates.checking.for.updates.requires.a.newer.pi.web.gateway.0a72c8", "Checking for updates requires a newer PI WEB gateway"),
224
+ run: (context) => context.checkForPiWebUpdates?.(),
225
+ },
226
+ ],
227
+ workspacePanels: [
228
+ {
229
+ id: "workspace.updates",
230
+ title: t("bundled.updates.updates.3055a0", "Updates"),
231
+ icon: svg `
229
232
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
230
233
  <path d="M20 6v5h-5"></path>
231
234
  <path d="M4 18v-5h5"></path>
@@ -233,16 +236,17 @@ const plugin = {
233
236
  <path d="M5.6 15A7 7 0 0 0 17.9 17.3L20 15.2"></path>
234
237
  </svg>
235
238
  `,
236
- order: 100,
237
- visible: (context) => shouldShowUpdatesPanel(context.state, runtimeHint),
238
- badge: (context) => {
239
- const count = messageCount(context.state);
240
- return count > 0 ? count : undefined;
239
+ order: 100,
240
+ visible: (context) => shouldShowUpdatesPanel(context.state, runtimeHint),
241
+ badge: (context) => {
242
+ const count = messageCount(context.state);
243
+ return count > 0 ? count : undefined;
244
+ },
245
+ render: (context) => renderUpdatesPanel(html, context.terminal, context.state),
241
246
  },
242
- render: (context) => renderUpdatesPanel(html, context.terminal, context.state),
243
- },
244
- ],
245
- },
246
- }),
247
+ ],
248
+ },
249
+ });
250
+ },
247
251
  };
248
252
  export default plugin;