dsh-edge 0.17.0 → 0.18.0-alpha.2

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.
@@ -268,10 +268,23 @@ window.__ModuleLoader__.load({
268
268
  function messageOf(error) {
269
269
  return error instanceof Error ? error.message : String(error);
270
270
  }
271
+ function isRuntimeState(value) {
272
+ if (value === null || typeof value !== "object") return false;
273
+ const { settings, container } = value;
274
+ return typeof settings === "object" && settings !== null && [
275
+ "auto",
276
+ "light",
277
+ "container"
278
+ ].includes(settings.bashRouting) && [
279
+ 5,
280
+ 10,
281
+ 30
282
+ ].includes(settings.containerSleepMinutes) && (container === null || typeof container === "object" && typeof container.running === "boolean" && typeof container.runningCommands === "number");
283
+ }
271
284
  function isHealth(value) {
272
285
  if (value === null || typeof value !== "object") return false;
273
286
  const health = value;
274
- return health.ok === true && health.service === "dsh-edge" && health.status === "ready" && (health.shell === "just-bash-direct" || health.shell === "just-bash-isolated") && health.storage === "durable-object-sqlite-vfs" && typeof health.deploymentId === "string" && typeof health.version === "string" && typeof health.upstreamVersion === "string";
287
+ return health.ok === true && health.service === "dsh-edge" && health.status === "ready" && (health.shell === "just-bash-direct" || health.shell === "just-bash-isolated" || health.shell === "linux-container") && health.storage === "durable-object-sqlite-vfs" && typeof health.deploymentId === "string" && typeof health.version === "string" && typeof health.upstreamVersion === "string";
275
288
  }
276
289
  /** Lazy, fail-soft controller for the Edge deployment settings page. */
277
290
  var EdgeSettingsController = class EdgeSettingsController {
@@ -284,12 +297,16 @@ window.__ModuleLoader__.load({
284
297
  approvalMode: "never",
285
298
  approvalSaving: false,
286
299
  approvalSaved: false,
300
+ runtimeSaving: false,
301
+ runtimeSaved: false,
302
+ containerStopping: false,
287
303
  mcpServers: [],
288
304
  mcpLoaded: false,
289
305
  mcpSaving: false
290
306
  });
291
307
  loadGeneration = 0;
292
308
  approvalGeneration = 0;
309
+ runtimeGeneration = 0;
293
310
  mcpGeneration = 0;
294
311
  oauthMessageHandler;
295
312
  constructor(io) {
@@ -347,6 +364,7 @@ window.__ModuleLoader__.load({
347
364
  state.approvalError = "Could not load approval setting.";
348
365
  });
349
366
  }
367
+ if (health.shell === "linux-container") await this.refreshRuntime();
350
368
  const mcpGen = ++this.mcpGeneration;
351
369
  try {
352
370
  const mcpResponse = await this.io.fetch("/api/mcp-servers", { credentials: "same-origin" });
@@ -407,6 +425,80 @@ window.__ModuleLoader__.load({
407
425
  });
408
426
  }
409
427
  }
428
+ /** Reload runtime settings and container status. */
429
+ async refreshRuntime() {
430
+ const generation = ++this.runtimeGeneration;
431
+ try {
432
+ const response = await this.io.fetch("/api/runtime", { credentials: "same-origin" });
433
+ const body = response.ok ? await response.json() : void 0;
434
+ if (generation !== this.runtimeGeneration) return;
435
+ if (!isRuntimeState(body)) throw new Error("Invalid runtime response");
436
+ this.store.update((state) => {
437
+ state.runtime = body;
438
+ delete state.runtimeError;
439
+ });
440
+ } catch {
441
+ if (generation !== this.runtimeGeneration) return;
442
+ this.store.update((state) => {
443
+ state.runtimeError = "load";
444
+ });
445
+ }
446
+ }
447
+ async setRuntimeSettings(patch) {
448
+ const generation = ++this.runtimeGeneration;
449
+ this.store.update((state) => {
450
+ state.runtimeSaving = true;
451
+ state.runtimeSaved = false;
452
+ delete state.runtimeError;
453
+ });
454
+ try {
455
+ const response = await this.io.fetch("/api/runtime", {
456
+ method: "PUT",
457
+ credentials: "same-origin",
458
+ headers: { "content-type": "application/json" },
459
+ body: JSON.stringify(patch)
460
+ });
461
+ const body = response.ok ? await response.json() : void 0;
462
+ if (!isRuntimeState(body)) throw new Error("Invalid runtime response");
463
+ this.store.update((state) => {
464
+ state.runtimeSaving = false;
465
+ if (generation !== this.runtimeGeneration) return;
466
+ state.runtime = body;
467
+ state.runtimeSaved = true;
468
+ });
469
+ } catch {
470
+ this.store.update((state) => {
471
+ state.runtimeSaving = false;
472
+ state.runtimeError = "save";
473
+ });
474
+ }
475
+ }
476
+ /** Stop the idle container now; the next Linux command starts it again. */
477
+ async stopContainer() {
478
+ const generation = ++this.runtimeGeneration;
479
+ this.store.update((state) => {
480
+ state.containerStopping = true;
481
+ state.runtimeSaved = false;
482
+ delete state.runtimeError;
483
+ });
484
+ try {
485
+ const { outcome, ...runtime } = await (await this.io.fetch("/api/runtime/container/stop", {
486
+ method: "POST",
487
+ credentials: "same-origin"
488
+ })).json();
489
+ this.store.update((state) => {
490
+ state.containerStopping = false;
491
+ if (generation === this.runtimeGeneration && isRuntimeState(runtime)) state.runtime = runtime;
492
+ if (outcome === "busy") state.runtimeError = "busy";
493
+ else if (outcome !== "stopped") state.runtimeError = "stop";
494
+ });
495
+ } catch {
496
+ this.store.update((state) => {
497
+ state.containerStopping = false;
498
+ state.runtimeError = "stop";
499
+ });
500
+ }
501
+ }
410
502
  async refreshMcpServers() {
411
503
  const mcpGen = ++this.mcpGeneration;
412
504
  try {
@@ -647,7 +739,7 @@ window.__ModuleLoader__.load({
647
739
  };
648
740
  //#endregion
649
741
  //#region \0dsh-edge-css:src/client/EdgeSettingsSection.module.css.mjs
650
- const css = "._68Y4qa_section{gap:20px;max-width:720px;display:grid}._68Y4qa_section header h2,._68Y4qa_card h3{color:var(--dsw-alias-text-primary);margin:0}._68Y4qa_section header p,._68Y4qa_card p{color:var(--dsw-alias-label-secondary)}._68Y4qa_card{border:1px solid var(--dsw-alias-border-subtle);border-radius:12px;padding:18px}._68Y4qa_card dl{margin:12px 0}._68Y4qa_row{border-bottom:1px solid var(--dsw-alias-border-secondary);grid-template-columns:minmax(150px,1fr) minmax(0,2fr);gap:16px;padding:8px 0;display:grid}._68Y4qa_row:last-child{border-bottom:0}._68Y4qa_row dt{color:var(--dsw-alias-label-secondary)}._68Y4qa_row dd{overflow-wrap:anywhere;color:var(--dsw-alias-text-primary);margin:0}._68Y4qa_actions{flex-wrap:wrap;align-items:center;gap:12px;display:flex}._68Y4qa_actions a{color:var(--dsw-alias-brand-primary)}._68Y4qa_status{align-items:center;gap:8px;display:flex}._68Y4qa_notice{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:13px}._68Y4qa_error{word-break:break-word;overflow-wrap:anywhere;font-size:13px;color:var(--dsw-alias-state-error-primary)!important}._68Y4qa_select{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-background-primary));color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));height:34px;font:inherit;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23999' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 10px center;background-repeat:no-repeat;border-radius:8px;padding:0 28px 0 10px;font-size:13px;line-height:1.5}._68Y4qa_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}._68Y4qa_input{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-background-primary));color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));height:34px;font:inherit;box-sizing:border-box;border-radius:8px;width:100%;padding:0 12px;font-size:13px;line-height:1.5}._68Y4qa_input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}._68Y4qa_mcpList{flex-direction:column;gap:10px;margin:0;padding:0;list-style:none;display:flex}._68Y4qa_mcpCard{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:16px;list-style:none;transition:border-color .16s,background .16s}._68Y4qa_mcpCard:hover{border-color:var(--dsw-alias-label-dimmed,#bbb)}._68Y4qa_mcpCardOpen{background:var(--dsw-alias-bg-layer-2,transparent);border-color:var(--dsw-alias-label-dimmed,#bbb)}._68Y4qa_mcpCardHeader{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}._68Y4qa_mcpCardHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}._68Y4qa_mcpAvatar{background:var(--dsw-alias-brand-background,#eef2fe);width:32px;height:32px;color:var(--dsw-alias-brand-primary);border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:flex}._68Y4qa_mcpCardTitleGroup{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}._68Y4qa_mcpCardName{color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));margin:0;font-size:15px;font-weight:600;line-height:1.4}._68Y4qa_mcpCardSub{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));align-items:center;gap:8px;margin:0;font-size:13px;line-height:1.5;display:flex}._68Y4qa_mcpChevron{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));flex:none;transition:transform .16s}._68Y4qa_mcpChevronOpen{transform:rotate(180deg)}._68Y4qa_mcpChevron svg{display:block}._68Y4qa_mcpBadge{border-radius:4px;padding:1px 6px;font-size:11px;font-weight:500}._68Y4qa_mcpBadge[data-status=connected]{background:var(--dsw-alias-state-success-background,#ecfdf3);color:var(--dsw-alias-state-success-primary,#16a34a)}._68Y4qa_mcpBadge[data-status=error]{background:var(--dsw-alias-state-error-background,#fff0f0);color:var(--dsw-alias-state-error-primary,#dc2626)}._68Y4qa_mcpBadge[data-status=needs_reauth]{background:var(--dsw-alias-state-warning-background,#fff8e6);color:var(--dsw-alias-state-warning-primary,#d97706)}._68Y4qa_mcpBadge[data-status=unknown]{background:var(--dsw-alias-background-secondary,#f3f4f6);color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary))}._68Y4qa_mcpCardBody{border-top:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-secondary));gap:12px;min-width:0;margin:0 16px;padding:12px 0 8px;display:grid}._68Y4qa_mcpFieldRow{grid-template-columns:140px 1fr;align-items:center;gap:12px;display:grid}._68Y4qa_mcpFieldLabel{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:13px;line-height:1.5}._68Y4qa_mcpFieldValue{color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));font-size:13px;line-height:1.5}._68Y4qa_mcpCardSuccess{color:var(--dsw-alias-state-success-primary,#16a34a);margin:0;padding:4px 0;font-size:12px;line-height:1.4}._68Y4qa_mcpCardError{color:var(--dsw-alias-state-error-primary,#dc2626);margin:0;padding:4px 0;font-size:12px;line-height:1.4}._68Y4qa_mcpCardActions{border-top:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-secondary));justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}._68Y4qa_mcpAddTrigger{appearance:none;width:100%;font:inherit;cursor:pointer;border:.5px dashed var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));background:0 0;border-radius:16px;justify-content:center;align-items:center;gap:6px;padding:14px 16px;font-size:13px;line-height:1.5;transition:border-color .16s,color .16s;display:flex}._68Y4qa_mcpAddTrigger:hover{border-color:var(--dsw-alias-label-dimmed,#bbb);color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary))}._68Y4qa_mcpAddTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}._68Y4qa_mcpToolList{flex-direction:column;gap:6px;display:flex}._68Y4qa_mcpToolItems{flex-direction:column;gap:0;min-width:0;max-height:300px;margin:4px 0 0;padding:0;list-style:none;display:flex;overflow-y:auto}._68Y4qa_mcpToolItem{border-bottom:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-secondary));flex-wrap:wrap;align-items:baseline;gap:4px 8px;padding:6px 0;display:flex}._68Y4qa_mcpToolItem:last-child{border-bottom:none}._68Y4qa_mcpToolName{font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));font-size:12px}._68Y4qa_mcpToolDesc{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));width:100%;font-size:12px;line-height:1.4}._68Y4qa_mcpAddForm{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));border-radius:16px;gap:14px;padding:16px;display:grid}._68Y4qa_mcpFormRow{grid-template-columns:1fr 1fr;gap:10px;display:grid}._68Y4qa_mcpFormActions{justify-content:flex-end;gap:8px;display:flex}@media (width<=560px){._68Y4qa_row{grid-template-columns:1fr;gap:4px}._68Y4qa_mcpFormRow{grid-template-columns:1fr}._68Y4qa_mcpFieldRow{grid-template-columns:1fr;gap:4px}}";
742
+ const css = "._68Y4qa_section{gap:20px;max-width:720px;display:grid}._68Y4qa_section header h2,._68Y4qa_card h3{color:var(--dsw-alias-text-primary);margin:0}._68Y4qa_section header p,._68Y4qa_card p{color:var(--dsw-alias-label-secondary)}._68Y4qa_card{border:1px solid var(--dsw-alias-border-subtle);border-radius:12px;padding:18px}._68Y4qa_card dl{margin:12px 0}._68Y4qa_row{border-bottom:1px solid var(--dsw-alias-border-secondary);grid-template-columns:minmax(150px,1fr) minmax(0,2fr);gap:16px;padding:8px 0;display:grid}._68Y4qa_row:last-child{border-bottom:0}._68Y4qa_row dt{color:var(--dsw-alias-label-secondary)}._68Y4qa_row dd{overflow-wrap:anywhere;color:var(--dsw-alias-text-primary);margin:0}._68Y4qa_actions{flex-wrap:wrap;align-items:center;gap:12px;display:flex}._68Y4qa_actions a{color:var(--dsw-alias-brand-primary)}._68Y4qa_status{align-items:center;gap:8px;display:flex}._68Y4qa_capabilities{margin:0;padding-left:18px}._68Y4qa_notice{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:13px}._68Y4qa_error{word-break:break-word;overflow-wrap:anywhere;font-size:13px;color:var(--dsw-alias-state-error-primary)!important}._68Y4qa_select{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-background-primary));color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));height:34px;font:inherit;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23999' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 10px center;background-repeat:no-repeat;border-radius:8px;padding:0 28px 0 10px;font-size:13px;line-height:1.5}._68Y4qa_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}._68Y4qa_input{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-background-primary));color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));height:34px;font:inherit;box-sizing:border-box;border-radius:8px;width:100%;padding:0 12px;font-size:13px;line-height:1.5}._68Y4qa_input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}._68Y4qa_mcpList{flex-direction:column;gap:10px;margin:0;padding:0;list-style:none;display:flex}._68Y4qa_mcpCard{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:16px;list-style:none;transition:border-color .16s,background .16s}._68Y4qa_mcpCard:hover{border-color:var(--dsw-alias-label-dimmed,#bbb)}._68Y4qa_mcpCardOpen{background:var(--dsw-alias-bg-layer-2,transparent);border-color:var(--dsw-alias-label-dimmed,#bbb)}._68Y4qa_mcpCardHeader{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}._68Y4qa_mcpCardHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}._68Y4qa_mcpAvatar{background:var(--dsw-alias-brand-background,#eef2fe);width:32px;height:32px;color:var(--dsw-alias-brand-primary);border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:flex}._68Y4qa_mcpCardTitleGroup{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}._68Y4qa_mcpCardName{color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));margin:0;font-size:15px;font-weight:600;line-height:1.4}._68Y4qa_mcpCardSub{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));align-items:center;gap:8px;margin:0;font-size:13px;line-height:1.5;display:flex}._68Y4qa_mcpChevron{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));flex:none;transition:transform .16s}._68Y4qa_mcpChevronOpen{transform:rotate(180deg)}._68Y4qa_mcpChevron svg{display:block}._68Y4qa_mcpBadge{border-radius:4px;padding:1px 6px;font-size:11px;font-weight:500}._68Y4qa_mcpBadge[data-status=connected]{background:var(--dsw-alias-state-success-background,#ecfdf3);color:var(--dsw-alias-state-success-primary,#16a34a)}._68Y4qa_mcpBadge[data-status=error]{background:var(--dsw-alias-state-error-background,#fff0f0);color:var(--dsw-alias-state-error-primary,#dc2626)}._68Y4qa_mcpBadge[data-status=needs_reauth]{background:var(--dsw-alias-state-warning-background,#fff8e6);color:var(--dsw-alias-state-warning-primary,#d97706)}._68Y4qa_mcpBadge[data-status=unknown]{background:var(--dsw-alias-background-secondary,#f3f4f6);color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary))}._68Y4qa_mcpCardBody{border-top:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-secondary));gap:12px;min-width:0;margin:0 16px;padding:12px 0 8px;display:grid}._68Y4qa_mcpFieldRow{grid-template-columns:140px 1fr;align-items:center;gap:12px;display:grid}._68Y4qa_mcpFieldLabel{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));font-size:13px;line-height:1.5}._68Y4qa_mcpFieldValue{color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));font-size:13px;line-height:1.5}._68Y4qa_mcpCardSuccess{color:var(--dsw-alias-state-success-primary,#16a34a);margin:0;padding:4px 0;font-size:12px;line-height:1.4}._68Y4qa_mcpCardError{color:var(--dsw-alias-state-error-primary,#dc2626);margin:0;padding:4px 0;font-size:12px;line-height:1.4}._68Y4qa_mcpCardActions{border-top:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-secondary));justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}._68Y4qa_mcpAddTrigger{appearance:none;width:100%;font:inherit;cursor:pointer;border:.5px dashed var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));background:0 0;border-radius:16px;justify-content:center;align-items:center;gap:6px;padding:14px 16px;font-size:13px;line-height:1.5;transition:border-color .16s,color .16s;display:flex}._68Y4qa_mcpAddTrigger:hover{border-color:var(--dsw-alias-label-dimmed,#bbb);color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary))}._68Y4qa_mcpAddTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}._68Y4qa_mcpToolList{flex-direction:column;gap:6px;display:flex}._68Y4qa_mcpToolItems{flex-direction:column;gap:0;min-width:0;max-height:300px;margin:4px 0 0;padding:0;list-style:none;display:flex;overflow-y:auto}._68Y4qa_mcpToolItem{border-bottom:.5px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-secondary));flex-wrap:wrap;align-items:baseline;gap:4px 8px;padding:6px 0;display:flex}._68Y4qa_mcpToolItem:last-child{border-bottom:none}._68Y4qa_mcpToolName{font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-label-primary,var(--dsw-alias-text-primary));font-size:12px}._68Y4qa_mcpToolDesc{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));width:100%;font-size:12px;line-height:1.4}._68Y4qa_mcpAddForm{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-subtle));border-radius:16px;gap:14px;padding:16px;display:grid}._68Y4qa_mcpFormRow{grid-template-columns:1fr 1fr;gap:10px;display:grid}._68Y4qa_mcpFormActions{justify-content:flex-end;gap:8px;display:flex}@media (width<=560px){._68Y4qa_row{grid-template-columns:1fr;gap:4px}._68Y4qa_mcpFormRow{grid-template-columns:1fr}._68Y4qa_mcpFieldRow{grid-template-columns:1fr;gap:4px}}";
651
743
  const tagId = "dsh-edge-client-ui/src/client/EdgeSettingsSection.module.css";
652
744
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
653
745
  const tag = document.createElement("style");
@@ -658,6 +750,7 @@ window.__ModuleLoader__.load({
658
750
  }
659
751
  var EdgeSettingsSection_module_css_default = {
660
752
  "actions": "_68Y4qa_actions",
753
+ "capabilities": "_68Y4qa_capabilities",
661
754
  "card": "_68Y4qa_card",
662
755
  "error": "_68Y4qa_error",
663
756
  "input": "_68Y4qa_input",
@@ -696,12 +789,161 @@ window.__ModuleLoader__.load({
696
789
  };
697
790
  //#endregion
698
791
  //#region ../../../packages/client/ui-edge/src/client/EdgeSettingsSection.tsx
792
+ /** Each deployment's capabilities, cumulative from the free tier up, and its cost. */
793
+ const CAPABILITIES = {
794
+ "just-bash-direct": {
795
+ can: ["capResearch"],
796
+ cost: "costFree"
797
+ },
798
+ "just-bash-isolated": {
799
+ can: ["capResearch", "capAnalyze"],
800
+ cost: "costPaid"
801
+ },
802
+ "linux-container": {
803
+ can: [
804
+ "capResearch",
805
+ "capAnalyze",
806
+ "capCode"
807
+ ],
808
+ cost: "costContainer"
809
+ }
810
+ };
811
+ const ROUTING_HELP = {
812
+ auto: "routingAutoHelp",
813
+ light: "routingLightHelp",
814
+ container: "routingContainerHelp"
815
+ };
816
+ const RUNTIME_ERRORS = {
817
+ load: "runtimeLoadFailed",
818
+ save: "runtimeSaveFailed",
819
+ busy: "containerBusy",
820
+ stop: "containerStopFailed"
821
+ };
699
822
  function Row({ label, value }) {
700
823
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
701
824
  className: EdgeSettingsSection_module_css_default.row,
702
825
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: value })]
703
826
  });
704
827
  }
828
+ function ContainerCard(props) {
829
+ const { state, refreshRuntime, setRuntimeSettings, stopContainer, t } = props;
830
+ const { runtime } = state;
831
+ const container = runtime?.container ?? null;
832
+ const busy = state.runtimeSaving || state.containerStopping;
833
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
834
+ className: EdgeSettingsSection_module_css_default.card,
835
+ "aria-labelledby": "edge-container-title",
836
+ children: [
837
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
838
+ id: "edge-container-title",
839
+ children: t("linuxContainer")
840
+ }),
841
+ runtime === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", { children: [
842
+ container === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
843
+ label: t("containerStatus"),
844
+ value: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
845
+ className: EdgeSettingsSection_module_css_default.status,
846
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: container.running ? "done" : "idle" }), container.running ? t("containerRunning") : t("containerSleeping")]
847
+ })
848
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
849
+ label: t("containerCommands"),
850
+ value: `${String(container.runningCommands)} / ${String(container.maxConcurrentCommands)}`
851
+ })] }),
852
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
853
+ label: t("bashRouting"),
854
+ value: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
855
+ className: EdgeSettingsSection_module_css_default.select,
856
+ value: runtime.settings.bashRouting,
857
+ disabled: busy,
858
+ "aria-label": t("bashRouting"),
859
+ onChange: (e) => {
860
+ setRuntimeSettings({ bashRouting: e.target.value });
861
+ },
862
+ children: [
863
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
864
+ value: "auto",
865
+ children: t("routingAuto")
866
+ }),
867
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
868
+ value: "light",
869
+ children: t("routingLight")
870
+ }),
871
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
872
+ value: "container",
873
+ children: t("routingContainer")
874
+ })
875
+ ]
876
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
877
+ className: EdgeSettingsSection_module_css_default.notice,
878
+ children: t(ROUTING_HELP[runtime.settings.bashRouting])
879
+ })] })
880
+ }),
881
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
882
+ label: t("containerSleep"),
883
+ value: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
884
+ className: EdgeSettingsSection_module_css_default.select,
885
+ value: runtime.settings.containerSleepMinutes,
886
+ disabled: busy,
887
+ "aria-label": t("containerSleep"),
888
+ onChange: (e) => {
889
+ setRuntimeSettings({ containerSleepMinutes: Number(e.target.value) });
890
+ },
891
+ children: [
892
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
893
+ value: 5,
894
+ children: t("sleep5")
895
+ }),
896
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
897
+ value: 10,
898
+ children: t("sleep10")
899
+ }),
900
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
901
+ value: 30,
902
+ children: t("sleep30")
903
+ })
904
+ ]
905
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
906
+ className: EdgeSettingsSection_module_css_default.notice,
907
+ children: t("containerSleepHelp")
908
+ })] })
909
+ })
910
+ ] }),
911
+ state.runtimeSaved ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
912
+ className: EdgeSettingsSection_module_css_default.status,
913
+ children: t("runtimeSaved")
914
+ }) : null,
915
+ state.runtimeError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
916
+ className: EdgeSettingsSection_module_css_default.error,
917
+ role: "alert",
918
+ children: t(RUNTIME_ERRORS[state.runtimeError])
919
+ }),
920
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
921
+ className: EdgeSettingsSection_module_css_default.actions,
922
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
923
+ variant: "outline",
924
+ size: "sm",
925
+ disabled: busy || container?.running !== true || container.runningCommands > 0,
926
+ onClick: () => {
927
+ stopContainer();
928
+ },
929
+ children: state.containerStopping ? t("sleepingNow") : t("sleepNow")
930
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
931
+ variant: "outline",
932
+ size: "sm",
933
+ disabled: busy,
934
+ onClick: () => {
935
+ refreshRuntime();
936
+ },
937
+ children: t("containerRefresh")
938
+ })]
939
+ }),
940
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
941
+ className: EdgeSettingsSection_module_css_default.notice,
942
+ children: t("sleepNowHelp")
943
+ })
944
+ ]
945
+ });
946
+ }
705
947
  function EdgeSettingsSection(props) {
706
948
  const { useEdgeSettings, load, copyUpgrade, signOut, setApprovalMode, t } = props;
707
949
  (0, react.useEffect)(() => {
@@ -722,79 +964,98 @@ window.__ModuleLoader__.load({
722
964
  },
723
965
  children: t("retry")
724
966
  })]
725
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
726
- className: EdgeSettingsSection_module_css_default.card,
727
- "aria-labelledby": "edge-release-title",
728
- children: [
729
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
730
- id: "edge-release-title",
731
- children: t("release")
732
- }),
733
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", { children: [
734
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
735
- label: t("currentVersion"),
736
- value: state.health.version
967
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
968
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
969
+ className: EdgeSettingsSection_module_css_default.card,
970
+ "aria-labelledby": "edge-release-title",
971
+ children: [
972
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
973
+ id: "edge-release-title",
974
+ children: t("release")
737
975
  }),
738
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
739
- label: t("updateChannel"),
740
- value: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: state.releaseChannel ?? "—" })
976
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", { children: [
977
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
978
+ label: t("currentVersion"),
979
+ value: state.health.version
980
+ }),
981
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
982
+ label: t("updateChannel"),
983
+ value: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: state.releaseChannel ?? "—" })
984
+ }),
985
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
986
+ label: t("latestVersion"),
987
+ value: state.latestVersion ?? "—"
988
+ }),
989
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
990
+ label: t("upstreamVersion"),
991
+ value: state.health.upstreamVersion
992
+ })
993
+ ] }),
994
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
995
+ className: EdgeSettingsSection_module_css_default.status,
996
+ children: [state.releaseStatus === void 0 || state.releaseStatus === "unavailable" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: state.releaseStatus === "update-available" ? "warning" : "done" }), state.releaseStatus === "latest" ? t("latest") : state.releaseStatus === "update-available" ? t("updateAvailable") : state.releaseStatus === "development" ? t("development") : t("unavailable")]
741
997
  }),
742
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
743
- label: t("latestVersion"),
744
- value: state.latestVersion ?? "—"
998
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
999
+ className: EdgeSettingsSection_module_css_default.actions,
1000
+ children: [state.releaseStatus === "update-available" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1001
+ variant: "outline",
1002
+ size: "sm",
1003
+ onClick: () => {
1004
+ copyUpgrade();
1005
+ },
1006
+ children: state.copied ? t("copied") : t("copyUpgrade")
1007
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1008
+ href: DSH_EDGE_RELEASES_URL,
1009
+ target: "_blank",
1010
+ rel: "noreferrer",
1011
+ children: t("releaseNotes")
1012
+ })]
745
1013
  }),
746
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
747
- label: t("upstreamVersion"),
748
- value: state.health.upstreamVersion
1014
+ state.copyError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1015
+ className: EdgeSettingsSection_module_css_default.error,
1016
+ role: "alert",
1017
+ children: t("copyFailed")
749
1018
  })
750
- ] }),
751
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
752
- className: EdgeSettingsSection_module_css_default.status,
753
- children: [state.releaseStatus === void 0 || state.releaseStatus === "unavailable" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: state.releaseStatus === "update-available" ? "warning" : "done" }), state.releaseStatus === "latest" ? t("latest") : state.releaseStatus === "update-available" ? t("updateAvailable") : state.releaseStatus === "development" ? t("development") : t("unavailable")]
754
- }),
755
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
756
- className: EdgeSettingsSection_module_css_default.actions,
757
- children: [state.releaseStatus === "update-available" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
758
- variant: "outline",
759
- size: "sm",
760
- onClick: () => {
761
- copyUpgrade();
762
- },
763
- children: state.copied ? t("copied") : t("copyUpgrade")
764
- }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
765
- href: DSH_EDGE_RELEASES_URL,
766
- target: "_blank",
767
- rel: "noreferrer",
768
- children: t("releaseNotes")
769
- })]
770
- }),
771
- state.copyError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
772
- className: EdgeSettingsSection_module_css_default.error,
773
- role: "alert",
774
- children: t("copyFailed")
775
- })
776
- ]
777
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
778
- className: EdgeSettingsSection_module_css_default.card,
779
- "aria-labelledby": "edge-runtime-title",
780
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
781
- id: "edge-runtime-title",
782
- children: t("runtime")
783
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", { children: [
784
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
785
- label: t("runtime"),
786
- value: state.health.shell === "just-bash-direct" ? t("direct") : t("isolated")
787
- }),
788
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
789
- label: t("storage"),
790
- value: t("durableStorage")
791
- }),
792
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
793
- label: t("deploymentId"),
794
- value: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: state.health.deploymentId })
795
- })
796
- ] })]
797
- })] });
1019
+ ]
1020
+ }),
1021
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1022
+ className: EdgeSettingsSection_module_css_default.card,
1023
+ "aria-labelledby": "edge-capabilities-title",
1024
+ children: [
1025
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
1026
+ id: "edge-capabilities-title",
1027
+ children: t("capabilities")
1028
+ }),
1029
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", { children: [
1030
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1031
+ label: t("capabilityList"),
1032
+ value: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1033
+ className: EdgeSettingsSection_module_css_default.capabilities,
1034
+ children: CAPABILITIES[state.health.shell].can.map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t(key) }, key))
1035
+ })
1036
+ }),
1037
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1038
+ label: t("cost"),
1039
+ value: t(CAPABILITIES[state.health.shell].cost)
1040
+ }),
1041
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1042
+ label: t("storage"),
1043
+ value: t("durableStorage")
1044
+ }),
1045
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1046
+ label: t("deploymentId"),
1047
+ value: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: state.health.deploymentId })
1048
+ })
1049
+ ] }),
1050
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("changeCapabilities") }),
1051
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: upgradeCommand(state.health.version) })
1052
+ ]
1053
+ }),
1054
+ state.health.shell === "linux-container" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContainerCard, {
1055
+ ...props,
1056
+ state
1057
+ }) : null
1058
+ ] });
798
1059
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
799
1060
  className: EdgeSettingsSection_module_css_default.section,
800
1061
  children: [
@@ -1343,9 +1604,42 @@ window.__ModuleLoader__.load({
1343
1604
  updateAvailable: "Update available",
1344
1605
  development: "Development build",
1345
1606
  unavailable: "Could not check npm",
1346
- runtime: "Runtime",
1347
- direct: "Free · Direct Shell",
1348
- isolated: "Isolated · Dynamic Worker",
1607
+ capabilities: "What this instance can do",
1608
+ capabilityList: "Can",
1609
+ capResearch: "Research and write",
1610
+ capAnalyze: "Analyze data and split big jobs",
1611
+ capCode: "Work on code projects",
1612
+ cost: "Cost",
1613
+ costFree: "Free (Workers Free)",
1614
+ costPaid: "Workers Paid (from $5/month)",
1615
+ costContainer: "Workers Paid (from $5/month) plus container time while it runs",
1616
+ changeCapabilities: "To add or remove capabilities, run this command in a terminal and choose “Update and change what it can do”. Conversations and files are kept.",
1617
+ linuxContainer: "Linux container",
1618
+ containerStatus: "Status",
1619
+ containerRunning: "Running",
1620
+ containerSleeping: "Sleeping; the next Linux command wakes it in about 5 seconds",
1621
+ containerCommands: "Commands running",
1622
+ containerRefresh: "Refresh",
1623
+ sleepNow: "Sleep now",
1624
+ sleepingNow: "Stopping…",
1625
+ sleepNowHelp: "A sleeping container is not billed. Unavailable while a command runs.",
1626
+ containerBusy: "A command is running. Try again when it finishes.",
1627
+ containerStopFailed: "Could not stop the container.",
1628
+ bashRouting: "Where commands run",
1629
+ routingAuto: "Automatic (recommended)",
1630
+ routingLight: "Always lightweight",
1631
+ routingContainer: "Always Linux",
1632
+ routingAutoHelp: "File and text commands run in the lightweight shell; git, npm, python, and anything it cannot run go to the container.",
1633
+ routingLightHelp: "Cheapest. Commands that need Linux fail instead of starting the container.",
1634
+ routingContainerHelp: "Closest to a local terminal, but every command wakes the container and costs more.",
1635
+ containerSleep: "Sleep after idle",
1636
+ sleep5: "5 minutes",
1637
+ sleep10: "10 minutes",
1638
+ sleep30: "30 minutes",
1639
+ containerSleepHelp: "Longer means fewer cold starts but a higher bill.",
1640
+ runtimeSaved: "Saved. Applies to the next command.",
1641
+ runtimeSaveFailed: "Could not save setting.",
1642
+ runtimeLoadFailed: "Could not load the container status.",
1349
1643
  storage: "Storage",
1350
1644
  durableStorage: "Durable Object SQLite VFS",
1351
1645
  deploymentId: "Deployment ID",
@@ -1418,9 +1712,42 @@ window.__ModuleLoader__.load({
1418
1712
  updateAvailable: "有可用更新",
1419
1713
  development: "开发版本",
1420
1714
  unavailable: "无法检查 npm",
1421
- runtime: "运行时",
1422
- direct: "免费 · Direct Shell",
1423
- isolated: "隔离 · Dynamic Worker",
1715
+ capabilities: "这个实例能做什么",
1716
+ capabilityList: "能力",
1717
+ capResearch: "调研和写作",
1718
+ capAnalyze: "分析数据、拆分大任务",
1719
+ capCode: "做代码项目",
1720
+ cost: "费用",
1721
+ costFree: "免费(Workers Free)",
1722
+ costPaid: "Workers Paid(每月 $5 起)",
1723
+ costContainer: "Workers Paid(每月 $5 起),另按容器运行时长计费",
1724
+ changeCapabilities: "要增减能力,在终端运行下面的命令,选择“Update and change what it can do”。对话和文件都会保留。",
1725
+ linuxContainer: "Linux 容器",
1726
+ containerStatus: "状态",
1727
+ containerRunning: "运行中",
1728
+ containerSleeping: "休眠中;下一条需要 Linux 的命令会在约 5 秒内唤醒它",
1729
+ containerCommands: "正在运行的命令",
1730
+ containerRefresh: "刷新",
1731
+ sleepNow: "立即休眠",
1732
+ sleepingNow: "正在休眠…",
1733
+ sleepNowHelp: "休眠中的容器不计费。有命令正在运行时不可用。",
1734
+ containerBusy: "有命令正在运行,等它结束后再试。",
1735
+ containerStopFailed: "无法让容器休眠。",
1736
+ bashRouting: "命令执行方式",
1737
+ routingAuto: "自动(推荐)",
1738
+ routingLight: "总是轻量",
1739
+ routingContainer: "总是 Linux",
1740
+ routingAutoHelp: "文件和文本命令在轻量 shell 里运行;git、npm、python,以及轻量 shell 跑不了的命令,自动转到容器。",
1741
+ routingLightHelp: "最省钱。需要 Linux 的命令会直接失败,不会启动容器。",
1742
+ routingContainerHelp: "最接近本地终端,但每条命令都会唤醒容器,费用更高。",
1743
+ containerSleep: "闲置多久后休眠",
1744
+ sleep5: "5 分钟",
1745
+ sleep10: "10 分钟",
1746
+ sleep30: "30 分钟",
1747
+ containerSleepHelp: "时间越长,冷启动越少,但费用越高。",
1748
+ runtimeSaved: "已保存,下一条命令生效。",
1749
+ runtimeSaveFailed: "无法保存设置。",
1750
+ runtimeLoadFailed: "无法加载容器状态。",
1424
1751
  storage: "存储",
1425
1752
  durableStorage: "Durable Object SQLite VFS",
1426
1753
  deploymentId: "部署 ID",
@@ -1511,7 +1838,10 @@ window.__ModuleLoader__.load({
1511
1838
  load: () => controller.load(),
1512
1839
  copyUpgrade: () => controller.copyUpgrade(),
1513
1840
  signOut: () => controller.signOut(),
1514
- setApprovalMode: (mode) => controller.setApprovalMode(mode)
1841
+ setApprovalMode: (mode) => controller.setApprovalMode(mode),
1842
+ refreshRuntime: () => controller.refreshRuntime(),
1843
+ setRuntimeSettings: (patch) => controller.setRuntimeSettings(patch),
1844
+ stopContainer: () => controller.stopContainer()
1515
1845
  });
1516
1846
  const mcpInjected = () => ({
1517
1847
  hooks: { edgeSettings: controller.store },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-edge",
3
- "version": "0.17.0",
3
+ "version": "0.18.0-alpha.2",
4
4
  "description": "Your DeepSeek Harness, anywhere — deploy a persistent personal coding agent to Cloudflare Workers in one command",
5
5
  "author": "pawaca",
6
6
  "license": "MIT",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "devDependencies": {
57
57
  "@cfworker/json-schema": "^4.1.1",
58
- "@cloudflare/computer": "0.2.1",
58
+ "@cloudflare/computer": "0.3.1",
59
59
  "@cloudflare/workers-types": "5.20260904.1",
60
60
  "@deepseek-ai/cordis": "4.0.2",
61
61
  "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
@@ -159,6 +159,7 @@
159
159
  "bundle:workers": "pnpm --dir standalone run build && pnpm --dir standalone run verify && node standalone/scripts/promote.mjs all",
160
160
  "dev": "pnpm run bundle:direct && node scripts/dev.mjs direct",
161
161
  "dev:isolated": "pnpm run bundle:isolated && node scripts/dev.mjs isolated",
162
+ "dev:container": "pnpm run bundle:isolated && node scripts/dev.mjs container",
162
163
  "dsh-edge": "node scripts/cli.mjs",
163
164
  "example:install": "node examples/install-keyless.mjs",
164
165
  "install:cloudflare": "pnpm run bundle:workers && node scripts/cli.mjs install",
@@ -167,6 +168,7 @@
167
168
  "web:build": "pnpm --dir standalone run build:web && node standalone/scripts/promote.mjs web",
168
169
  "test": "vitest run --root ../.. --project edge-runtime",
169
170
  "test:integration": "pnpm run bundle:workers && node tests/run-session-integration.mjs",
171
+ "test:container": "pnpm run bundle:isolated && node tests/container.integration.mjs",
170
172
  "test:snapshot": "vitest run --root ../.. --config apps/dsh-edge/vitest.snapshot.config.ts",
171
173
  "typecheck": "tsc --noEmit"
172
174
  }