@geminixiang/mikan 1.0.0-beta.62 → 1.0.0-beta.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +13 -13
- package/dist/adapters/commands/sandbox.d.ts.map +1 -1
- package/dist/adapters/commands/sandbox.js +30 -53
- package/dist/adapters/commands/sandbox.js.map +1 -1
- package/dist/adapters/commands/types.d.ts +3 -3
- package/dist/adapters/commands/types.d.ts.map +1 -1
- package/dist/adapters/commands/types.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +8 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +32 -2
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/web/admin/portal.d.ts.map +1 -1
- package/dist/adapters/web/admin/portal.js +28 -121
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/config.d.ts +13 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -50
- package/dist/config.js.map +1 -1
- package/dist/harness/execution-resolver.d.ts.map +1 -1
- package/dist/harness/execution-resolver.js +1 -1
- package/dist/harness/execution-resolver.js.map +1 -1
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +17 -21
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +2 -2
- package/dist/harness/runner.js.map +1 -1
- package/dist/office/projection.d.ts +19 -2
- package/dist/office/projection.d.ts.map +1 -1
- package/dist/office/projection.js +73 -98
- package/dist/office/projection.js.map +1 -1
- package/dist/office/types.d.ts +13 -8
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/sandbox/index.d.ts +9 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +16 -12
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/provisioner.d.ts +8 -0
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +36 -0
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/settings-mutation.d.ts +5 -29
- package/dist/settings-mutation.d.ts.map +1 -1
- package/dist/settings-mutation.js +7 -13
- package/dist/settings-mutation.js.map +1 -1
- package/dist/types.d.ts +5 -23
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../../../src/adapters/web/admin/portal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,qBAAa,uBAAwB,SAAQ,kBAAkB,CAAC,UAAU,CAAC;IACzE,MAAM,CAAC,IAAI,EAAE;QACX,QAAQ,EAAE,YAAY,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,GAAG,UAAU,CAUb;CACF;
|
|
1
|
+
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../../../src/adapters/web/admin/portal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,qBAAa,uBAAwB,SAAQ,kBAAkB,CAAC,UAAU,CAAC;IACzE,MAAM,CAAC,IAAI,EAAE;QACX,QAAQ,EAAE,YAAY,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,GAAG,UAAU,CAUb;CACF;AAoCD,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAYzD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,OAAO,CAAC,CA6BlB;AAwGD,UAAU,sBAAsB;IAC9B,OAAO,EAAE,aAAa,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,UAAU,GAChB,sBAAsB,CAexB;AA28BD,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,QAAQ,GAAG,cAAc,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAwBD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,UAAU,EAAE,CAuB/F;AAqRD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAmBjF"}
|
|
@@ -16,11 +16,11 @@ export class InMemoryAdminTokenStore extends InMemoryTokenStore {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
import {
|
|
19
|
+
import { loadOfficeVisibilityOverride, loadGlobalSettings, loadScopeMcpServers, resolveConversationSettings, } from "../../../config.js";
|
|
20
20
|
import { findMcpPreset, listMcpPresets, materializeMcpPreset } from "../../../harness/mcp.js";
|
|
21
21
|
import { loadMcpTools } from "../../../harness/mcp.js";
|
|
22
22
|
import { isValidMcpServerName, parseStandardMcpServers, redactMcpUrl, } from "../../../harness/mcp.js";
|
|
23
|
-
import { applyConversationSettings,
|
|
23
|
+
import { applyConversationSettings, applyOfficeVisibility, applyGlobalSettings, } from "../../../settings-mutation.js";
|
|
24
24
|
import { escapeHtml, jsonResponse as jsonRes, readJsonBody, renderPortalShell, } from "../portal-shell.js";
|
|
25
25
|
import { resolveExistingSessionFile } from "../session-view/portal.js";
|
|
26
26
|
import { PRODUCT_NAME } from "../../../platform-messages.js";
|
|
@@ -115,8 +115,8 @@ async function routePostApiRequest(req, res, url, services) {
|
|
|
115
115
|
switch (url.pathname) {
|
|
116
116
|
case "/admin/api/conversations/model":
|
|
117
117
|
return serveConversationModelUpdate(res, body, services, token);
|
|
118
|
-
case "/admin/api/conversations/
|
|
119
|
-
return
|
|
118
|
+
case "/admin/api/conversations/visibility":
|
|
119
|
+
return serveConversationVisibilityUpdate(res, body, services, token);
|
|
120
120
|
case "/admin/api/conversations/slack":
|
|
121
121
|
return serveConversationSlackUpdate(res, body, services, token);
|
|
122
122
|
case "/admin/api/conversations/session-link":
|
|
@@ -129,8 +129,6 @@ async function routePostApiRequest(req, res, url, services) {
|
|
|
129
129
|
return serveMcpServerMutation(res, body, services, token);
|
|
130
130
|
case "/admin/api/settings/model":
|
|
131
131
|
return serveGlobalModelUpdate(res, body, services);
|
|
132
|
-
case "/admin/api/settings/workspace":
|
|
133
|
-
return serveGlobalWorkspaceUpdate(res, body, services);
|
|
134
132
|
case "/admin/api/settings/sandbox":
|
|
135
133
|
return serveGlobalSandboxUpdate(res, body, services);
|
|
136
134
|
case "/admin/api/settings/slack":
|
|
@@ -443,7 +441,6 @@ function serveConversationState(res, url, services, token) {
|
|
|
443
441
|
const globalConfig = loadGlobalSettings();
|
|
444
442
|
const conversationConfig = resolveConversationSettings(office);
|
|
445
443
|
const conversationWorkspace = resolveWorkspaceProjection(office);
|
|
446
|
-
const globalWorkspaceSettings = globalConfig.sandbox?.workspace;
|
|
447
444
|
jsonRes(res, 200, {
|
|
448
445
|
conversationId,
|
|
449
446
|
provider: conversationConfig.provider,
|
|
@@ -452,13 +449,10 @@ function serveConversationState(res, url, services, token) {
|
|
|
452
449
|
globalProvider: globalConfig.provider,
|
|
453
450
|
globalModel: globalConfig.model,
|
|
454
451
|
globalThinkingLevel: globalConfig.thinkingLevel,
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
globalWorkspaceDoorPolicy: globalWorkspaceSettings?.doorPolicy ?? "isolated",
|
|
460
|
-
globalWorkspaceLayout: globalWorkspaceSettings?.layout ?? "conversation",
|
|
461
|
-
globalWorkspaceVisibility: globalWorkspaceSettings?.visibility ?? "public",
|
|
452
|
+
officeVisibility: conversationWorkspace.visibility,
|
|
453
|
+
officeVisibilitySource: conversationWorkspace.source,
|
|
454
|
+
officeVisibilityOverride: loadOfficeVisibilityOverride(office),
|
|
455
|
+
officeLegacyFull: conversationWorkspace.legacyFull,
|
|
462
456
|
slack: {
|
|
463
457
|
replyMode: conversationConfig.slack?.replyMode ?? globalConfig.slack?.replyMode ?? "top-level",
|
|
464
458
|
globalReplyMode: globalConfig.slack?.replyMode ?? "top-level",
|
|
@@ -476,9 +470,6 @@ function serveGlobalSettings(res) {
|
|
|
476
470
|
sandboxMemory: config.sandbox?.memory ?? null,
|
|
477
471
|
sandboxBoostCpus: config.sandbox?.boost?.cpus ?? null,
|
|
478
472
|
sandboxBoostMemory: config.sandbox?.boost?.memory ?? null,
|
|
479
|
-
workspaceDoorPolicy: config.sandbox?.workspace?.doorPolicy ?? null,
|
|
480
|
-
workspaceLayout: config.sandbox?.workspace?.layout ?? null,
|
|
481
|
-
workspaceVisibility: config.sandbox?.workspace?.visibility ?? null,
|
|
482
473
|
defaultSharedVault: config.sandbox?.defaultSharedVault ?? null,
|
|
483
474
|
slack: {
|
|
484
475
|
replyMode: config.slack?.replyMode ?? "top-level",
|
|
@@ -543,48 +534,9 @@ function serveConversationModelUpdate(res, body, services, token) {
|
|
|
543
534
|
jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
|
|
544
535
|
}
|
|
545
536
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
* MEMORY.md; `trusted-shared-support-private` is the same layout with the
|
|
550
|
-
* shared MEMORY.md mounted read-only (modeled on Claude Tag's private-
|
|
551
|
-
* channel memory: read the shared pool, never write into it).
|
|
552
|
-
*/
|
|
553
|
-
function parseDoorPolicyChoice(value) {
|
|
554
|
-
switch (value) {
|
|
555
|
-
case "default":
|
|
556
|
-
return { choice: null };
|
|
557
|
-
case "isolated":
|
|
558
|
-
return { choice: { doorPolicy: "isolated" } };
|
|
559
|
-
case "trusted-shared-support":
|
|
560
|
-
return { choice: { doorPolicy: "trusted", layout: "shared-support", visibility: "public" } };
|
|
561
|
-
case "trusted-shared-support-private":
|
|
562
|
-
return {
|
|
563
|
-
choice: { doorPolicy: "trusted", layout: "shared-support", visibility: "private" },
|
|
564
|
-
};
|
|
565
|
-
case "trusted-full":
|
|
566
|
-
return { choice: { doorPolicy: "trusted", layout: "full" } };
|
|
567
|
-
default:
|
|
568
|
-
return undefined;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
function doorPolicyChoiceKey(choice) {
|
|
572
|
-
if (!choice)
|
|
573
|
-
return "default";
|
|
574
|
-
if (choice.doorPolicy === "isolated")
|
|
575
|
-
return "isolated";
|
|
576
|
-
if (choice.layout === "full")
|
|
577
|
-
return "trusted-full";
|
|
578
|
-
return choice.visibility === "private"
|
|
579
|
-
? "trusted-shared-support-private"
|
|
580
|
-
: "trusted-shared-support";
|
|
581
|
-
}
|
|
582
|
-
function serveConversationSandboxUpdate(res, body, services, token) {
|
|
583
|
-
const parsed = parseDoorPolicyChoice(body.doorPolicy);
|
|
584
|
-
if (!parsed) {
|
|
585
|
-
jsonRes(res, 400, {
|
|
586
|
-
error: "doorPolicy must be 'default', 'isolated', 'trusted-shared-support', 'trusted-shared-support-private', or 'trusted-full'",
|
|
587
|
-
});
|
|
537
|
+
function serveConversationVisibilityUpdate(res, body, services, token) {
|
|
538
|
+
if (body.visibility !== "private" && body.visibility !== "default") {
|
|
539
|
+
jsonRes(res, 400, { error: "visibility must be 'private' or 'default'" });
|
|
588
540
|
return;
|
|
589
541
|
}
|
|
590
542
|
const target = requireConversationWorkspace(res, body, services, token);
|
|
@@ -592,7 +544,7 @@ function serveConversationSandboxUpdate(res, body, services, token) {
|
|
|
592
544
|
return;
|
|
593
545
|
const { scope, workspace } = target;
|
|
594
546
|
try {
|
|
595
|
-
const result =
|
|
547
|
+
const result = applyOfficeVisibility(services.runtime, workspace.office(scope.address), body.visibility === "private" ? "private" : null);
|
|
596
548
|
if (!result.ok) {
|
|
597
549
|
jsonRes(res, 409, { error: "Conversation is busy; retry when the current run finishes" });
|
|
598
550
|
return;
|
|
@@ -603,19 +555,6 @@ function serveConversationSandboxUpdate(res, body, services, token) {
|
|
|
603
555
|
jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
|
|
604
556
|
}
|
|
605
557
|
}
|
|
606
|
-
function serveGlobalWorkspaceUpdate(res, body, services) {
|
|
607
|
-
const parsed = parseDoorPolicyChoice(body.doorPolicy);
|
|
608
|
-
if (!parsed) {
|
|
609
|
-
jsonRes(res, 400, {
|
|
610
|
-
error: "doorPolicy must be 'default', 'isolated', 'trusted-shared-support', 'trusted-shared-support-private', or 'trusted-full'",
|
|
611
|
-
});
|
|
612
|
-
return;
|
|
613
|
-
}
|
|
614
|
-
respondWithSettingsUpdate(res, () => {
|
|
615
|
-
const result = applyGlobalWorkspacePolicy(services.runtime, parsed.choice);
|
|
616
|
-
return { ok: true, staleConversations: result.staleConversations.length };
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
558
|
function serveConversationSlackUpdate(res, body, services, token) {
|
|
620
559
|
const replyMode = body.replyMode;
|
|
621
560
|
if (replyMode !== "top-level" && replyMode !== "thread") {
|
|
@@ -1848,23 +1787,12 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
1848
1787
|
function renderReplyOptions(slack) {
|
|
1849
1788
|
return renderOptions(['top-level','thread'].map((m) => [m, m]), (slack && slack.replyMode) || 'top-level');
|
|
1850
1789
|
}
|
|
1851
|
-
function renderDoorOptions(value, channel) {
|
|
1852
|
-
return renderOptions([
|
|
1853
|
-
['default', 'Automatic — follows ' + channel + ' platform channel (public shares, private reads only, DMs isolated)'],
|
|
1854
|
-
['isolated', 'isolated — own office only'],
|
|
1855
|
-
['trusted-shared-support', 'trusted / shared-support (public) — office + shared memory, skills, events — read-write'],
|
|
1856
|
-
['trusted-shared-support-private', 'trusted / shared-support (private) — same, but shared MEMORY.md is read-only'],
|
|
1857
|
-
['trusted-full', 'trusted / full — entire workspace'],
|
|
1858
|
-
], value);
|
|
1859
|
-
}
|
|
1860
|
-
|
|
1861
1790
|
function renderSettings(data) {
|
|
1862
1791
|
const thinkingOpts = renderThinkingOptions(data.thinkingLevel);
|
|
1863
1792
|
const replyModeOpts = renderReplyOptions(data.slack);
|
|
1864
1793
|
const globalReplyMode = (data.slack && data.slack.globalReplyMode) || 'top-level';
|
|
1865
1794
|
const globalModel = [data.globalProvider, data.globalModel].filter(Boolean).join('/');
|
|
1866
1795
|
const globalModelLabel = globalModel + (data.globalThinkingLevel ? ':' + data.globalThinkingLevel : '');
|
|
1867
|
-
const doorPolicyOpts = renderDoorOptions(data.workspaceOverride || 'default', 'the');
|
|
1868
1796
|
return [
|
|
1869
1797
|
'<div class="config-grid">',
|
|
1870
1798
|
renderConfigCard('Model', [
|
|
@@ -1873,11 +1801,19 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
1873
1801
|
'<p class="muted-note">Global default: ' + escHtml(globalModelLabel) + '</p>',
|
|
1874
1802
|
].join(''), 'saveModel', 'Save model', 'model-save-result'),
|
|
1875
1803
|
|
|
1876
|
-
renderConfigCard('Office
|
|
1877
|
-
'<div class="config-row"><label>
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1804
|
+
renderConfigCard('Office visibility', [
|
|
1805
|
+
'<div class="config-row"><label>Visibility</label><select id="m-visibility">' +
|
|
1806
|
+
renderOptions([
|
|
1807
|
+
['default', 'Follow the Slack conversation type (default)'],
|
|
1808
|
+
['private', 'Private — treat this public channel as private'],
|
|
1809
|
+
], data.officeVisibilityOverride === 'private' ? 'private' : 'default') + '</select></div>',
|
|
1810
|
+
'<p class="muted-note">Effective: <strong>' + escHtml(data.officeVisibility) + '</strong> · ' + escHtml(
|
|
1811
|
+
data.officeVisibilitySource === 'override' ? 'set here'
|
|
1812
|
+
: data.officeVisibilitySource === 'platform' ? 'from the Slack conversation type'
|
|
1813
|
+
: 'conversation type unknown; private until observed') + '</p>',
|
|
1814
|
+
'<p class="muted-note">Public offices can be read by every other office and may write shared MEMORY.md and skills. Private offices (private channels, DMs) are visible only to themselves and read shared knowledge without writing it. Nothing can be made more visible than Slack allows.</p>',
|
|
1815
|
+
(data.officeLegacyFull ? '<p class="muted-note">This office still declares the retired <code>full</code> door policy; it no longer widens access.</p>' : ''),
|
|
1816
|
+
].join(''), 'saveVisibility', 'Save visibility', 'mount-save-result'),
|
|
1881
1817
|
renderConfigCard('Slack', [
|
|
1882
1818
|
'<div class="config-row"><label>Reply mode</label><select id="m-slack-reply-mode">' + replyModeOpts + '</select></div>',
|
|
1883
1819
|
'<p class="muted-note">Global default: ' + escHtml(globalReplyMode) + '</p>',
|
|
@@ -1906,10 +1842,10 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
1906
1842
|
await saveConversationSetting(btn, result, 'slack', { replyMode }, 'Save Slack');
|
|
1907
1843
|
}
|
|
1908
1844
|
|
|
1909
|
-
async function
|
|
1910
|
-
const
|
|
1845
|
+
async function saveVisibility(btn) {
|
|
1846
|
+
const visibility = document.getElementById('m-visibility').value;
|
|
1911
1847
|
const result = document.getElementById('mount-save-result');
|
|
1912
|
-
await saveConversationSetting(btn, result, '
|
|
1848
|
+
await saveConversationSetting(btn, result, 'visibility', { visibility }, 'Save visibility', loadSettings);
|
|
1913
1849
|
}
|
|
1914
1850
|
|
|
1915
1851
|
function saveConversationSetting(btn, result, setting, values, label, onSaved) {
|
|
@@ -2674,14 +2610,6 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
2674
2610
|
function renderGlobalSettings(data) {
|
|
2675
2611
|
const thinkingOpts = renderThinkingOptions(data.thinkingLevel);
|
|
2676
2612
|
const replyModeOpts = renderReplyOptions(data.slack);
|
|
2677
|
-
const gDoorKey = !data.workspaceDoorPolicy
|
|
2678
|
-
? 'default'
|
|
2679
|
-
: (data.workspaceDoorPolicy === 'isolated'
|
|
2680
|
-
? 'isolated'
|
|
2681
|
-
: (data.workspaceLayout === 'full'
|
|
2682
|
-
? 'trusted-full'
|
|
2683
|
-
: ((data.workspaceVisibility || 'public') === 'private' ? 'trusted-shared-support-private' : 'trusted-shared-support')));
|
|
2684
|
-
const gDoorPolicyOpts = renderDoorOptions(gDoorKey, 'each');
|
|
2685
2613
|
return [
|
|
2686
2614
|
'<div class="config-grid">',
|
|
2687
2615
|
renderConfigCard('Default model', [
|
|
@@ -2694,10 +2622,6 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
2694
2622
|
'<div class="config-row"><label>Boost CPUs</label><input id="g-bcpus" placeholder="2" value="' + escAttr(data.sandboxBoostCpus || '') + '"></div>',
|
|
2695
2623
|
'<div class="config-row"><label>Boost Mem</label><input id="g-bmem" placeholder="4g" value="' + escAttr(data.sandboxBoostMemory || '') + '"></div>',
|
|
2696
2624
|
].join(''), 'saveGlobalSandbox', 'Save sandbox', 'g-sandbox-result'),
|
|
2697
|
-
renderConfigCard('Office door policy', [
|
|
2698
|
-
'<div class="config-row"><label>Default</label><select id="g-door-policy">' + gDoorPolicyOpts + '</select></div>',
|
|
2699
|
-
'<p class="muted-note">Applies to offices without their own policy. Affected offices rebuild their sandbox container with the new mounts on the next message; container contents are preserved.</p>',
|
|
2700
|
-
].join(''), 'saveGlobalWorkspace', 'Save door policy', 'g-workspace-result'),
|
|
2701
2625
|
renderConfigCard('Slack', [
|
|
2702
2626
|
'<div class="config-row"><label>Reply mode</label><select id="g-slack-reply-mode">' + replyModeOpts + '</select></div>',
|
|
2703
2627
|
].join(''), 'saveGlobalSlack', 'Save Slack', 'g-slack-result'),
|
|
@@ -2735,23 +2659,6 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
2735
2659
|
await saveSetting(btn, result, 'settings/sandbox', { cpus, memory, boostCpus, boostMemory }, 'Save sandbox');
|
|
2736
2660
|
}
|
|
2737
2661
|
|
|
2738
|
-
async function saveGlobalWorkspace(btn) {
|
|
2739
|
-
const doorPolicy = document.getElementById('g-door-policy').value;
|
|
2740
|
-
const result = document.getElementById('g-workspace-result');
|
|
2741
|
-
btn.disabled = true; btn.textContent = 'Saving…'; result.style.display = 'none';
|
|
2742
|
-
try {
|
|
2743
|
-
const data = await apiPost('/admin/api/settings/workspace', { doorPolicy });
|
|
2744
|
-
result.style.display = 'block'; result.className = 'inline-result ok';
|
|
2745
|
-
result.textContent = data.staleConversations > 0
|
|
2746
|
-
? 'Saved ✓ (' + data.staleConversations + ' busy conversation(s) refresh after their current run)'
|
|
2747
|
-
: 'Saved ✓';
|
|
2748
|
-
} catch (err) {
|
|
2749
|
-
result.style.display = 'block'; result.className = 'inline-result err'; result.textContent = err.message;
|
|
2750
|
-
} finally {
|
|
2751
|
-
btn.disabled = false; btn.textContent = 'Save door policy';
|
|
2752
|
-
}
|
|
2753
|
-
}
|
|
2754
|
-
|
|
2755
2662
|
async function saveGlobalSlack(btn) {
|
|
2756
2663
|
const replyMode = document.getElementById('g-slack-reply-mode').value;
|
|
2757
2664
|
const result = document.getElementById('g-slack-result');
|