@xopcai/xopc 0.0.297 → 0.0.299
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/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-DKWpcUF7.js → activity-store-C-DSdak3.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BfYFd0FF.js → agent-avatar-dicebear-BnrB5fWD.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CaA7l5Xv.js +1 -0
- package/dist/gateway/static/root/assets/agents-DNxSNGao.js +1 -0
- package/dist/gateway/static/root/assets/api-BhJmc8E-.js +1 -0
- package/dist/gateway/static/root/assets/{api-Bq0dy2ht.js → api-DS4w0i5N.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-D43Mgx8B.js → app-management-settings-panel-Dfrcz-vZ.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DlXRpU1B.js → appearance-settings-BLB_xmtb.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-Bg-7fqIS.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-CSML9uqu.js → archive-plugin-CISHdvCz.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CWG19Y6q.js → attachment-load-c0q_Q6IQ.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-EmWwQYaa.js → automations-page-BOiNdKcv.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-DDdsNbjH.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-BZS8DPaq.js → binary-plugins-BO1hALPX.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-ByjiDUgd.js → block-editor-BWzZ4hDH.js} +3 -3
- package/dist/gateway/static/root/assets/{browser-automation-inputs-Ba7bkmFQ.js → browser-automation-inputs-DvwCwLOp.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-Dt_L_Cpo.js → browser-automations-page-B8LfUUco.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-BtZbX85K.js +3 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-mNpAFqTf.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-BBX7Gp4q.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-Czx0fIBL.js → channels-status-swr-CgtFOwNh.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-Bqo71n61.js → chat-terminal-dock-CLYsf1w_.js} +1 -1
- package/dist/gateway/static/root/assets/{computer-model-settings-WsDcg3Cu.js → computer-model-settings-DYWcZu2X.js} +1 -1
- package/dist/gateway/static/root/assets/{computer-settings-page-CqSG1Z5G.js → computer-settings-page-B4pC7mRs.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-BVUnp0UV.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-Dk8yzEE2.js → cron-expression-DKSgHs4I.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-q4WA5x1M.js → date-picker-DRTglPVS.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-zHQy10Yn.js → dependency-picker-_-7WsbTH.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-DhkPZj6W.js → desktop-pet-CR7n2K67.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BIwU_kdY.js → desktop-pet-settings-Bu7g83kd.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-D5z7BvaO.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-BBgQYoL7.js → extension-debug-page-BI8pvu2u.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-D_cUtXzx.js → extension-page-EZC07dGv.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-C9W-nxmA.js → extension-settings-page-DLYC6gVA.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Dkc1As9z.js → gateway-config-swr-B2xVR9gt.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-C17LDur8.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DnLnaPev.js → gateway-startup-retry-c7s8h7px.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-vqqTCSuv.js → heartbeat-settings-BAMr_vYa.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-DG19Sjrn.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-DTXI5ZGN.js → image-generation-api-DUjbV88R.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-DTqPlG9Z.js → imports-page-BaQmVh_d.js} +1 -1
- package/dist/gateway/static/root/assets/index-B7JCOaCc.js +81 -0
- package/dist/gateway/static/root/assets/index-Bt6a_Yxc.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CGmRXeAV.js → keyboard-shortcuts-settings-DfNQK_hR.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-h48NEuKs.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-8EVAomX7.js → local-apps-page-DFMrfoGF.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-Bvh7i-qf.js → locale-store-CwuCkjo7.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-hLfq_60v.js → logs-page-CD9MfQDD.js} +2 -2
- package/dist/gateway/static/root/assets/{management-settings-APknJ5Qn.js → management-settings-Dib_yIDQ.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-D5qRss8E.js → markdown-view-3YQc6QFV.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DnchdxYn.js → media-plugins-DlZXjN6z.js} +1 -1
- package/dist/gateway/static/root/assets/messages-D6CRVWtT.js +3 -0
- package/dist/gateway/static/root/assets/note-detail-panel-CS0W3ESn.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-BNMVGN6Y.js +8 -0
- package/dist/gateway/static/root/assets/{page-tabs-BlJpkM2b.js → page-tabs-BLzm5EXm.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Db4HBrWW.js → preview-open-alternatives-B6QLKIZy.js} +1 -1
- package/dist/gateway/static/root/assets/{proactive-page-Cc35IKkK.js → proactive-page-W_uN2_ie.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-DZkUoQug.js → product-open-page-DLm3cUhY.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-Gfze4S0P.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-DT7zmH0f.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-Z5aZS7Pw.js → registry-api-Cxx1-pCg.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CXQkXSU2.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BerFoTmq.js → runtime-tools-settings-panel-DHkNbhpP.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-BiEwDJQH.js → schema-form-BTLg2fN1.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CxTLRoxv.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BgtDlDZh.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-064-WN2e.js → settings-form-section-D9rWLTBX.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-CknC1u66.js → settings-page-BR9XJ0j9.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-BSo76NwE.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-D_-ggSSf.js → share-preview-page-Dx2IpPEp.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-BMF0Bo06.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-DNBw3BJR.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-J1NQE7pm.js → skills-page-CaX9EQtn.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-wM2PHuMb.js → skills-page.utils-CxWdcFKs.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-BpLdnG9I.js → system-settings-panel-BkiXkDSq.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-UBuGZQkl.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-DBrRX9jz.js → theme-store-Dt7ob2wD.js} +1 -1
- package/dist/gateway/static/root/assets/tool-activity-BtJkgjFf.js +1 -0
- package/dist/gateway/static/root/assets/tunnel-api-CEXwG7vJ.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-M_tMNgrm.js → use-autosave-BHxjmV8l.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-Dvtr3CPj.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-CYPTjigV.js → voice-api-key-field-BCNM-BaQ.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-CzjqrH53.js → voice-config-api-De1DTzxK.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CkjhVk1T.js → work-discovery-overlay-tig5sF-Q.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DadGKMJG.js → workflow-run-setup-panel-OcS30LVZ.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-AqlMn0Bx.js +6 -0
- package/dist/gateway/static/root/index.html +11 -11
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/tool-activity.js +48 -0
- package/dist/src/agent/memory/compaction.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js +11 -4
- package/dist/src/agent/service/process-direct-streaming.js +2 -1
- package/dist/src/auth/oauth/xopc-cloud.js +22 -9
- package/dist/src/auth/oauth-provider-lock.js +29 -0
- package/dist/src/chat-commands/builtins/config.d.ts +1 -0
- package/dist/src/chat-commands/builtins/config.js +13 -9
- package/dist/src/chat-commands/builtins/model.js +2 -1
- package/dist/src/chat-commands/builtins/session.js +10 -7
- package/dist/src/chat-commands/builtins/skill.js +0 -1
- package/dist/src/chat-commands/builtins/thinking.js +12 -8
- package/dist/src/chat-commands/builtins/tts.js +7 -7
- package/dist/src/chat-commands/builtins/understanding.js +2 -1
- package/dist/src/chat-commands/command-parse.js +5 -6
- package/dist/src/chat-commands/context.js +19 -16
- package/dist/src/cli/commands/browser-cli-helpers.js +4 -1
- package/dist/src/config/schema.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/chat-stream/mapper.js +1 -0
- package/dist/src/gateway/chat-stream/protocol.d.ts +2 -1
- package/dist/src/gateway/hono/routes/browser.js +3 -1
- package/dist/src/gateway/hono/routes/session-input-handler.d.ts +3 -1
- package/dist/src/gateway/hono/routes/session-input-handler.js +21 -1
- package/dist/src/gateway/hono/routes/tasks.js +1 -1
- package/dist/src/session/reset-triggers.d.ts +2 -0
- package/dist/src/session/reset-triggers.js +11 -1
- package/dist/src/session/turn-outcome-projector.js +1 -3
- package/dist/src/user-context/config.js +2 -2
- package/package.json +3 -3
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CjMbr_tR.js +0 -1
- package/dist/gateway/static/root/assets/agents-Cd56crFB.js +0 -1
- package/dist/gateway/static/root/assets/api-DPVNGtF-.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-DKM50qxI.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-BeT43VCC.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-41LCBsl6.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-y-B20Hls.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-CSh7VaIN.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DRJgZgHk.js +0 -2
- package/dist/gateway/static/root/assets/device-pairing-wizard-CYW-SA1I.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-BzGDSxs8.js +0 -1
- package/dist/gateway/static/root/assets/home-page-Bg2FLMtL.js +0 -1
- package/dist/gateway/static/root/assets/index-BWAwKQMv.js +0 -75
- package/dist/gateway/static/root/assets/index-CdrKvNSO.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-D-Ak9bTF.js +0 -2
- package/dist/gateway/static/root/assets/messages-CRy5Dn65.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-D6Zx-Q4b.js +0 -5
- package/dist/gateway/static/root/assets/notes-page--sNX8iOX.js +0 -8
- package/dist/gateway/static/root/assets/project-detail-page-B03RQcfa.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-C9DLyRWZ.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DZBWTZrQ.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-B4hnQBev.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-NpUbJw3z.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DI7Clo_p.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Y0WYEYSb.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-FaKOLTFa.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-BsDOJlNH.js +0 -1
- package/dist/gateway/static/root/assets/tool-activity-R8V9l6nk.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-C4xWYFhH.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-82Rgg2gv.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-BEmYJRnU.js +0 -6
|
@@ -367,14 +367,24 @@ async function login(callbacks, options) {
|
|
|
367
367
|
}) === "device_code" ? loginWithDeviceCode(callbacks, options.scope) : loginWithBrowser(callbacks, options.scope);
|
|
368
368
|
}
|
|
369
369
|
async function refreshToken(current, signal) {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
370
|
+
for (let attempt = 1; attempt <= 2; attempt += 1) try {
|
|
371
|
+
const attemptSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(REFRESH_ATTEMPT_TIMEOUT_MS)]) : AbortSignal.timeout(REFRESH_ATTEMPT_TIMEOUT_MS);
|
|
372
|
+
const response = await tokenRequest(new URLSearchParams({
|
|
373
|
+
grant_type: "refresh_token",
|
|
374
|
+
client_id: CLIENT_ID,
|
|
375
|
+
refresh_token: current.refresh
|
|
376
|
+
}), attemptSignal);
|
|
377
|
+
const body = await readJson(response);
|
|
378
|
+
if (!response.ok) {
|
|
379
|
+
const detail = body.error_description ?? body.error ?? "XOPC OAuth refresh failed";
|
|
380
|
+
throw new OAuthRefreshRejectedError(body.error === "invalid_grant" ? `XOPC authorization expired; reconnect the affected service in Settings. ${detail}` : detail);
|
|
381
|
+
}
|
|
382
|
+
return credentials(body);
|
|
383
|
+
} catch (error) {
|
|
384
|
+
if (error instanceof OAuthRefreshRejectedError || attempt === 2 || signal?.aborted) throw error;
|
|
385
|
+
await setTimeout$1(REFRESH_RETRY_DELAY_MS, void 0, signal ? { signal } : void 0);
|
|
386
|
+
}
|
|
387
|
+
throw new Error("XOPC OAuth refresh failed");
|
|
378
388
|
}
|
|
379
389
|
function createXopcOAuthProvider(options) {
|
|
380
390
|
return {
|
|
@@ -389,7 +399,7 @@ function createXopcOAuthProvider(options) {
|
|
|
389
399
|
getApiKey: (value) => value.access
|
|
390
400
|
};
|
|
391
401
|
}
|
|
392
|
-
var CLIENT_ID, DEFAULT_CONSOLE_URL, MODEL_SERVICE_SCOPE, TUNNEL_REGISTRATION_SCOPE, HOSTED_SHARE_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, xopcCloudOAuthProvider, xopcTunnelOAuthProvider, xopcShareOAuthProvider;
|
|
402
|
+
var CLIENT_ID, DEFAULT_CONSOLE_URL, MODEL_SERVICE_SCOPE, TUNNEL_REGISTRATION_SCOPE, HOSTED_SHARE_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, REFRESH_ATTEMPT_TIMEOUT_MS, REFRESH_RETRY_DELAY_MS, OAuthRefreshRejectedError, xopcCloudOAuthProvider, xopcTunnelOAuthProvider, xopcShareOAuthProvider;
|
|
393
403
|
var init_xopc_cloud = __esmMin((() => {
|
|
394
404
|
init_pkce();
|
|
395
405
|
init_resolution();
|
|
@@ -400,6 +410,9 @@ var init_xopc_cloud = __esmMin((() => {
|
|
|
400
410
|
HOSTED_SHARE_SCOPE = "shares:read shares:write offline_access";
|
|
401
411
|
CALLBACK_PATH = "/oauth/callback";
|
|
402
412
|
AUTHORIZATION_TIMEOUT_MS = 5 * 6e4;
|
|
413
|
+
REFRESH_ATTEMPT_TIMEOUT_MS = 7e3;
|
|
414
|
+
REFRESH_RETRY_DELAY_MS = 100;
|
|
415
|
+
OAuthRefreshRejectedError = class extends Error {};
|
|
403
416
|
xopcCloudOAuthProvider = createXopcOAuthProvider({
|
|
404
417
|
id: "xopc-cloud",
|
|
405
418
|
name: "XOPC Model Service",
|
|
@@ -15,6 +15,34 @@ function isAlreadyExists(error) {
|
|
|
15
15
|
function isMissing(error) {
|
|
16
16
|
return error?.code === "ENOENT";
|
|
17
17
|
}
|
|
18
|
+
function isProcessMissing(error) {
|
|
19
|
+
return error?.code === "ESRCH";
|
|
20
|
+
}
|
|
21
|
+
async function removeAbandonedLock(path) {
|
|
22
|
+
let owner;
|
|
23
|
+
try {
|
|
24
|
+
owner = await readFile(path, "utf8");
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if (isMissing(error)) return true;
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
const pid = Number.parseInt(owner.split(":", 1)[0] ?? "", 10);
|
|
30
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
31
|
+
try {
|
|
32
|
+
process.kill(pid, 0);
|
|
33
|
+
return false;
|
|
34
|
+
} catch (error) {
|
|
35
|
+
if (!isProcessMissing(error)) return false;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
if (await readFile(path, "utf8") !== owner) return false;
|
|
39
|
+
await rm(path, { force: true });
|
|
40
|
+
return true;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (isMissing(error)) return true;
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
18
46
|
async function removeStaleLock(path) {
|
|
19
47
|
try {
|
|
20
48
|
const info = await stat(path);
|
|
@@ -47,6 +75,7 @@ async function acquireFileLock(providerId, options) {
|
|
|
47
75
|
};
|
|
48
76
|
} catch (error) {
|
|
49
77
|
if (!isAlreadyExists(error)) throw error;
|
|
78
|
+
if (await removeAbandonedLock(path)) continue;
|
|
50
79
|
if (await removeStaleLock(path)) continue;
|
|
51
80
|
if (Date.now() >= deadline) throw new Error(`Timed out waiting for OAuth credential lock for ${providerId}`);
|
|
52
81
|
await setTimeout(LOCK_RETRY_MS, void 0, options.signal ? { signal: options.signal } : void 0);
|
|
@@ -19,12 +19,13 @@ function isBlockedPath(path) {
|
|
|
19
19
|
for (const blocked of BLOCKED_WRITE_PATHS) if (joined === blocked || joined.startsWith(`${blocked}.`)) return true;
|
|
20
20
|
return false;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
22
|
+
const SENSITIVE_CONFIG_KEY = /(?:api[_-]?key|token|secret|password|passwd|credential|private[_-]?key|authorization|cookie)$/i;
|
|
23
|
+
function redactConfigForDisplay(value) {
|
|
24
|
+
if (Array.isArray(value)) return value.map(redactConfigForDisplay);
|
|
25
|
+
if (!value || typeof value !== "object") return value;
|
|
26
|
+
const out = {};
|
|
27
|
+
for (const [key, entry] of Object.entries(value)) out[key] = SENSITIVE_CONFIG_KEY.test(key) ? "[redacted]" : redactConfigForDisplay(entry);
|
|
28
|
+
return out;
|
|
28
29
|
}
|
|
29
30
|
function senderMayWritePersistentConfig(ctx) {
|
|
30
31
|
const { source, senderId, isGroup } = ctx;
|
|
@@ -84,9 +85,12 @@ const configCommand = {
|
|
|
84
85
|
const action = parts[0]?.toLowerCase();
|
|
85
86
|
const rest = parts.slice(1).join(" ").trim();
|
|
86
87
|
if (!action || action === "show" || action === "get") {
|
|
88
|
+
if (!senderMayWritePersistentConfig(ctx)) return {
|
|
89
|
+
content: "⚠️ You are not allowed to view configuration from this chat surface.",
|
|
90
|
+
success: false
|
|
91
|
+
};
|
|
87
92
|
const config = ctx.getConfig?.() ?? loadConfig(resolveConfigPath());
|
|
88
|
-
const plain = JSON.parse(JSON.stringify(config));
|
|
89
|
-
redactConfigForDisplay(plain);
|
|
93
|
+
const plain = redactConfigForDisplay(JSON.parse(JSON.stringify(config)));
|
|
90
94
|
if (rest) {
|
|
91
95
|
const parsed = parseConfigPath(rest);
|
|
92
96
|
if (!parsed.ok || !parsed.path) return {
|
|
@@ -183,4 +187,4 @@ function registerConfigCommand() {
|
|
|
183
187
|
commandRegistry.register(configCommand);
|
|
184
188
|
}
|
|
185
189
|
//#endregion
|
|
186
|
-
export { registerConfigCommand };
|
|
190
|
+
export { redactConfigForDisplay, registerConfigCommand };
|
|
@@ -78,7 +78,8 @@ const switchCommand = {
|
|
|
78
78
|
const modelName = modelId.split("/").pop() || modelId;
|
|
79
79
|
return {
|
|
80
80
|
content: joinBlocks(`✅ Switched to ${code(modelId)} (${modelName}).`, "This model will be used for your next message."),
|
|
81
|
-
success: true
|
|
81
|
+
success: true,
|
|
82
|
+
metadata: { sessionConfigChanged: true }
|
|
82
83
|
};
|
|
83
84
|
}
|
|
84
85
|
return {
|
|
@@ -16,7 +16,7 @@ const newCommand = {
|
|
|
16
16
|
await ctx.setTyping(true);
|
|
17
17
|
await ctx.resetSession();
|
|
18
18
|
return {
|
|
19
|
-
content: "",
|
|
19
|
+
content: "✅ New session started. Previous transcript archived; model and session overrides kept.",
|
|
20
20
|
success: true
|
|
21
21
|
};
|
|
22
22
|
}
|
|
@@ -42,7 +42,7 @@ const listCommand = {
|
|
|
42
42
|
sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
43
43
|
const content = "📋 Your Sessions:\n\n" + sessions.slice(0, 10).map((s) => {
|
|
44
44
|
const indicator = s.isActive ? "▶️" : " ";
|
|
45
|
-
const name = getSessionDisplayName(s.key);
|
|
45
|
+
const name = s.name ?? getSessionDisplayName(s.key);
|
|
46
46
|
const date = s.updatedAt.toLocaleDateString();
|
|
47
47
|
return `${indicator} ${name}\n ${s.messageCount} messages · ${date}`;
|
|
48
48
|
}).join("\n\n");
|
|
@@ -53,7 +53,7 @@ const listCommand = {
|
|
|
53
53
|
type: "session-list",
|
|
54
54
|
sessions: sessions.slice(0, 5).map((s) => ({
|
|
55
55
|
...s,
|
|
56
|
-
name: getSessionDisplayName(s.key)
|
|
56
|
+
name: s.name ?? getSessionDisplayName(s.key)
|
|
57
57
|
})),
|
|
58
58
|
currentSession: ctx.conversationId
|
|
59
59
|
}]
|
|
@@ -67,7 +67,7 @@ const listCommand = {
|
|
|
67
67
|
const clearCommand = {
|
|
68
68
|
id: "session.clear",
|
|
69
69
|
name: "clear",
|
|
70
|
-
description: "Clear current session
|
|
70
|
+
description: "Clear current session and archive its previous transcript",
|
|
71
71
|
category: "session",
|
|
72
72
|
scope: [
|
|
73
73
|
"global",
|
|
@@ -76,10 +76,9 @@ const clearCommand = {
|
|
|
76
76
|
],
|
|
77
77
|
handler: async (ctx) => {
|
|
78
78
|
await ctx.setTyping(true);
|
|
79
|
-
|
|
80
|
-
await ctx.clearSession();
|
|
79
|
+
await ctx.resetSession();
|
|
81
80
|
return {
|
|
82
|
-
content:
|
|
81
|
+
content: "🗑️ Session cleared. Previous transcript archived.",
|
|
83
82
|
success: true
|
|
84
83
|
};
|
|
85
84
|
}
|
|
@@ -226,6 +225,10 @@ const archiveCommand = {
|
|
|
226
225
|
"group"
|
|
227
226
|
],
|
|
228
227
|
handler: async (ctx) => {
|
|
228
|
+
if (ctx.channelId === "webchat") return {
|
|
229
|
+
content: "Archive this chat from the sidebar so the app can navigate away safely.",
|
|
230
|
+
success: false
|
|
231
|
+
};
|
|
229
232
|
await ctx.setTyping(true);
|
|
230
233
|
await ctx.archiveSession();
|
|
231
234
|
return {
|
|
@@ -70,7 +70,6 @@ function parseInstallArgs(args) {
|
|
|
70
70
|
const skillCommand = {
|
|
71
71
|
id: "system.skill",
|
|
72
72
|
name: "skill",
|
|
73
|
-
aliases: ["skills"],
|
|
74
73
|
description: "Install skills from explicit sources. Subcommands: install <source>",
|
|
75
74
|
category: "tool",
|
|
76
75
|
scope: ["global", "private"],
|
|
@@ -49,8 +49,9 @@ const thinkCommand = {
|
|
|
49
49
|
xhigh: "Extra high thinking effort",
|
|
50
50
|
max: "Maximum thinking effort",
|
|
51
51
|
adaptive: "Auto-adjust based on task complexity"
|
|
52
|
-
}[level]}\n\
|
|
53
|
-
success: true
|
|
52
|
+
}[level]}\n\nSaved for this conversation until you change it.`,
|
|
53
|
+
success: true,
|
|
54
|
+
metadata: { sessionConfigChanged: true }
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
57
|
};
|
|
@@ -88,8 +89,9 @@ const reasoningCommand = {
|
|
|
88
89
|
off: "Hide reasoning from user",
|
|
89
90
|
on: "Show reasoning after completion",
|
|
90
91
|
stream: "Stream reasoning in real-time"
|
|
91
|
-
}[level]}\n\
|
|
92
|
-
success: true
|
|
92
|
+
}[level]}\n\nSaved for this conversation until you change it.`,
|
|
93
|
+
success: true,
|
|
94
|
+
metadata: { sessionConfigChanged: true }
|
|
93
95
|
};
|
|
94
96
|
}
|
|
95
97
|
};
|
|
@@ -116,8 +118,9 @@ const verboseCommand = {
|
|
|
116
118
|
const newLevel = await ctx.getVerboseLevel?.() === "on" ? "off" : "on";
|
|
117
119
|
await setSessionAgentField(ctx.getSessionConfigStore?.(), ctx.conversationId, "verboseLevel", newLevel);
|
|
118
120
|
return {
|
|
119
|
-
content: `📝 *Verbose Mode*\n\nMode: *${newLevel}*\n\n${newLevel === "on" ? "Verbose output enabled
|
|
120
|
-
success: true
|
|
121
|
+
content: `📝 *Verbose Mode*\n\nMode: *${newLevel}*\n\n${newLevel === "on" ? "Verbose output enabled for this conversation." : "Verbose output disabled for this conversation."}`,
|
|
122
|
+
success: true,
|
|
123
|
+
metadata: { sessionConfigChanged: true }
|
|
121
124
|
};
|
|
122
125
|
}
|
|
123
126
|
const level = normalizeVerboseLevel(args.trim());
|
|
@@ -131,8 +134,9 @@ const verboseCommand = {
|
|
|
131
134
|
off: "Minimal output",
|
|
132
135
|
on: "Normal verbose output",
|
|
133
136
|
full: "Full verbose output with all details"
|
|
134
|
-
}[level]}\n\
|
|
135
|
-
success: true
|
|
137
|
+
}[level]}\n\nSaved for this conversation until you change it.`,
|
|
138
|
+
success: true,
|
|
139
|
+
metadata: { sessionConfigChanged: true }
|
|
136
140
|
};
|
|
137
141
|
}
|
|
138
142
|
};
|
|
@@ -84,7 +84,7 @@ Voice: *${currentVoice}*
|
|
|
84
84
|
switch (arg) {
|
|
85
85
|
case "on":
|
|
86
86
|
case "enable": {
|
|
87
|
-
const success = await ctx.updateConfig?.("tts.enabled", true);
|
|
87
|
+
const success = await ctx.updateConfig?.("messages.tts.enabled", true);
|
|
88
88
|
const base = success ? "✅ TTS enabled. Use `/tts always` or `/tts inbound` to set trigger mode." : "❌ Failed to enable TTS.";
|
|
89
89
|
return {
|
|
90
90
|
content: success ? appendTtsReadinessNote(base, ctx.getConfig?.()) : base,
|
|
@@ -93,7 +93,7 @@ Voice: *${currentVoice}*
|
|
|
93
93
|
}
|
|
94
94
|
case "off":
|
|
95
95
|
case "disable": {
|
|
96
|
-
const success = await ctx.updateConfig?.("tts.enabled", false);
|
|
96
|
+
const success = await ctx.updateConfig?.("messages.tts.enabled", false);
|
|
97
97
|
return {
|
|
98
98
|
content: success ? "✅ TTS disabled." : "❌ Failed to disable TTS.",
|
|
99
99
|
success: !!success
|
|
@@ -103,8 +103,8 @@ Voice: *${currentVoice}*
|
|
|
103
103
|
case "inbound":
|
|
104
104
|
case "tagged": {
|
|
105
105
|
const mode = arg;
|
|
106
|
-
const success = await ctx.updateConfig?.("tts.trigger", mode);
|
|
107
|
-
if (success && !isEnabled) await ctx.updateConfig?.("tts.enabled", true);
|
|
106
|
+
const success = await ctx.updateConfig?.("messages.tts.trigger", mode);
|
|
107
|
+
if (success && !isEnabled) await ctx.updateConfig?.("messages.tts.enabled", true);
|
|
108
108
|
const base = success ? `✅ TTS trigger mode set to *${mode}*${!isEnabled ? " and TTS enabled" : ""}.` : `❌ Failed to set TTS trigger mode.`;
|
|
109
109
|
return {
|
|
110
110
|
content: success ? appendTtsReadinessNote(base, ctx.getConfig?.()) : base,
|
|
@@ -112,7 +112,7 @@ Voice: *${currentVoice}*
|
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
114
|
case "never": {
|
|
115
|
-
const success = await ctx.updateConfig?.("tts.trigger", "off");
|
|
115
|
+
const success = await ctx.updateConfig?.("messages.tts.trigger", "off");
|
|
116
116
|
return {
|
|
117
117
|
content: success ? "✅ TTS trigger mode set to *off*." : "❌ Failed to set TTS trigger mode.",
|
|
118
118
|
success: !!success
|
|
@@ -165,7 +165,7 @@ Voice: *${currentVoice}*
|
|
|
165
165
|
content: `❌ Invalid provider: ${provider}\nValid providers: openai, alibaba, minimax, edge`,
|
|
166
166
|
success: false
|
|
167
167
|
};
|
|
168
|
-
const success = await ctx.updateConfig?.("tts.provider", provider);
|
|
168
|
+
const success = await ctx.updateConfig?.("messages.tts.provider", provider);
|
|
169
169
|
const base = success ? `✅ TTS provider set to *${provider}*.` : "❌ Failed to set TTS provider.";
|
|
170
170
|
return {
|
|
171
171
|
content: success ? appendTtsReadinessNote(base, ctx.getConfig?.()) : base,
|
|
@@ -175,7 +175,7 @@ Voice: *${currentVoice}*
|
|
|
175
175
|
if (subcommand === "voice" && subarg) {
|
|
176
176
|
const voice = subarg;
|
|
177
177
|
const provider = currentProvider;
|
|
178
|
-
const success = await ctx.updateConfig?.(`tts.${provider}.voice`, voice);
|
|
178
|
+
const success = await ctx.updateConfig?.(`messages.tts.providers.${provider}.voice`, voice);
|
|
179
179
|
return {
|
|
180
180
|
content: success ? `✅ TTS voice set to *${voice}* for ${provider}.` : "❌ Failed to set TTS voice.",
|
|
181
181
|
success: !!success
|
|
@@ -101,7 +101,8 @@ const learningCommand = {
|
|
|
101
101
|
const mode = (await store.get(ctx.conversationId))?.userContextMode ?? "enabled";
|
|
102
102
|
return {
|
|
103
103
|
content: globallyEnabled && mode === "enabled" ? "User understanding is enabled for this conversation." : globallyEnabled && mode === "temporary" ? "This is a temporary conversation. Stored user context is not read, and this conversation does not update user understanding." : globallyEnabled ? "User understanding is off for this conversation. Existing chat history is still stored; use /remember for anything you explicitly want saved." : "User understanding is disabled globally. Existing chat history is still stored.",
|
|
104
|
-
success: true
|
|
104
|
+
success: true,
|
|
105
|
+
...action !== "status" ? { metadata: { sessionConfigChanged: true } } : {}
|
|
105
106
|
};
|
|
106
107
|
}
|
|
107
108
|
};
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
function normalizeTelegramCommandName(command) {
|
|
7
7
|
const at = command.indexOf("@");
|
|
8
|
-
|
|
9
|
-
return command.slice(0, at);
|
|
8
|
+
return (at === -1 ? command : command.slice(0, at)).toLowerCase();
|
|
10
9
|
}
|
|
11
10
|
/**
|
|
12
11
|
* Parse a `/command` from message text. Handles:
|
|
@@ -20,14 +19,14 @@ function parseSlashCommand(text) {
|
|
|
20
19
|
const line = part.trim();
|
|
21
20
|
if (!line.startsWith("/")) continue;
|
|
22
21
|
const withoutPrefix = line.slice(1);
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
22
|
+
const whitespaceIndex = withoutPrefix.search(/\s/);
|
|
23
|
+
if (whitespaceIndex === -1) return {
|
|
25
24
|
command: normalizeTelegramCommandName(withoutPrefix),
|
|
26
25
|
args: ""
|
|
27
26
|
};
|
|
28
27
|
return {
|
|
29
|
-
command: normalizeTelegramCommandName(withoutPrefix.slice(0,
|
|
30
|
-
args: withoutPrefix.slice(
|
|
28
|
+
command: normalizeTelegramCommandName(withoutPrefix.slice(0, whitespaceIndex)),
|
|
29
|
+
args: withoutPrefix.slice(whitespaceIndex + 1).trim()
|
|
31
30
|
};
|
|
32
31
|
}
|
|
33
32
|
return null;
|
|
@@ -86,13 +86,6 @@ var CommandContextImpl = class {
|
|
|
86
86
|
await this.clearSession();
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
|
-
await this.deps.bus.publishOutbound({
|
|
90
|
-
channel: this.source,
|
|
91
|
-
chat_id: this.chatId,
|
|
92
|
-
content: "✅ New session started. Previous transcript archived; model and session overrides kept.",
|
|
93
|
-
type: "message",
|
|
94
|
-
metadata: this.outboundMetadata()
|
|
95
|
-
});
|
|
96
89
|
log.info({ conversationId: this.conversationId }, "Session reset");
|
|
97
90
|
}
|
|
98
91
|
async clearSession() {
|
|
@@ -120,15 +113,25 @@ var CommandContextImpl = class {
|
|
|
120
113
|
log.info({ conversationId: this.conversationId }, "Session archived");
|
|
121
114
|
}
|
|
122
115
|
async listSessions() {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
116
|
+
const { items } = await this.deps.sessionStore.list({
|
|
117
|
+
channel: this.channelId,
|
|
118
|
+
limit: 100,
|
|
119
|
+
sortBy: "updatedAt",
|
|
120
|
+
sortOrder: "desc"
|
|
121
|
+
});
|
|
122
|
+
return items.filter((item) => {
|
|
123
|
+
if (this.channelId === "webchat") return true;
|
|
124
|
+
const routing = item.routing;
|
|
125
|
+
if (!routing) return item.key === this.conversationId;
|
|
126
|
+
return routing.peerId === this.chatId && (!this.accountId || routing.accountId === this.accountId) && (!this.threadId || routing.threadId === this.threadId);
|
|
127
|
+
}).map((item) => ({
|
|
128
|
+
key: item.key,
|
|
129
|
+
name: item.name ?? getSessionDisplayName(item.key),
|
|
130
|
+
messageCount: item.messageCount,
|
|
131
|
+
createdAt: new Date(item.createdAt),
|
|
132
|
+
updatedAt: new Date(item.updatedAt),
|
|
133
|
+
isActive: item.key === this.conversationId
|
|
134
|
+
}));
|
|
132
135
|
}
|
|
133
136
|
async switchSession(conversationId) {
|
|
134
137
|
log.info({
|
|
@@ -8,7 +8,10 @@ async function doctorCli() {
|
|
|
8
8
|
console.log("Browser Control v2");
|
|
9
9
|
console.log(`Driver: ${config.browser.driver.kind}`);
|
|
10
10
|
if (!readiness) {
|
|
11
|
-
|
|
11
|
+
if (config.browser.driver.kind === "extension") {
|
|
12
|
+
console.log("Artifacts: ready");
|
|
13
|
+
console.log("Connection: not checked (use the Gateway browser status to verify the live extension endpoint)");
|
|
14
|
+
} else console.log("Status: ready");
|
|
12
15
|
return;
|
|
13
16
|
}
|
|
14
17
|
console.error(`Status: ${readiness.hint.reason}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { ComputerConfigSchema, init_config } from "../computer/config.js";
|
|
2
3
|
import { AgentModelsOverrideSchema, AgentsConfigSchema as AgentsConfigSchema$1, DEFAULT_AGENT_MODEL_REF, ImageGenerationRouteSchema, ModelRouteSchema } from "../agent-config/schema.js";
|
|
3
4
|
import { init_agent_config } from "../agent-config/index.js";
|
|
4
|
-
import { ComputerConfigSchema, init_config } from "../computer/config.js";
|
|
5
5
|
import { DEFAULT_CONTEXT_COMPACTION_POLICY, UserContextConfigSchema, init_config as init_config$1 } from "../user-context/config.js";
|
|
6
6
|
import { init_default_model } from "./default-model.js";
|
|
7
7
|
import { init_public_url, validatePublicUrl } from "./public-url.js";
|
|
@@ -277,4 +277,4 @@ export declare const GATEWAY_BUILTIN_TOOLS: readonly [{
|
|
|
277
277
|
readonly zh: "使用已验证的参数执行选定的外部工具。";
|
|
278
278
|
};
|
|
279
279
|
}];
|
|
280
|
-
export declare const GATEWAY_BUILTIN_TOOL_IDS: ("automation" | "workflow" | "find" | "image" | "
|
|
280
|
+
export declare const GATEWAY_BUILTIN_TOOL_IDS: ("automation" | "workflow" | "find" | "image" | "knowledge_search" | "knowledge_get" | "knowledge_write" | "user_context_search" | "user_context_get" | "user_context_update" | "web_search" | "web_fetch" | "browser_use" | "grep" | "session_search" | "read_file" | "list_dir" | "write_file" | "apply_patch" | "exec_command" | "update_plan" | "todo" | "clarify" | "web_extract" | "image_generate" | "skills_list" | "skill_view" | "skill_manage" | "skills_marketplace_search" | "xopc_tool_search" | "xopc_tool_describe" | "xopc_tool_execute" | "send_message" | "send_media" | "read_media" | "create_share" | "session_status" | "memory_maintenance" | "computer_use" | "tool_manual" | "delegate_task" | "skill_install" | "text_to_speech" | "execute_code" | "create_desktop_pet")[];
|
|
@@ -110,6 +110,7 @@ var ChatStreamMapper = class {
|
|
|
110
110
|
const outcome = parseTurnOutcome(event.outcome);
|
|
111
111
|
return outcome ? [this.make("turn_outcome", outcome)] : [];
|
|
112
112
|
}
|
|
113
|
+
case "session_config_updated": return [this.make("session_config_updated", {})];
|
|
113
114
|
case "error": return [this.make("error", {
|
|
114
115
|
code: "AGENT_RUN_ERROR",
|
|
115
116
|
message: String(event.content ?? event.message ?? "Unknown error"),
|
|
@@ -143,6 +143,7 @@ export type TurnDiffEvent = ChatStreamEnvelope<'turn_diff', {
|
|
|
143
143
|
removed: number;
|
|
144
144
|
}>;
|
|
145
145
|
export type TurnOutcomeEvent = ChatStreamEnvelope<'turn_outcome', TurnOutcome>;
|
|
146
|
+
export type SessionConfigUpdatedEvent = ChatStreamEnvelope<'session_config_updated', Record<string, never>>;
|
|
146
147
|
export type ReviewStartEvent = ChatStreamEnvelope<'review_start', {
|
|
147
148
|
messageId: string;
|
|
148
149
|
reviewId: string;
|
|
@@ -220,4 +221,4 @@ export type StreamErrorEvent = ChatStreamEnvelope<'error', {
|
|
|
220
221
|
recoverable?: boolean;
|
|
221
222
|
petFeedback: PetFeedback;
|
|
222
223
|
}>;
|
|
223
|
-
export type ChatStreamEvent = RunStartEvent | UserMessageEvent | UserTranscriptEvent | AssistantMessageStartEvent | AssistantDeltaEvent | ThinkingDeltaEvent | ThinkingEndEvent | ToolStartEvent | ToolUpdateEvent | ToolEndEvent | CommandStartedEvent | CommandOutputDeltaEvent | CommandCompletedEvent | PatchAppliedEvent | TurnPlanUpdatedEvent | TaskPlanUpdatedEvent | TurnDiffEvent | TurnOutcomeEvent | ReviewStartEvent | ReviewDeltaEvent | ReviewEndEvent | ReviewEvent | AssistantMessageEndEvent | ProgressEvent | CompactionEvent | TtsAudioEvent | ClarifyRequestEvent | RunEndEvent | StreamErrorEvent;
|
|
224
|
+
export type ChatStreamEvent = RunStartEvent | UserMessageEvent | UserTranscriptEvent | AssistantMessageStartEvent | AssistantDeltaEvent | ThinkingDeltaEvent | ThinkingEndEvent | ToolStartEvent | ToolUpdateEvent | ToolEndEvent | CommandStartedEvent | CommandOutputDeltaEvent | CommandCompletedEvent | PatchAppliedEvent | TurnPlanUpdatedEvent | TaskPlanUpdatedEvent | TurnDiffEvent | TurnOutcomeEvent | SessionConfigUpdatedEvent | ReviewStartEvent | ReviewDeltaEvent | ReviewEndEvent | ReviewEvent | AssistantMessageEndEvent | ProgressEvent | CompactionEvent | TtsAudioEvent | ClarifyRequestEvent | RunEndEvent | StreamErrorEvent;
|
|
@@ -18,6 +18,7 @@ async function extensionStatus(service, includeLocalArtifacts) {
|
|
|
18
18
|
const connected = endpoints.length > 0;
|
|
19
19
|
const extensionVersion = endpoint?.appVersion ?? null;
|
|
20
20
|
const doctor = includeLocalArtifacts ? await import("../../../browser/providers/browser-ext-install.js").then(({ browserExtDoctor }) => browserExtDoctor({ runtimeExtensionVersion: extensionVersion ?? void 0 })) : void 0;
|
|
21
|
+
const setupState = connected ? "connected" : doctor ? doctor.installed === true ? "installed_not_connected" : "not_installed" : void 0;
|
|
21
22
|
return {
|
|
22
23
|
running: true,
|
|
23
24
|
socketConnected: connected,
|
|
@@ -46,7 +47,8 @@ async function extensionStatus(service, includeLocalArtifacts) {
|
|
|
46
47
|
} : {} },
|
|
47
48
|
bridgeHeld: false,
|
|
48
49
|
refCount: endpoints.length,
|
|
49
|
-
transport: "gateway-realtime"
|
|
50
|
+
transport: "gateway-realtime",
|
|
51
|
+
...setupState ? { setupState } : {}
|
|
50
52
|
};
|
|
51
53
|
}
|
|
52
54
|
function isLocalOwnerRequest(c, service) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Context } from 'hono';
|
|
2
2
|
import type { AuthenticatedRouteDeps } from './deps.js';
|
|
3
|
-
export declare function submitSessionInput(c: Context, deps: AuthenticatedRouteDeps, conversationId: string
|
|
3
|
+
export declare function submitSessionInput(c: Context, deps: AuthenticatedRouteDeps, conversationId: string, options?: {
|
|
4
|
+
taskConversation?: boolean;
|
|
5
|
+
}): Promise<(Response & import("hono").TypedResponse<{
|
|
4
6
|
ok: false;
|
|
5
7
|
error: {
|
|
6
8
|
code: string;
|
|
@@ -3,6 +3,11 @@ import { init_src } from "../../../../packages/gateway-contract/src/index.js";
|
|
|
3
3
|
import { endpointTurnClaimSchema, init_src as init_src$1 } from "../../../../packages/endpoint-tools-protocol/src/index.js";
|
|
4
4
|
import { init_providers, resolveModel } from "../../../providers/index.js";
|
|
5
5
|
import { validateWebchatAttachments, validateWebchatContent } from "../../chat-limits.js";
|
|
6
|
+
import { isTaskDestructiveCommand } from "../../../session/reset-triggers.js";
|
|
7
|
+
import { parseSlashCommand } from "../../../chat-commands/command-parse.js";
|
|
8
|
+
import { commandRegistry } from "../../../chat-commands/registry.js";
|
|
9
|
+
import "../../../chat-commands/index.js";
|
|
10
|
+
import { isVoiceLikeAttachment } from "../../../channels/attachments/voice-stt-webchat.js";
|
|
6
11
|
import { parseTurnContextRefs } from "../../../agent/source-context/types.js";
|
|
7
12
|
import { getModelThinking } from "../../../providers/model-thinking.js";
|
|
8
13
|
import { withModelConfigLock } from "../../../session/model-config-lock.js";
|
|
@@ -12,7 +17,7 @@ init_src();
|
|
|
12
17
|
init_src$1();
|
|
13
18
|
init_providers();
|
|
14
19
|
const MAX_TURN_CONTEXTS = 5;
|
|
15
|
-
async function submitSessionInput(c, deps, conversationId) {
|
|
20
|
+
async function submitSessionInput(c, deps, conversationId, options) {
|
|
16
21
|
const body = await c.req.json().catch(() => null);
|
|
17
22
|
if (!body || !conversationId) return c.json({
|
|
18
23
|
ok: false,
|
|
@@ -39,6 +44,21 @@ async function submitSessionInput(c, deps, conversationId) {
|
|
|
39
44
|
}
|
|
40
45
|
}, 400);
|
|
41
46
|
const content = typeof body.content === "string" ? body.content : "";
|
|
47
|
+
if (options?.taskConversation && isTaskDestructiveCommand(content)) return c.json({
|
|
48
|
+
ok: false,
|
|
49
|
+
error: {
|
|
50
|
+
code: "BAD_REQUEST",
|
|
51
|
+
message: "A task has one continuous conversation."
|
|
52
|
+
}
|
|
53
|
+
}, 400);
|
|
54
|
+
const parsedCommand = parseSlashCommand(content);
|
|
55
|
+
if (parsedCommand && commandRegistry.has(parsedCommand.command) && attachments?.some((attachment) => !isVoiceLikeAttachment(attachment))) return c.json({
|
|
56
|
+
ok: false,
|
|
57
|
+
error: {
|
|
58
|
+
code: "BAD_REQUEST",
|
|
59
|
+
message: "Slash commands do not accept file or image attachments."
|
|
60
|
+
}
|
|
61
|
+
}, 400);
|
|
42
62
|
const contentError = validateWebchatContent(content);
|
|
43
63
|
if (contentError) return c.json({
|
|
44
64
|
ok: false,
|
|
@@ -222,7 +222,7 @@ function registerTaskRoutes(authenticated, deps) {
|
|
|
222
222
|
message: "Task executor changed; refresh the conversation"
|
|
223
223
|
}
|
|
224
224
|
}, 409);
|
|
225
|
-
return submitSessionInput(c, deps, active.conversationId);
|
|
225
|
+
return submitSessionInput(c, deps, active.conversationId, { taskConversation: true });
|
|
226
226
|
});
|
|
227
227
|
authenticated.patch("/api/tasks/:id/conversation/config", taskRateLimit, async (c) => {
|
|
228
228
|
const body = await c.req.json().catch(() => null);
|
|
@@ -17,4 +17,6 @@ export declare function resolveResetTriggers(configured?: string[]): readonly st
|
|
|
17
17
|
export declare function bareResetAckMessage(matchedTrigger?: string): string;
|
|
18
18
|
/** Slash command names that overlap reset triggers — skip when init already reset. */
|
|
19
19
|
export declare const RESET_OVERLAP_COMMANDS: Set<string>;
|
|
20
|
+
export declare const TASK_DESTRUCTIVE_COMMANDS: Set<string>;
|
|
21
|
+
export declare function isTaskDestructiveCommand(body: string): boolean;
|
|
20
22
|
export declare function shouldSkipResetOverlapCommand(command: string | undefined, resetTriggered: boolean): boolean;
|
|
@@ -53,9 +53,19 @@ const RESET_OVERLAP_COMMANDS = new Set([
|
|
|
53
53
|
"reset",
|
|
54
54
|
"restart"
|
|
55
55
|
]);
|
|
56
|
+
const TASK_DESTRUCTIVE_COMMANDS = new Set([
|
|
57
|
+
...RESET_OVERLAP_COMMANDS,
|
|
58
|
+
"clear",
|
|
59
|
+
"archive"
|
|
60
|
+
]);
|
|
61
|
+
function isTaskDestructiveCommand(body) {
|
|
62
|
+
const normalized = stripLeadingEnvelopeTimestamp(body.trim());
|
|
63
|
+
const match = /^\/([^\s@]+)(?:@[^\s]+)?(?:\s|$)/.exec(normalized);
|
|
64
|
+
return Boolean(match && TASK_DESTRUCTIVE_COMMANDS.has(match[1].toLowerCase()));
|
|
65
|
+
}
|
|
56
66
|
function shouldSkipResetOverlapCommand(command, resetTriggered) {
|
|
57
67
|
if (!resetTriggered || !command) return false;
|
|
58
68
|
return RESET_OVERLAP_COMMANDS.has(command.toLowerCase());
|
|
59
69
|
}
|
|
60
70
|
//#endregion
|
|
61
|
-
export { DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, bareResetAckMessage, matchResetTriggers, resolveResetTriggers, shouldSkipResetOverlapCommand, stripLeadingEnvelopeTimestamp };
|
|
71
|
+
export { DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, TASK_DESTRUCTIVE_COMMANDS, bareResetAckMessage, isTaskDestructiveCommand, matchResetTriggers, resolveResetTriggers, shouldSkipResetOverlapCommand, stripLeadingEnvelopeTimestamp };
|
|
@@ -74,7 +74,6 @@ function projectTurnOutcome(params) {
|
|
|
74
74
|
const diffs = [];
|
|
75
75
|
let added = 0;
|
|
76
76
|
let removed = 0;
|
|
77
|
-
let failedToolCount = 0;
|
|
78
77
|
let createdAtMs = 0;
|
|
79
78
|
let verificationSummary = null;
|
|
80
79
|
for (const source of params.rows) {
|
|
@@ -85,7 +84,6 @@ function projectTurnOutcome(params) {
|
|
|
85
84
|
if (Number.isFinite(timestamp)) createdAtMs = Math.max(createdAtMs, timestamp);
|
|
86
85
|
if (row.role !== "toolResult" && row.role !== "tool") continue;
|
|
87
86
|
const details = record(row.details) ?? {};
|
|
88
|
-
if (row.isError === true && record(details.verification)?.kind !== "check") failedToolCount += 1;
|
|
89
87
|
const explicit = Array.isArray(details.artifacts) ? details.artifacts.flatMap((value) => {
|
|
90
88
|
const parsed = TurnOutcomeDeliverableSchema.safeParse(value);
|
|
91
89
|
return parsed.success ? [parsed.data] : [];
|
|
@@ -149,7 +147,7 @@ function projectTurnOutcome(params) {
|
|
|
149
147
|
const evidenceItems = [...evidence.values()];
|
|
150
148
|
const collectedArtifacts = [...deliverables.values()];
|
|
151
149
|
const artifactItems = mergeTurnOutcomeDeliverables(collectedArtifacts);
|
|
152
|
-
const partial =
|
|
150
|
+
const partial = evidenceItems.some((item) => item.status !== "passed") || verificationSummary?.required === true && verificationSummary.changed === true && !evidenceItems.some((item) => item.status === "passed") || collectedArtifacts.some((item) => item.availability !== "available");
|
|
153
151
|
const diff = diffs.join("\n");
|
|
154
152
|
const diffTruncated = diff.length > MAX_OUTCOME_DIFF_CHARS;
|
|
155
153
|
const createdAt = new Date(createdAtMs || Date.now()).toISOString();
|
|
@@ -20,7 +20,7 @@ var init_config = __esmMin((() => {
|
|
|
20
20
|
minMessagesBeforeCompact: 10,
|
|
21
21
|
keepRecentTokens: 2e4,
|
|
22
22
|
recentTurnsPreserve: 3,
|
|
23
|
-
summaryMaxTokens:
|
|
23
|
+
summaryMaxTokens: 16e3,
|
|
24
24
|
summaryChunkTokens: 24e3,
|
|
25
25
|
summaryTimeoutMs: 18e4,
|
|
26
26
|
summaryRetries: 2,
|
|
@@ -37,7 +37,7 @@ var init_config = __esmMin((() => {
|
|
|
37
37
|
minMessagesBeforeCompact: z.number().int().min(2).default(10),
|
|
38
38
|
keepRecentTokens: z.number().int().min(1e3).default(2e4),
|
|
39
39
|
recentTurnsPreserve: z.number().int().min(1).max(12).default(3),
|
|
40
|
-
summaryMaxTokens: z.number().int().min(256).default(
|
|
40
|
+
summaryMaxTokens: z.number().int().min(256).default(16e3),
|
|
41
41
|
summaryChunkTokens: z.number().int().min(1e3).default(24e3),
|
|
42
42
|
summaryTimeoutMs: z.number().int().min(1e3).max(6e5).default(18e4),
|
|
43
43
|
summaryRetries: z.number().int().min(0).max(5).default(2),
|