@geminixiang/mikan 1.0.0-beta.62 → 1.0.0-beta.64
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 +26 -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 +26 -121
- package/dist/adapters/web/admin/portal.js.map +1 -1
- package/dist/cli/boot.js +1 -1
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/office.d.ts.map +1 -1
- package/dist/cli/office.js +33 -1
- package/dist/cli/office.js.map +1 -1
- package/dist/config.d.ts +26 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +103 -61
- 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 +67 -99
- package/dist/office/projection.js.map +1 -1
- package/dist/office/types.d.ts +7 -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 +2 -32
- 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;AA08BD,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,9 @@ 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
|
-
workspaceOverride: doorPolicyChoiceKey(loadConversationWorkspaceOverride(office)),
|
|
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),
|
|
462
455
|
slack: {
|
|
463
456
|
replyMode: conversationConfig.slack?.replyMode ?? globalConfig.slack?.replyMode ?? "top-level",
|
|
464
457
|
globalReplyMode: globalConfig.slack?.replyMode ?? "top-level",
|
|
@@ -476,9 +469,6 @@ function serveGlobalSettings(res) {
|
|
|
476
469
|
sandboxMemory: config.sandbox?.memory ?? null,
|
|
477
470
|
sandboxBoostCpus: config.sandbox?.boost?.cpus ?? null,
|
|
478
471
|
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
472
|
defaultSharedVault: config.sandbox?.defaultSharedVault ?? null,
|
|
483
473
|
slack: {
|
|
484
474
|
replyMode: config.slack?.replyMode ?? "top-level",
|
|
@@ -543,48 +533,9 @@ function serveConversationModelUpdate(res, body, services, token) {
|
|
|
543
533
|
jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
|
|
544
534
|
}
|
|
545
535
|
}
|
|
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
|
-
});
|
|
536
|
+
function serveConversationVisibilityUpdate(res, body, services, token) {
|
|
537
|
+
if (body.visibility !== "private" && body.visibility !== "default") {
|
|
538
|
+
jsonRes(res, 400, { error: "visibility must be 'private' or 'default'" });
|
|
588
539
|
return;
|
|
589
540
|
}
|
|
590
541
|
const target = requireConversationWorkspace(res, body, services, token);
|
|
@@ -592,7 +543,7 @@ function serveConversationSandboxUpdate(res, body, services, token) {
|
|
|
592
543
|
return;
|
|
593
544
|
const { scope, workspace } = target;
|
|
594
545
|
try {
|
|
595
|
-
const result =
|
|
546
|
+
const result = applyOfficeVisibility(services.runtime, workspace.office(scope.address), body.visibility === "private" ? "private" : null);
|
|
596
547
|
if (!result.ok) {
|
|
597
548
|
jsonRes(res, 409, { error: "Conversation is busy; retry when the current run finishes" });
|
|
598
549
|
return;
|
|
@@ -603,19 +554,6 @@ function serveConversationSandboxUpdate(res, body, services, token) {
|
|
|
603
554
|
jsonRes(res, 500, { error: err instanceof Error ? err.message : String(err) });
|
|
604
555
|
}
|
|
605
556
|
}
|
|
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
557
|
function serveConversationSlackUpdate(res, body, services, token) {
|
|
620
558
|
const replyMode = body.replyMode;
|
|
621
559
|
if (replyMode !== "top-level" && replyMode !== "thread") {
|
|
@@ -1848,23 +1786,12 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
1848
1786
|
function renderReplyOptions(slack) {
|
|
1849
1787
|
return renderOptions(['top-level','thread'].map((m) => [m, m]), (slack && slack.replyMode) || 'top-level');
|
|
1850
1788
|
}
|
|
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
1789
|
function renderSettings(data) {
|
|
1862
1790
|
const thinkingOpts = renderThinkingOptions(data.thinkingLevel);
|
|
1863
1791
|
const replyModeOpts = renderReplyOptions(data.slack);
|
|
1864
1792
|
const globalReplyMode = (data.slack && data.slack.globalReplyMode) || 'top-level';
|
|
1865
1793
|
const globalModel = [data.globalProvider, data.globalModel].filter(Boolean).join('/');
|
|
1866
1794
|
const globalModelLabel = globalModel + (data.globalThinkingLevel ? ':' + data.globalThinkingLevel : '');
|
|
1867
|
-
const doorPolicyOpts = renderDoorOptions(data.workspaceOverride || 'default', 'the');
|
|
1868
1795
|
return [
|
|
1869
1796
|
'<div class="config-grid">',
|
|
1870
1797
|
renderConfigCard('Model', [
|
|
@@ -1873,11 +1800,18 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
1873
1800
|
'<p class="muted-note">Global default: ' + escHtml(globalModelLabel) + '</p>',
|
|
1874
1801
|
].join(''), 'saveModel', 'Save model', 'model-save-result'),
|
|
1875
1802
|
|
|
1876
|
-
renderConfigCard('Office
|
|
1877
|
-
'<div class="config-row"><label>
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1803
|
+
renderConfigCard('Office visibility', [
|
|
1804
|
+
'<div class="config-row"><label>Visibility</label><select id="m-visibility">' +
|
|
1805
|
+
renderOptions([
|
|
1806
|
+
['default', 'Follow the Slack conversation type (default)'],
|
|
1807
|
+
['private', 'Private — treat this public channel as private'],
|
|
1808
|
+
], data.officeVisibilityOverride === 'private' ? 'private' : 'default') + '</select></div>',
|
|
1809
|
+
'<p class="muted-note">Effective: <strong>' + escHtml(data.officeVisibility) + '</strong> · ' + escHtml(
|
|
1810
|
+
data.officeVisibilitySource === 'override' ? 'set here'
|
|
1811
|
+
: data.officeVisibilitySource === 'platform' ? 'from the Slack conversation type'
|
|
1812
|
+
: 'conversation type unknown; private until observed') + '</p>',
|
|
1813
|
+
'<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>',
|
|
1814
|
+
].join(''), 'saveVisibility', 'Save visibility', 'mount-save-result'),
|
|
1881
1815
|
renderConfigCard('Slack', [
|
|
1882
1816
|
'<div class="config-row"><label>Reply mode</label><select id="m-slack-reply-mode">' + replyModeOpts + '</select></div>',
|
|
1883
1817
|
'<p class="muted-note">Global default: ' + escHtml(globalReplyMode) + '</p>',
|
|
@@ -1906,10 +1840,10 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
1906
1840
|
await saveConversationSetting(btn, result, 'slack', { replyMode }, 'Save Slack');
|
|
1907
1841
|
}
|
|
1908
1842
|
|
|
1909
|
-
async function
|
|
1910
|
-
const
|
|
1843
|
+
async function saveVisibility(btn) {
|
|
1844
|
+
const visibility = document.getElementById('m-visibility').value;
|
|
1911
1845
|
const result = document.getElementById('mount-save-result');
|
|
1912
|
-
await saveConversationSetting(btn, result, '
|
|
1846
|
+
await saveConversationSetting(btn, result, 'visibility', { visibility }, 'Save visibility', loadSettings);
|
|
1913
1847
|
}
|
|
1914
1848
|
|
|
1915
1849
|
function saveConversationSetting(btn, result, setting, values, label, onSaved) {
|
|
@@ -2674,14 +2608,6 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
2674
2608
|
function renderGlobalSettings(data) {
|
|
2675
2609
|
const thinkingOpts = renderThinkingOptions(data.thinkingLevel);
|
|
2676
2610
|
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
2611
|
return [
|
|
2686
2612
|
'<div class="config-grid">',
|
|
2687
2613
|
renderConfigCard('Default model', [
|
|
@@ -2694,10 +2620,6 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
2694
2620
|
'<div class="config-row"><label>Boost CPUs</label><input id="g-bcpus" placeholder="2" value="' + escAttr(data.sandboxBoostCpus || '') + '"></div>',
|
|
2695
2621
|
'<div class="config-row"><label>Boost Mem</label><input id="g-bmem" placeholder="4g" value="' + escAttr(data.sandboxBoostMemory || '') + '"></div>',
|
|
2696
2622
|
].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
2623
|
renderConfigCard('Slack', [
|
|
2702
2624
|
'<div class="config-row"><label>Reply mode</label><select id="g-slack-reply-mode">' + replyModeOpts + '</select></div>',
|
|
2703
2625
|
].join(''), 'saveGlobalSlack', 'Save Slack', 'g-slack-result'),
|
|
@@ -2735,23 +2657,6 @@ const adminViewScript = ` let activeConversationKey = defaultConversationKey;
|
|
|
2735
2657
|
await saveSetting(btn, result, 'settings/sandbox', { cpus, memory, boostCpus, boostMemory }, 'Save sandbox');
|
|
2736
2658
|
}
|
|
2737
2659
|
|
|
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
2660
|
async function saveGlobalSlack(btn) {
|
|
2756
2661
|
const replyMode = document.getElementById('g-slack-reply-mode').value;
|
|
2757
2662
|
const result = document.getElementById('g-slack-result');
|