@abot-ai/runtime 1.8.0 → 1.8.1
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/README.md +216 -222
- package/dist/src/capabilities/tool-definition-validator/definition-parser.js +8 -0
- package/dist/src/capabilities/tool-types.d.ts +4 -0
- package/dist/src/model-gateway/protocol/message-contract.d.ts +1 -0
- package/dist/src/model-gateway/protocol/message-contract.js +1 -1
- package/dist/src/model-gateway/server/chat-handler.js +5 -7
- package/dist/src/model-gateway/server/chat-stream-response.d.ts +7 -0
- package/dist/src/model-gateway/server/chat-stream-response.js +25 -0
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.d.ts +2 -2
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.js +2 -2
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/prepared-execution.js +17 -11
- package/dist/src/runtime/capabilities/tool-availability.js +6 -0
- package/dist/src/runtime/context/capability-brief.d.ts +2 -2
- package/dist/src/runtime/context/capability-brief.js +3 -3
- package/dist/src/runtime/context/capability-descriptions.d.ts +3 -2
- package/dist/src/runtime/context/capability-descriptions.js +57 -20
- package/dist/src/runtime/long-term-memory/conversation-authoring/context.d.ts +6 -1
- package/dist/src/runtime/long-term-memory/conversation-authoring/context.js +51 -25
- package/dist/src/runtime/long-term-memory/initial-context.d.ts +17 -0
- package/dist/src/runtime/long-term-memory/initial-context.js +57 -0
- package/dist/src/runtime/long-term-memory/projection.js +1 -1
- package/dist/src/runtime/orchestration/role-calls/candidate-validation.js +2 -1
- package/dist/src/runtime/orchestration/role-calls/checkpoint-state.d.ts +1 -1
- package/dist/src/runtime/orchestration/role-calls/checkpoint-state.js +5 -2
- package/dist/src/runtime/orchestration/role-calls/contracts.d.ts +2 -1
- package/dist/src/runtime/orchestration/role-calls/ledger.d.ts +2 -1
- package/dist/src/runtime/orchestration/role-calls/ledger.js +2 -2
- package/dist/src/runtime/orchestration/role-calls/memory-recall-contract.d.ts +7 -0
- package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.d.ts +2 -0
- package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.js +88 -0
- package/dist/src/runtime/orchestration/role-calls/reducer.d.ts +1 -1
- package/dist/src/runtime/orchestration/role-calls/reducer.js +2 -1
- package/dist/src/runtime/orchestration/worker-capabilities/contracts.d.ts +3 -1
- package/dist/src/runtime/orchestration/worker-capabilities/contracts.js +1 -1
- package/dist/src/runtime/orchestration/worker-capabilities/execution/approval-group.js +5 -1
- package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.d.ts +5 -0
- package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.js +31 -0
- package/dist/src/runtime/plugins/manifest-projection.js +3 -0
- package/dist/src/runtime/request/capability-execution-freshness.js +6 -1
- package/dist/src/runtime/request/execution-agent-root-execution.js +11 -1
- package/dist/src/runtime/request/root-contract.d.ts +2 -0
- package/dist/src/runtime/request/root-execution-kernel.js +1 -0
- package/dist/src/runtime/request/runner.js +9 -3
- package/dist/src/runtime/request/supervisor-root-execution.js +6 -0
- package/dist/src/runtime/steps/execution-agent/contracts.d.ts +10 -0
- package/dist/src/runtime/steps/execution-agent/decision-parsing.js +13 -1
- package/dist/src/runtime/steps/execution-agent/direct-response-configuration.d.ts +3 -0
- package/dist/src/runtime/steps/execution-agent/direct-response-configuration.js +64 -0
- package/dist/src/runtime/steps/execution-agent/direct-response-contract.d.ts +7 -0
- package/dist/src/runtime/steps/execution-agent/direct-response-contract.js +56 -0
- package/dist/src/runtime/steps/execution-agent/direct-response-policy.d.ts +9 -0
- package/dist/src/runtime/steps/execution-agent/direct-response-policy.js +30 -0
- package/dist/src/runtime/steps/execution-agent/direct-response-prompt.d.ts +7 -0
- package/dist/src/runtime/steps/execution-agent/direct-response-prompt.js +43 -0
- package/dist/src/runtime/steps/execution-agent/format.js +2 -0
- package/dist/src/runtime/steps/execution-agent/input.d.ts +2 -0
- package/dist/src/runtime/steps/execution-agent/input.js +22 -1
- package/dist/src/runtime/steps/execution-agent/plugin-catalog.d.ts +4 -0
- package/dist/src/runtime/steps/execution-agent/plugin-catalog.js +8 -0
- package/dist/src/runtime/steps/execution-agent/prompt.d.ts +1 -0
- package/dist/src/runtime/steps/execution-agent/prompt.js +3 -4
- package/dist/src/runtime/steps/execution-agent/response-run.js +5 -11
- package/dist/src/runtime/steps/execution-agent/run.js +4 -1
- package/dist/src/runtime/steps/execution-agent/state-context.d.ts +2 -3
- package/dist/src/runtime/steps/execution-agent/state-context.js +2 -39
- package/dist/src/runtime/steps/planner-decision/capability-brief.d.ts +2 -0
- package/dist/src/runtime/steps/planner-decision/prompt.js +26 -49
- package/dist/src/runtime/steps/supervisor-decision/input.d.ts +1 -0
- package/dist/src/runtime/steps/supervisor-decision/input.js +5 -0
- package/dist/src/runtime/steps/supervisor-decision/prompt.d.ts +1 -0
- package/dist/src/runtime/steps/supervisor-decision/prompt.js +6 -2
- package/dist/src/runtime/steps/supervisor-decision/run.d.ts +1 -0
- package/dist/src/runtime/steps/supervisor-decision/run.js +4 -0
- package/dist/src/runtime/steps/supervisor-response/run.d.ts +2 -0
- package/dist/src/runtime/steps/supervisor-response/run.js +3 -6
- package/dist/src/web-ui/app/ARCHITECTURE.md +1 -1
- package/dist/src/web-ui/app/app.js +1 -0
- package/dist/src/web-ui/app/components/automations/timeline.js +3 -2
- package/dist/src/web-ui/app/components/dashboard/compact-layout.js +137 -0
- package/dist/src/web-ui/app/components/dashboard/icons.js +5 -0
- package/dist/src/web-ui/app/components/dashboard/widget-card.js +85 -0
- package/dist/src/web-ui/app/components/dashboard/widget-dialog.js +83 -0
- package/dist/src/web-ui/app/components/dashboard/widget-summaries.js +155 -0
- package/dist/src/web-ui/app/components/dashboard/workspace.js +28 -4
- package/dist/src/web-ui/app/components/operations-summary.js +2 -1
- package/dist/src/web-ui/app/components/passive-learning/home-widget-preview.js +32 -0
- package/dist/src/web-ui/app/components/passive-learning/home.js +4 -1
- package/dist/src/web-ui/app/components/schedules/details.js +3 -2
- package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -1
- package/dist/src/web-ui/app/components/spark-chat/settings.js +1 -1
- package/dist/src/web-ui/app/components/system-host/home-widget-permission-preview.js +75 -0
- package/dist/src/web-ui/app/components/system-host/home-widget-summary.js +93 -0
- package/dist/src/web-ui/app/components/system-host/macos-permission-rendering.js +2 -2
- package/dist/src/web-ui/app/components/system-host/native-windows-access.js +1 -1
- package/dist/src/web-ui/app/components/system-host/rendering.js +3 -3
- package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +2 -2
- package/dist/src/web-ui/app/computer-access-feature.js +13 -1
- package/dist/src/web-ui/app/configuration-feature.js +2 -0
- package/dist/src/web-ui/app/controllers/operations-controller.js +2 -1
- package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +1 -1
- package/dist/src/web-ui/app/dashboard-feature.js +9 -0
- package/dist/src/web-ui/app/lib/reasoning-controls.js +6 -1
- package/dist/src/web-ui/app/passive-learning-feature.js +2 -2
- package/dist/src/web-ui/app/styles/95-home-widgets.css +109 -0
- package/dist/src/web-ui/app/styles.css +1 -0
- package/docs/plugins.md +37 -32
- package/package.json +1 -1
- package/plugins/capability-brief/plugin.json +1 -1
- package/plugins/code-outline/plugin.json +1 -1
- package/plugins/document-reader/plugin.json +1 -1
- package/plugins/exec/plugin.json +1 -1
- package/plugins/filesystem/plugin.json +1 -1
- package/plugins/json-inspector/plugin.json +1 -1
- package/plugins/local-search/plugin.json +1 -1
- package/plugins/memory/plugin.json +1 -1
- package/plugins/project-orientation/plugin.json +1 -1
- package/plugins/system/plugin.json +1 -1
- package/plugins/system-probe/plugin.json +1 -1
- package/plugins/web/plugin.json +1 -1
|
@@ -3,6 +3,8 @@ import { getDashboardJobTemplates } from "../../lib/dashboard-job-templates.js";
|
|
|
3
3
|
import { renderDashboardActivity } from "./activity.js";
|
|
4
4
|
import { renderDashboardConversations } from "./recent-conversations.js";
|
|
5
5
|
import { renderDashboardAutomations } from "./automations.js";
|
|
6
|
+
import { createCompactHomeLayout } from "./compact-layout.js";
|
|
7
|
+
import { dashboardWidgetSummaries } from "./widget-summaries.js";
|
|
6
8
|
import {
|
|
7
9
|
hasPendingDashboardApprovals,
|
|
8
10
|
renderDashboardApprovals,
|
|
@@ -37,7 +39,26 @@ export function createDashboardWorkspace({ root, actions, passiveLearning }) {
|
|
|
37
39
|
const setupHost = root.querySelector("[data-dashboard-setup]");
|
|
38
40
|
const learningPanel = root.querySelector("[data-dashboard-learning]");
|
|
39
41
|
const automationPanel = root.querySelector("[data-dashboard-automations]");
|
|
40
|
-
|
|
42
|
+
let currentSnapshot = {};
|
|
43
|
+
function approvalHome() {
|
|
44
|
+
if (hasPendingDashboardApprovals(currentSnapshot)) return approvalDock;
|
|
45
|
+
return content;
|
|
46
|
+
}
|
|
47
|
+
const returnParents = { approvals: approvalHome };
|
|
48
|
+
const compactWidgets = createCompactHomeLayout({ root, content });
|
|
49
|
+
for (const [id, label, icon, element] of [
|
|
50
|
+
["learning", "ABot Spark", "learning", learningPanel],
|
|
51
|
+
["conversations", "Recent conversations", "conversations", conversations],
|
|
52
|
+
["activity", "Recent activity", "active", activity],
|
|
53
|
+
["automations", "Automations", "job", automationPanel],
|
|
54
|
+
["approvals", "Pending approvals", "success", approvals],
|
|
55
|
+
]) compactWidgets.register({
|
|
56
|
+
id, label, icon, element,
|
|
57
|
+
getReturnParent: returnParents[id],
|
|
58
|
+
isAvailable: () => id !== "learning" || Boolean(passiveLearning),
|
|
59
|
+
getSummary: () => dashboardWidgetSummaries(currentSnapshot, passiveLearning?.snapshot?.())[id],
|
|
60
|
+
});
|
|
61
|
+
passiveLearning?.mountHome(root.querySelector("[data-dashboard-learning-content]"), compactWidgets.refresh);
|
|
41
62
|
const composerNote = root.querySelector(".home-composer-note");
|
|
42
63
|
const handlers = {
|
|
43
64
|
template: (button) => actions.createJob(button.dataset.templateId),
|
|
@@ -57,12 +78,14 @@ export function createDashboardWorkspace({ root, actions, passiveLearning }) {
|
|
|
57
78
|
});
|
|
58
79
|
|
|
59
80
|
function render(snapshot) {
|
|
81
|
+
currentSnapshot = snapshot;
|
|
60
82
|
const setupRequired = snapshot.composerAvailable === false;
|
|
83
|
+
compactWidgets.setEnabled(!setupRequired);
|
|
61
84
|
const pendingApprovals = hasPendingDashboardApprovals(snapshot);
|
|
62
85
|
approvalDock.hidden = setupRequired || !pendingApprovals;
|
|
63
86
|
// Keep pending actions beside the composer; refresh errors stay in content.
|
|
64
|
-
const approvalParent =
|
|
65
|
-
if (approvals.parentElement !== approvalParent)
|
|
87
|
+
const approvalParent = approvalHome();
|
|
88
|
+
if (!compactWidgets.isExpanded(approvals) && approvals.parentElement !== approvalParent)
|
|
66
89
|
approvalParent.appendChild(approvals);
|
|
67
90
|
root.classList.toggle("home-setup-active", setupRequired);
|
|
68
91
|
learningPanel.hidden = setupRequired || !passiveLearning;
|
|
@@ -118,7 +141,8 @@ export function createDashboardWorkspace({ root, actions, passiveLearning }) {
|
|
|
118
141
|
"aria-busy",
|
|
119
142
|
String(Boolean(snapshot.loadingSessions)),
|
|
120
143
|
);
|
|
144
|
+
compactWidgets.refresh();
|
|
121
145
|
}
|
|
122
146
|
|
|
123
|
-
return { render, composerHost, setupHost };
|
|
147
|
+
return { render, composerHost, setupHost, compactWidgets };
|
|
124
148
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { displayReasoningMode } from "../lib/reasoning-controls.js";
|
|
1
2
|
import { formatTime, textOf } from "../lib/text-format.js";
|
|
2
3
|
import { getNumber } from "../lib/event-presentation.js";
|
|
3
4
|
|
|
@@ -91,7 +92,7 @@ function healthSummary(read) {
|
|
|
91
92
|
label: "System health · all environments",
|
|
92
93
|
items: [
|
|
93
94
|
{ label: "Health · all environments", value: unavailable || healthValue(payload.ok), status: true },
|
|
94
|
-
{ label: "Runtime mode", value: unavailable || textOf(payload.agentMode, "-") || "-" },
|
|
95
|
+
{ label: "Runtime mode", value: unavailable || textOf(displayReasoningMode(payload.agentMode), "-") || "-" },
|
|
95
96
|
{ label: "Active streams", value: unavailable || activeStreamCount(payload) },
|
|
96
97
|
{ label: "Latest event", value: unavailable || textOf(latest?.lastEventName || latest?.lastEventType, "-") || "-" },
|
|
97
98
|
],
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { coWorkerActivityStates, coWorkerActivityTones } from "./agent-state.js";
|
|
2
|
+
|
|
3
|
+
const indicators = {
|
|
4
|
+
off: { icon: "paused", tone: "neutral" },
|
|
5
|
+
waiting: { icon: "active", tone: "neutral" },
|
|
6
|
+
ready: { icon: "success", tone: "success" },
|
|
7
|
+
active: { icon: "active", tone: "active" },
|
|
8
|
+
attention: { icon: "failed", tone: "attention" },
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/** Read-only projection of the same activity states used by the expanded owner. */
|
|
12
|
+
export function learningWidgetPreview(status) {
|
|
13
|
+
if (!status?.preferences) return null;
|
|
14
|
+
const states = coWorkerActivityStates(status);
|
|
15
|
+
const tones = coWorkerActivityTones(status);
|
|
16
|
+
return {
|
|
17
|
+
kind: "metrics",
|
|
18
|
+
items: [
|
|
19
|
+
["collection", "Collection"],
|
|
20
|
+
["processing", "Learning"],
|
|
21
|
+
["proactive", "Proactive"],
|
|
22
|
+
].map(([key, label]) => {
|
|
23
|
+
const indicator = { ...(indicators[tones[key]] || indicators.off) };
|
|
24
|
+
indicator.label = [label, ...states[key]].filter(Boolean).join(": ");
|
|
25
|
+
if (key === "collection" && tones[key] === "active") indicator.icon = "collecting";
|
|
26
|
+
if (key === "processing" && ["ready", "waiting"].includes(tones[key])
|
|
27
|
+
&& Number.isFinite(status.pendingObservations) && status.pendingObservations > 0)
|
|
28
|
+
indicator.value = status.pendingObservations;
|
|
29
|
+
return { label, indicator };
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -37,8 +37,10 @@ export function createPassiveLearningHome({
|
|
|
37
37
|
let root = null;
|
|
38
38
|
let renderedSnapshot = {};
|
|
39
39
|
let motion;
|
|
40
|
+
let onRendered = () => {};
|
|
40
41
|
|
|
41
|
-
function mount(nextRoot) {
|
|
42
|
+
function mount(nextRoot, notify = () => {}) {
|
|
43
|
+
onRendered = notify;
|
|
42
44
|
if (root === nextRoot) return;
|
|
43
45
|
motion?.dispose();
|
|
44
46
|
root?.removeEventListener("click", handleClick);
|
|
@@ -88,6 +90,7 @@ export function createPassiveLearningHome({
|
|
|
88
90
|
const error = root.querySelector("[data-learning-status]");
|
|
89
91
|
error.textContent = snapshot.statusError || "";
|
|
90
92
|
error.hidden = !snapshot.statusError;
|
|
93
|
+
onRendered();
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
return Object.freeze({ mount, render });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { displayReasoningMode } from "../../lib/reasoning-controls.js";
|
|
1
2
|
import { toolPermissionModeMeta } from "../../lib/tool-permission-mode.js";
|
|
2
3
|
import { updateLiveRegion } from "../../lib/live-region.js";
|
|
3
4
|
import { escapeHtml } from "../../lib/text-format.js";
|
|
@@ -33,7 +34,7 @@ function runMarkup(run) {
|
|
|
33
34
|
return `<article class="schedule-run" data-run-id="${escapeHtml(run.id)}">
|
|
34
35
|
<div class="schedule-run-heading"><strong>${scheduleTimeLabel(run.scheduledAt, timeZone)}</strong><span class="schedule-badge" data-state="${escapeHtml(run.status)}">${escapeHtml(run.status)}</span></div>
|
|
35
36
|
<div class="schedule-run-meta">${run.trigger === "manual" ? "Manual run" : "Scheduled run"}${run.startedAt ? ` · Started ${scheduleTimeLabel(run.startedAt, timeZone)}` : ""}${run.finishedAt ? ` · Finished ${scheduleTimeLabel(run.finishedAt, timeZone)}` : ""}</div>
|
|
36
|
-
<dl class="schedule-run-settings">${fact("Model", run.modelProfileId)}${fact("Mode", run.agentMode)}${fact("Tool access", toolPermissionModeMeta(run.toolPermissionMode).label)}${fact("Time zone", run.timeZone)}${fact("Job revision", String(run.jobRevision ?? "—"))}</dl>
|
|
37
|
+
<dl class="schedule-run-settings">${fact("Model", run.modelProfileId)}${fact("Mode", displayReasoningMode(run.agentMode))}${fact("Tool access", toolPermissionModeMeta(run.toolPermissionMode).label)}${fact("Time zone", run.timeZone)}${fact("Job revision", String(run.jobRevision ?? "—"))}</dl>
|
|
37
38
|
${run.error ? `<p class="schedule-error" dir="auto">${escapeHtml(run.error)}</p>` : ""}
|
|
38
39
|
${run.resultText ? `<details class="schedule-result" data-disclosure-id="result:${escapeHtml(run.id)}"><summary>View result</summary><pre dir="auto">${escapeHtml(run.resultText)}</pre></details>` : ""}
|
|
39
40
|
<details class="schedule-prompt-disclosure" data-disclosure-id="run:${escapeHtml(run.id)}"><summary>View invocation prompt</summary><pre dir="auto">${escapeHtml(run.prompt)}</pre></details>
|
|
@@ -67,7 +68,7 @@ export function renderScheduleDetails({ root, snapshot, actions }) {
|
|
|
67
68
|
const conversationLabel = scheduleConversationLabel(job.sessionId, snapshot.sessions);
|
|
68
69
|
const markup = `<div class="schedule-detail-heading"><span class="schedule-eyebrow">Scheduled task</span><h3 dir="auto">${escapeHtml(job.title)}</h3><span class="schedule-badge" data-state="${job.state}">${job.state}</span></div>
|
|
69
70
|
<div class="schedule-action-row">${actionsMarkup(job, snapshot.mutation)}</div>
|
|
70
|
-
<dl class="schedule-facts">${fact("Schedule", scheduleDescription(job))}${fact("Next run", scheduleTimeLabel(job.nextRunAt, job.timeZone))}${fact("Time zone", job.timeZone)}${fact("Model", job.modelProfileId)}${fact("Mode", job.agentMode)}${fact("Tool access", toolPermissionModeMeta(job.toolPermissionMode).label)}${fact("Created", scheduleTimeLabel(job.createdAt, job.timeZone))}${fact("Updated", scheduleTimeLabel(job.updatedAt, job.timeZone))}</dl>
|
|
71
|
+
<dl class="schedule-facts">${fact("Schedule", scheduleDescription(job))}${fact("Next run", scheduleTimeLabel(job.nextRunAt, job.timeZone))}${fact("Time zone", job.timeZone)}${fact("Model", job.modelProfileId)}${fact("Mode", displayReasoningMode(job.agentMode))}${fact("Tool access", toolPermissionModeMeta(job.toolPermissionMode).label)}${fact("Created", scheduleTimeLabel(job.createdAt, job.timeZone))}${fact("Updated", scheduleTimeLabel(job.updatedAt, job.timeZone))}</dl>
|
|
71
72
|
<button type="button" class="schedule-conversation-link" data-open-conversation>↗ <span dir="auto">${escapeHtml(conversationLabel)}</span></button>
|
|
72
73
|
<details class="schedule-prompt-disclosure" data-disclosure-id="job:${escapeHtml(job.id)}"><summary>View task prompt</summary><pre dir="auto">${escapeHtml(job.prompt)}</pre></details>
|
|
73
74
|
<small class="schedule-id">Job ${escapeHtml(job.id)} · Revision ${job.revision}</small>
|
|
@@ -66,7 +66,7 @@ export function createSparkChatPanel({ documentRoot = document, launcherAnchor }
|
|
|
66
66
|
placement.refresh();
|
|
67
67
|
onToggle(value);
|
|
68
68
|
if (!focus) return;
|
|
69
|
-
if (value) dom.
|
|
69
|
+
if (value) dom.composerInput.focus({ preventScroll: true });
|
|
70
70
|
else (previousFocus?.isConnected ? previousFocus : dom.launcherButton)?.focus({ preventScroll: true });
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -14,7 +14,7 @@ export function createSparkChatSettings({ root, onSave, onClear, onOpen, onReset
|
|
|
14
14
|
</form>
|
|
15
15
|
<div class="spark-settings-row">
|
|
16
16
|
<label for="spark-agent-mode"><strong>Thinking mode</strong><span>Choose how deeply SPARK thinks before replying.</span></label>
|
|
17
|
-
<select id="spark-agent-mode" data-spark-agent-mode aria-label="SPARK thinking mode"><option value="fast">
|
|
17
|
+
<select id="spark-agent-mode" data-spark-agent-mode aria-label="SPARK thinking mode"><option value="fast">Low</option><option value="reasoning" selected>Reasoning</option><option value="deep">Deep</option></select>
|
|
18
18
|
</div>
|
|
19
19
|
<div class="spark-settings-row"><div><strong>Chat shortcut</strong><p>Drag SPARK wherever feels right. Use Alt + arrow keys to move it.</p></div>
|
|
20
20
|
<button type="button" data-spark-reset-position>Return to sidebar</button></div>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { hostSetupIsReady } from "./rendering.js";
|
|
2
|
+
import { hasNativePermissionSurface, permissionSummary } from "./macos-permission-rendering.js";
|
|
3
|
+
import { canCheckMacPermissions, canCheckNativePermissions, permissionsMatchConnection, permissionsMatchNativeOwner } from "./macos-permission-scopes.js";
|
|
4
|
+
|
|
5
|
+
function currentPermissionScopes(state) {
|
|
6
|
+
const snapshot = state.snapshot;
|
|
7
|
+
const scopes = [];
|
|
8
|
+
if (snapshot.identity?.os === "macos") {
|
|
9
|
+
scopes.push({
|
|
10
|
+
available: canCheckMacPermissions(snapshot),
|
|
11
|
+
current: permissionsMatchConnection(state.macPermissions, snapshot),
|
|
12
|
+
receipt: state.macPermissions,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
if (hasNativePermissionSurface(snapshot)) {
|
|
16
|
+
const environmentId = snapshot.nativePermissions?.environmentId;
|
|
17
|
+
scopes.push({
|
|
18
|
+
available: canCheckNativePermissions(snapshot, environmentId),
|
|
19
|
+
current: permissionsMatchNativeOwner(state.nativeMacPermissions, snapshot, environmentId),
|
|
20
|
+
receipt: state.nativeMacPermissions,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return scopes;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function scopeRequiresPermission(scope) {
|
|
27
|
+
if (!scope.current) return false;
|
|
28
|
+
return permissionSummary(scope.receipt) === "action needed";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function scopeHasGrantedPermissions(scope) {
|
|
32
|
+
if (!scope.current) return false;
|
|
33
|
+
return permissionSummary(scope.receipt) === "granted";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function scopeCannotCheckPermissions(scope) {
|
|
37
|
+
return !scope.available;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function computerPermissionIndicator(state) {
|
|
41
|
+
const scopes = currentPermissionScopes(state);
|
|
42
|
+
if (scopes.some(scopeRequiresPermission))
|
|
43
|
+
return { icon: "failed", label: "Required", tone: "attention" };
|
|
44
|
+
if (!scopes.length)
|
|
45
|
+
return { icon: "neutral", label: "Unavailable", tone: "neutral" };
|
|
46
|
+
if (scopes.some(scopeCannotCheckPermissions))
|
|
47
|
+
return { icon: "paused", label: "Unavailable", tone: "neutral" };
|
|
48
|
+
if (scopes.every(scopeHasGrantedPermissions))
|
|
49
|
+
return { icon: "success", label: "Granted", tone: "success" };
|
|
50
|
+
return { icon: "unknown", label: "Not checked", tone: "neutral" };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function canPreviewConnectedComputer(state) {
|
|
54
|
+
if (state.snapshot?.connected !== true) return false;
|
|
55
|
+
if (!hostSetupIsReady(state.snapshot)) return false;
|
|
56
|
+
if (state.busy) return false;
|
|
57
|
+
if (state.downloaded) return false;
|
|
58
|
+
if (state.manualMac) return false;
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Project current receipts without requesting permissions or changing connection state. */
|
|
63
|
+
export function computerWidgetPreview(state, title, status) {
|
|
64
|
+
if (!canPreviewConnectedComputer(state)) return null;
|
|
65
|
+
const os = state.snapshot.identity?.os;
|
|
66
|
+
return {
|
|
67
|
+
kind: "computer",
|
|
68
|
+
title,
|
|
69
|
+
detail: { macos: "macOS", windows: "Windows", linux: "Linux" }[os] || os || "Unknown OS",
|
|
70
|
+
items: [
|
|
71
|
+
{ label: "Connection", indicator: { icon: "success", label: status, tone: "success" } },
|
|
72
|
+
{ label: "Permissions", indicator: computerPermissionIndicator(state) },
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { connectionDescription, connectionStatus, connectionTitle, hostSetupIsReady } from "./rendering.js";
|
|
2
|
+
import { isNativeWindowsLocalAccess, nativeWindowsAccessPresentation } from "./native-windows-access.js";
|
|
3
|
+
import { computerWidgetPreview } from "./home-widget-permission-preview.js";
|
|
4
|
+
import { macPermissionSummary, permissionSummary } from "./macos-permission-rendering.js";
|
|
5
|
+
import { permissionsMatchConnection, permissionsMatchNativeOwner } from "./macos-permission-scopes.js";
|
|
6
|
+
import { storeConnectionStage, storeConnectionDisplayContent, windowsStorePanelIsAvailable } from "./windows-store-setup.js";
|
|
7
|
+
|
|
8
|
+
function currentMacPermissionStates(state) {
|
|
9
|
+
const snapshot = state.snapshot;
|
|
10
|
+
const states = [];
|
|
11
|
+
if (permissionsMatchConnection(state.macPermissions, snapshot))
|
|
12
|
+
states.push(permissionSummary(state.macPermissions));
|
|
13
|
+
if (permissionsMatchNativeOwner(state.nativeMacPermissions, snapshot, snapshot?.nativePermissions?.environmentId))
|
|
14
|
+
states.push(permissionSummary(state.nativeMacPermissions));
|
|
15
|
+
return states;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function hasComputerActionFailure(state) {
|
|
19
|
+
return Boolean(state.error || state.actionError || state.macPermissionError || state.nativeMacPermissionError);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function computerPermissionTone(state, permissionText) {
|
|
23
|
+
if (hasComputerActionFailure(state)) return "attention";
|
|
24
|
+
const status = connectionStatus(state.snapshot, state.statusUnavailable, state.busy);
|
|
25
|
+
if (["Paired · offline", "Update needed", "Computer access unavailable"].includes(status)) return "attention";
|
|
26
|
+
const states = currentMacPermissionStates(state);
|
|
27
|
+
if (states.includes("action needed")) return "attention";
|
|
28
|
+
// A connected Mac with unmeasured or unavailable permissions is not all-clear.
|
|
29
|
+
if (permissionText) return "neutral";
|
|
30
|
+
if (hostSetupIsReady(state.snapshot)) return "success";
|
|
31
|
+
return "neutral";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function windowsStoreTone(state, stage) {
|
|
35
|
+
if (hasComputerActionFailure(state)) return "attention";
|
|
36
|
+
if (state.busy) return "neutral";
|
|
37
|
+
const tones = { ready: "success", reconnect: "attention", expired: "attention", "confirm-repair": "attention", preparing: "active", repairing: "active", waiting: "active", open: "active" };
|
|
38
|
+
return tones[stage] || "neutral";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function nativeWindowsTone(state, status) {
|
|
42
|
+
if (hasComputerActionFailure(state)) return "attention";
|
|
43
|
+
if (status === "Check needed") return "attention";
|
|
44
|
+
return "neutral";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function windowsStoreSummary(state) {
|
|
48
|
+
const snapshot = state.snapshot;
|
|
49
|
+
const invitation = state.windowsStoreInvitation;
|
|
50
|
+
const stage = storeConnectionStage(snapshot, invitation, state.windowsStoreAttempt);
|
|
51
|
+
const content = storeConnectionDisplayContent(stage, snapshot, invitation, state.busy, state.statusUnavailable);
|
|
52
|
+
return {
|
|
53
|
+
title: snapshot.identity?.name || content.step,
|
|
54
|
+
detail: state.error || state.actionError || state.message || content.copy,
|
|
55
|
+
status: content.status,
|
|
56
|
+
tone: windowsStoreTone(state, stage),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Connection and process-bound permission receipts stay separate facts. */
|
|
61
|
+
export function computerAccessWidgetSummary(state = {}, supported = true) {
|
|
62
|
+
const input = { ...state, supported };
|
|
63
|
+
if (!supported)
|
|
64
|
+
return { title: "Computer connection unavailable", detail: "Computer access setup requires the local Runtime backend.", status: "Unavailable", tone: "neutral" };
|
|
65
|
+
if (state.statusUnavailable)
|
|
66
|
+
return { title: "Check your computer connection", detail: "The current connection status could not be checked.", status: "Status unavailable", tone: "attention" };
|
|
67
|
+
if (!state.snapshot)
|
|
68
|
+
return { title: "Checking this computer…", detail: "", status: "Checking", tone: "neutral" };
|
|
69
|
+
if (isNativeWindowsLocalAccess(state.snapshot)) {
|
|
70
|
+
const presentation = nativeWindowsAccessPresentation(input);
|
|
71
|
+
return {
|
|
72
|
+
title: presentation.title,
|
|
73
|
+
detail: state.error || state.actionError || state.message || presentation.description,
|
|
74
|
+
status: presentation.status,
|
|
75
|
+
tone: nativeWindowsTone(state, presentation.status),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (windowsStorePanelIsAvailable(state.snapshot)) return windowsStoreSummary(state);
|
|
79
|
+
const permissionText = macPermissionSummary(state.snapshot, state.macPermissions, state.nativeMacPermissions);
|
|
80
|
+
const title = state.snapshot.identity?.name || connectionTitle(input);
|
|
81
|
+
if (state.busy)
|
|
82
|
+
return { title, detail: "Waiting for the current connection status…", status: "Checking", tone: "neutral" };
|
|
83
|
+
const feedback = state.error || state.actionError || state.macPermissionError || state.nativeMacPermissionError || state.message;
|
|
84
|
+
const status = connectionStatus(state.snapshot, state.statusUnavailable, state.busy);
|
|
85
|
+
const preview = feedback ? null : computerWidgetPreview(state, title, status);
|
|
86
|
+
return {
|
|
87
|
+
title,
|
|
88
|
+
detail: feedback || permissionText || connectionDescription(input),
|
|
89
|
+
status,
|
|
90
|
+
tone: computerPermissionTone(state, permissionText),
|
|
91
|
+
...(preview ? { preview } : {}),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { escapeHtml } from "../../lib/text-format.js";
|
|
2
2
|
import { canCheckMacPermissions, canCheckNativePermissions, permissionsMatchConnection, permissionsMatchNativeOwner } from "./macos-permission-scopes.js";
|
|
3
3
|
|
|
4
|
-
function hasNativePermissionSurface(snapshot) {
|
|
4
|
+
export function hasNativePermissionSurface(snapshot) {
|
|
5
5
|
if (snapshot?.identity?.os === "macos") return true;
|
|
6
6
|
if (!snapshot?.nativePermissions) return false;
|
|
7
7
|
return snapshot.nativePermissions.reason !== "native_macos_unavailable";
|
|
8
8
|
}
|
|
9
|
-
function permissionSummary(receipt) {
|
|
9
|
+
export function permissionSummary(receipt) {
|
|
10
10
|
if (!receipt) return "not checked";
|
|
11
11
|
if (receipt.permissions.screenRecording !== "granted") return "action needed";
|
|
12
12
|
if (receipt.permissions.accessibility !== "granted") return "action needed";
|
|
@@ -11,7 +11,7 @@ export function shouldRenderNativeWindowsAccess(input) {
|
|
|
11
11
|
return isNativeWindowsLocalAccess(input.snapshot);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
function nativeWindowsAccessPresentation(input) {
|
|
14
|
+
export function nativeWindowsAccessPresentation(input) {
|
|
15
15
|
if (input.statusUnavailable) return {
|
|
16
16
|
title: "Check Windows access", status: "Status unavailable",
|
|
17
17
|
description: "The current local access status could not be checked. Refresh to try again.",
|
|
@@ -23,7 +23,7 @@ function pairedCompanionIsOffline(snapshot) {
|
|
|
23
23
|
function hasDirectAccess(snapshot) {
|
|
24
24
|
return ["native", "wsl_interop"].includes(snapshot?.readiness?.route);
|
|
25
25
|
}
|
|
26
|
-
function connectionStatus(snapshot, statusUnavailable, busy) {
|
|
26
|
+
export function connectionStatus(snapshot, statusUnavailable, busy) {
|
|
27
27
|
if (statusUnavailable) return "Status unavailable";
|
|
28
28
|
if (busy || !snapshot) return "Checking";
|
|
29
29
|
if (hostSetupIsReady(snapshot)) return snapshot.identity?.os === "macos" ? "Connected" : "Ready";
|
|
@@ -42,7 +42,7 @@ function readyDescription(snapshot) {
|
|
|
42
42
|
return "Direct commands are available. No extra installation is needed for direct commands.";
|
|
43
43
|
return "You can use computer tools from your ABot chat. Permissions and Spark collection are managed separately.";
|
|
44
44
|
}
|
|
45
|
-
function connectionTitle({ snapshot, supported, statusUnavailable, busy }) {
|
|
45
|
+
export function connectionTitle({ snapshot, supported, statusUnavailable, busy }) {
|
|
46
46
|
if (!supported) return "Computer connection unavailable";
|
|
47
47
|
if (statusUnavailable) return "Check your computer connection";
|
|
48
48
|
if (busy || !snapshot) return "Checking this computer…";
|
|
@@ -55,7 +55,7 @@ function connectionTitle({ snapshot, supported, statusUnavailable, busy }) {
|
|
|
55
55
|
if (platforms.length === 1 && platforms[0] === "linux") return "Connect your Linux computer";
|
|
56
56
|
return "Connect your computer";
|
|
57
57
|
}
|
|
58
|
-
function connectionDescription({ snapshot, supported, statusUnavailable, busy }) {
|
|
58
|
+
export function connectionDescription({ snapshot, supported, statusUnavailable, busy }) {
|
|
59
59
|
if (!supported) return "Computer access setup requires the local Runtime backend.";
|
|
60
60
|
if (statusUnavailable) return "The current connection status could not be checked. Refresh to try again.";
|
|
61
61
|
if (busy || !snapshot) return "Waiting for the current connection status…";
|
|
@@ -41,7 +41,7 @@ function storeRepairConfirmationIsCurrent(snapshot, attempt) {
|
|
|
41
41
|
return attempt?.phase === "confirm-repair";
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function storeConnectionStage(snapshot, invitation, attempt) {
|
|
44
|
+
export function storeConnectionStage(snapshot, invitation, attempt) {
|
|
45
45
|
if (snapshot?.readiness?.ready === true) return "ready";
|
|
46
46
|
if (attempt?.phase === "repairing") return "repairing";
|
|
47
47
|
if (storeRepairConfirmationIsCurrent(snapshot, attempt)) return "confirm-repair";
|
|
@@ -111,7 +111,7 @@ function connectionStageContent(stage, snapshot, invitation, disabled) {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function storeConnectionDisplayContent(stage, snapshot, invitation, disabled, statusUnavailable) {
|
|
114
|
+
export function storeConnectionDisplayContent(stage, snapshot, invitation, disabled, statusUnavailable) {
|
|
115
115
|
if (statusUnavailable) return {
|
|
116
116
|
status: "Status unavailable", step: "Check your computer connection",
|
|
117
117
|
copy: "The current connection status could not be checked. Refresh to try again.",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createSystemHostConnectionManager } from "./components/system-host/manager.js";
|
|
2
2
|
import { createSystemHostSetupNotice } from "./components/system-host/setup-notice.js";
|
|
3
|
+
import { computerAccessWidgetSummary } from "./components/system-host/home-widget-summary.js";
|
|
3
4
|
|
|
4
5
|
/** One connection owner for configured Home and its shared chat notice. */
|
|
5
6
|
export function createComputerAccessFeature({
|
|
@@ -7,11 +8,13 @@ export function createComputerAccessFeature({
|
|
|
7
8
|
runtimeClient,
|
|
8
9
|
getEnvironmentId = () => "",
|
|
9
10
|
isComputerAccessAvailable = () => true,
|
|
11
|
+
compactHomeWidgets,
|
|
10
12
|
onChange = () => {},
|
|
11
13
|
}) {
|
|
12
14
|
const documentRoot = dom.homeDashboardRoot?.ownerDocument;
|
|
13
15
|
const root = documentRoot?.createElement("section");
|
|
14
16
|
let notice;
|
|
17
|
+
let unregisterWidget = () => {};
|
|
15
18
|
const connection = createSystemHostConnectionManager({
|
|
16
19
|
documentRoot,
|
|
17
20
|
compact: true,
|
|
@@ -27,6 +30,7 @@ export function createComputerAccessFeature({
|
|
|
27
30
|
supportsConnection: () => runtimeClient.supportsSystemHostConnection(),
|
|
28
31
|
onChange: () => {
|
|
29
32
|
notice?.render();
|
|
33
|
+
compactHomeWidgets?.refresh();
|
|
30
34
|
onChange();
|
|
31
35
|
},
|
|
32
36
|
});
|
|
@@ -35,7 +39,7 @@ export function createComputerAccessFeature({
|
|
|
35
39
|
if (!isComputerAccessAvailable()) return false;
|
|
36
40
|
dom.homeWorkspaceButton?.click();
|
|
37
41
|
if (dom.homeWorkspacePanel?.hidden !== false || !root) return false;
|
|
38
|
-
connection.openManagement();
|
|
42
|
+
if (!compactHomeWidgets?.open("computer")) connection.openManagement();
|
|
39
43
|
root.scrollIntoView?.({ block: "start", behavior: "smooth" });
|
|
40
44
|
root.focus({ preventScroll: true });
|
|
41
45
|
return true;
|
|
@@ -45,6 +49,7 @@ export function createComputerAccessFeature({
|
|
|
45
49
|
const ready = isComputerAccessAvailable();
|
|
46
50
|
if (root) root.hidden = !ready;
|
|
47
51
|
connection.setActive(ready);
|
|
52
|
+
compactHomeWidgets?.refresh();
|
|
48
53
|
notice?.render();
|
|
49
54
|
}
|
|
50
55
|
|
|
@@ -71,6 +76,12 @@ export function createComputerAccessFeature({
|
|
|
71
76
|
dom.homeDashboardRoot,
|
|
72
77
|
);
|
|
73
78
|
connection.mount(root);
|
|
79
|
+
unregisterWidget = compactHomeWidgets?.register({
|
|
80
|
+
id: "computer", label: "Computer access", icon: "computer", element: root,
|
|
81
|
+
isAvailable: isComputerAccessAvailable,
|
|
82
|
+
getSummary: () => computerAccessWidgetSummary(connection.state, runtimeClient.supportsSystemHostConnection()),
|
|
83
|
+
onOpen: connection.openManagement,
|
|
84
|
+
}) || unregisterWidget;
|
|
74
85
|
runtimeAvailabilityChanged();
|
|
75
86
|
}
|
|
76
87
|
dom.environmentSelect?.addEventListener("change", connection.environmentChanged);
|
|
@@ -80,6 +91,7 @@ export function createComputerAccessFeature({
|
|
|
80
91
|
open,
|
|
81
92
|
runtimeAvailabilityChanged,
|
|
82
93
|
dispose() {
|
|
94
|
+
unregisterWidget();
|
|
83
95
|
dom.environmentSelect?.removeEventListener("change", connection.environmentChanged);
|
|
84
96
|
notice.dispose();
|
|
85
97
|
connection.dispose();
|
|
@@ -22,6 +22,7 @@ export function createConfigurationFeature({
|
|
|
22
22
|
getLearningSnapshot = () => null,
|
|
23
23
|
isRuntimeReady = () => true,
|
|
24
24
|
isComputerAccessAvailable = () => true,
|
|
25
|
+
compactHomeWidgets,
|
|
25
26
|
}) {
|
|
26
27
|
let configWorkspace;
|
|
27
28
|
let activation;
|
|
@@ -107,6 +108,7 @@ export function createConfigurationFeature({
|
|
|
107
108
|
let homeSetupSuggestion;
|
|
108
109
|
const computerAccess = createComputerAccessFeature({
|
|
109
110
|
dom,
|
|
111
|
+
compactHomeWidgets,
|
|
110
112
|
runtimeClient,
|
|
111
113
|
getEnvironmentId: selectedEnvironmentId,
|
|
112
114
|
isComputerAccessAvailable,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { displayReasoningMode } from "../lib/reasoning-controls.js";
|
|
1
2
|
import { escapeHtml, formatTime, shortId, textOf } from "../lib/text-format.js";
|
|
2
3
|
import { formatDurationMs, latestHealthEvent, projectOperationsSummary } from "../components/operations-summary.js";
|
|
3
4
|
|
|
@@ -112,7 +113,7 @@ export function createOperationsController({ dom, client, getEnvironmentId = ()
|
|
|
112
113
|
const latest = latestHealthEvent(details);
|
|
113
114
|
const rows = [
|
|
114
115
|
["Status", payload.ok ? "Healthy" : "Unhealthy"],
|
|
115
|
-
["Runtime mode", payload.agentMode || "-"],
|
|
116
|
+
["Runtime mode", displayReasoningMode(payload.agentMode) || "-"],
|
|
116
117
|
["Active streams", payload.activeStreamingRequests ?? details.length],
|
|
117
118
|
[
|
|
118
119
|
"Latest event",
|
|
@@ -12,7 +12,7 @@ export function normalizeAgentMode(mode) {
|
|
|
12
12
|
function agentModeMeta(mode) {
|
|
13
13
|
const modes = {
|
|
14
14
|
auto: { label: "Auto", description: "Lets the agent choose", icon: "*" },
|
|
15
|
-
fast: { label: "
|
|
15
|
+
fast: { label: "Low", description: "Shorter and quicker", icon: "!" },
|
|
16
16
|
deep: {
|
|
17
17
|
label: "Deep analysis",
|
|
18
18
|
description: "More careful responses",
|
|
@@ -75,6 +75,15 @@ export function createDashboardFeature({
|
|
|
75
75
|
document.addEventListener("visibilitychange", controller.visibilityChanged);
|
|
76
76
|
return {
|
|
77
77
|
...controller,
|
|
78
|
+
compactWidgets: view.compactWidgets,
|
|
79
|
+
setActive(value) {
|
|
80
|
+
view.compactWidgets.setWorkspace(value ? "home" : "other");
|
|
81
|
+
controller.setActive(value);
|
|
82
|
+
},
|
|
83
|
+
environmentChanged() {
|
|
84
|
+
view.compactWidgets.close({ restoreFocus: false });
|
|
85
|
+
controller.environmentChanged();
|
|
86
|
+
},
|
|
78
87
|
composerHost: view.composerHost,
|
|
79
88
|
setupHost: view.setupHost,
|
|
80
89
|
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { escapeHtml } from "./text-format.js";
|
|
2
2
|
|
|
3
|
+
export function displayReasoningMode(mode) {
|
|
4
|
+
if (mode === "fast") return "Low";
|
|
5
|
+
return mode;
|
|
6
|
+
}
|
|
7
|
+
|
|
3
8
|
export function canChooseReasoning(profile) {
|
|
4
9
|
return profile?.supportsThinking === true;
|
|
5
10
|
}
|
|
@@ -7,7 +12,7 @@ export function canChooseReasoning(profile) {
|
|
|
7
12
|
/** Keep the stored mode for compatibility while showing the effective provider default. */
|
|
8
13
|
export function reasoningModeOptions(mode, enabled, modes = ["fast", "reasoning", "deep"]) {
|
|
9
14
|
if (!enabled) return `<option value="${escapeHtml(mode || "reasoning")}">Provider default</option>`;
|
|
10
|
-
const labels = { fast: "
|
|
15
|
+
const labels = { fast: "Low", reasoning: "Reasoning", deep: "Deep", auto: "Auto" };
|
|
11
16
|
return modes.map((value) => `<option value="${escapeHtml(value)}"${value === mode ? " selected" : ""}>${escapeHtml(labels[value] || value)}</option>`).join("");
|
|
12
17
|
}
|
|
13
18
|
|
|
@@ -77,8 +77,8 @@ export function createPassiveLearningFeature({
|
|
|
77
77
|
macConsent.cancel();
|
|
78
78
|
controller.environmentChanged();
|
|
79
79
|
},
|
|
80
|
-
mountHome: (root) => {
|
|
81
|
-
home.mount(root);
|
|
80
|
+
mountHome: (root, onRendered) => {
|
|
81
|
+
home.mount(root, onRendered);
|
|
82
82
|
home.render(controller.snapshot());
|
|
83
83
|
},
|
|
84
84
|
});
|