@xopcai/xopc 0.0.246 → 0.0.248
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/src/update-offset-store.js +17 -54
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/auth/accounts.js +3 -5
- package/dist/extensions/weixin/src/monitor/monitor.js +3 -5
- package/dist/extensions/weixin/src/storage/sync-buf.d.ts +3 -6
- package/dist/extensions/weixin/src/storage/sync-buf.js +9 -22
- package/dist/gateway/static/root/assets/{activity-store-BlxqErph.js → activity-store-etpmyV7S.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CJJzpYYS.js → agent-avatar-dicebear-BmKxSM1k.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CUXApfcE.js +1 -0
- package/dist/gateway/static/root/assets/{agents-je3sRGmk.js → agents-DNq_GKuc.js} +1 -1
- package/dist/gateway/static/root/assets/{api-BbXzyQMj.js → api-B0-hLuZ1.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-Cnn3i00c.js → app-management-settings-panel-qfwAgyhQ.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-BToQaw_v.js → appearance-settings-DqQVUpCC.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-dwIqYmXk.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-DD2SweEH.js → archive-plugin-BnMSgZvR.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-BFtcib5t.js → attachment-load-CejsQMev.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-XS8wIl5o.js → automations-page-RC8EyoAf.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-SkdcSZ0i.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-Xs7pLHxR.js → binary-plugins-DGjppLSG.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BPdSzceB.js → block-editor-CWdP4bUc.js} +44 -44
- package/dist/gateway/static/root/assets/browser-settings-page-CKCa6TvG.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-BAAc151l.js → browser-workflow-inputs-BQ1Ilw_o.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DUPPvE30.js → browser-workflows-page-CJh4NyxT.js} +2 -2
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-cl9kYilL.js → capabilities-settings-panel-DSp--zIZ.js} +5 -5
- package/dist/gateway/static/root/assets/channels-settings-CMd2dDrI.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-CCBCtLDg.js → channels-status-swr-Ohhee4vm.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-DKW1M6aJ.js → chat-terminal-dock-BOtoKTK3.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-udWs5Kdm.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-Bijb0ZQu.js → cron-expression-DTj1V3Sw.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BZuHw-SY.js → date-picker-Yr6OCvGL.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-BsBD2JFY.js → dependency-picker-DpN3XZg9.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Ceuw3QKb.js → desktop-pet-DbGzggPF.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DctOXexM.js → desktop-pet-settings-DinCToZh.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BNlMPATK.js → extension-debug-page-DgTtk4KC.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CK4Uvzge.js → extension-page-DtQeiP6f.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CpnXXemw.js → extension-settings-page-DcguCgsH.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-C_mlpe-r.js → gateway-config-api-Br7lSf6H.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-826dipyU.js → gateway-config-swr-DXuXtU1w.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DSSW17ed.js → gateway-settings-CdPoDMuj.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DyvcAIMm.js → gateway-startup-retry-CzBzglzQ.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-hbmIZTpg.js → heartbeat-settings-DHk1hawP.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-YGipe_W6.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-D7cyfks6.js → image-generation-api-TIgsn04n.js} +1 -1
- package/dist/gateway/static/root/assets/{index-eZjksPvq.js → index-D5TQQpeb.js} +44 -44
- package/dist/gateway/static/root/assets/index-DReBaaTX.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BQrDwwgi.js → keyboard-shortcuts-settings-wsWuoa8p.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CpyvYyrb.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-D-YWD6LS.js → local-apps-page-CXrbrGo8.js} +1 -1
- package/dist/gateway/static/root/assets/local-context-graph-BjUf7fQ9.js +1 -0
- package/dist/gateway/static/root/assets/{locale-store-CBoCuIMx.js → locale-store-BJFLQY8O.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-DvLc9l59.js → logs-page-CXKy6E_l.js} +2 -2
- package/dist/gateway/static/root/assets/{management-settings-DsULLUUv.js → management-settings-BdJZFR7U.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-CjqlP6IB.js → markdown-split-NK3ACVG2.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-BXsHghJd.js → markdown-view-DTF9v1gg.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DQL029DU.js → media-plugins-F0jcUxyl.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CHNYp8EQ.js +3 -0
- package/dist/gateway/static/root/assets/{mobile-pairing-wizard-gauprAae.js → mobile-pairing-wizard-3NKCniSp.js} +1 -1
- package/dist/gateway/static/root/assets/models-hub-cache-nCfkBN8M.js +1 -0
- package/dist/gateway/static/root/assets/{notes-page-AsEfLZt9.js → notes-page-DuqLahi6.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-C7j9EdQk.js +5 -0
- package/dist/gateway/static/root/assets/{oauth-api-BjSUDIgq.js → oauth-api-8lP_qJpq.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-CAJeUXeU.js → product-open-page-CxGGlWA8.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-CfebYVX0.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-48GvzSVa.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-BhGKnvLP.js → registry-api-CIsNlSBi.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-64xj_s2m.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DH6EilMV.js → runtime-tools-settings-panel-YkjhiQfA.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-DYHmEZeZ.js → schema-form-oFGf3G3s.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CcwcdRN8.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BaN84CyW.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-BHwPd_M3.js → settings-page-C7VWs0IT.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DVVOCNbr.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-BjwrS03F.js → share-preview-page-t5oz18rh.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-DUYbYLi7.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BGyD0gB9.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-OHyK25op.js → skills-page-CjF8DTsN.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-DQx9ulmg.js → skills-page.utils-DEDTYs2W.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-wO7DWv4C.js → system-settings-panel-BSYuRgFI.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-YZYSTJH7.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-hybK3oC9.js → theme-store-O597U8q_.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-CVC8BHZu.js → tunnel-api-FKUi9wDL.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-DMvRu2XZ.js → use-autosave-B5eUJ6Zq.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-BCyiduKd.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-DuBK2NDG.js → voice-api-key-field-CMKSwz4C.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-CBbiF1T3.js → voice-config-api-q7B6fOFB.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-B7VXWpDr.js → work-discovery-overlay-jhT2EzeH.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BokVAsWN.js → workflow-run-setup-panel-DZmvLZjb.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DQC0TpMa.js +5 -0
- package/dist/gateway/static/root/index.html +12 -12
- package/dist/package.js +1 -1
- package/dist/src/agent/commands/command-registry.d.ts +1 -0
- package/dist/src/agent/commands/command-registry.js +12 -22
- package/dist/src/agent/ipc/inbox.d.ts +8 -31
- package/dist/src/agent/ipc/inbox.js +64 -133
- package/dist/src/agent/service/process-direct-one-shot.js +15 -10
- package/dist/src/agent/workflow/catalog.d.ts +1 -8
- package/dist/src/agent/workflow/catalog.js +44 -102
- package/dist/src/agent/workflow/index.d.ts +1 -1
- package/dist/src/agent/workflow/index.js +2 -2
- package/dist/src/automations/domain/types.d.ts +1 -0
- package/dist/src/automations/service/action-executor.js +2 -2
- package/dist/src/automations/service/automation-service.js +2 -2
- package/dist/src/channels/manager.d.ts +1 -1
- package/dist/src/channels/manager.js +2 -2
- package/dist/src/channels/outbound/persist-store.d.ts +2 -8
- package/dist/src/channels/outbound/persist-store.js +11 -38
- package/dist/src/channels/outbound-sender.d.ts +1 -1
- package/dist/src/channels/outbound-sender.js +2 -2
- package/dist/src/cli/commands/connectors.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/config/schema.js +2 -2
- package/dist/src/connectors/auth-provider-registry.js +1 -1
- package/dist/src/connectors/composio-triggers.d.ts +2 -2
- package/dist/src/connectors/composio-triggers.js +8 -15
- package/dist/src/connectors/connected-source-ingestion.js +1 -1
- package/dist/src/connectors/health.js +1 -1
- package/dist/src/gateway/automation-agent-session.js +3 -0
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +8 -25
- package/dist/src/gateway/hono/routes/capabilities.js +1 -1
- package/dist/src/gateway/hono/routes/connectors.js +3 -3
- package/dist/src/gateway/hono/routes/mcp.js +1 -1
- package/dist/src/gateway/hono/routes/projects.js +1 -1
- package/dist/src/gateway/hono/routes/you.js +20 -4
- package/dist/src/gateway/service.js +4 -5
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/notes/index.d.ts +1 -1
- package/dist/src/notes/index.js +2 -2
- package/dist/src/notes/paths.d.ts +0 -3
- package/dist/src/notes/paths.js +1 -10
- package/dist/src/notes/service.d.ts +0 -1
- package/dist/src/notes/service.js +0 -3
- package/dist/src/notes/store.d.ts +0 -2
- package/dist/src/notes/store.js +33 -80
- package/dist/src/share/hosted-session-share.d.ts +1 -4
- package/dist/src/share/hosted-session-share.js +14 -47
- package/dist/src/share/share-auto.d.ts +1 -1
- package/dist/src/share/share-auto.js +2 -2
- package/dist/src/share/share-store.d.ts +2 -7
- package/dist/src/share/share-store.js +153 -195
- package/dist/src/share/share-types.d.ts +0 -4
- package/dist/src/share/site-share-store.d.ts +3 -8
- package/dist/src/share/site-share-store.js +94 -153
- package/dist/src/share/site-share-types.d.ts +0 -4
- package/dist/src/storage/sqlite/connection.d.ts +1 -2
- package/dist/src/storage/sqlite/connection.js +50 -47
- package/dist/src/storage/sqlite/durable-queue.d.ts +16 -0
- package/dist/src/storage/sqlite/durable-queue.js +52 -0
- package/dist/src/storage/sqlite/durable-state.d.ts +16 -0
- package/dist/src/storage/sqlite/durable-state.js +43 -0
- package/dist/src/storage/sqlite/migrations/146_understanding_focus_exclusions.sql +9 -0
- package/dist/src/storage/sqlite/migrations/147_durable_application_state.sql +39 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/understanding-focus-exclusions.d.ts +2 -0
- package/dist/src/storage/sqlite/understanding-focus-exclusions.js +24 -0
- package/dist/src/tui/tui-scoped-models.js +9 -6
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/voice/dashscope/streaming-tts-stream.js +49 -0
- package/dist/src/voice/realtime/agentEngine.js +63 -18
- package/dist/src/voice/realtime/conversationTurn.d.ts +20 -0
- package/dist/src/voice/realtime/conversationTurn.js +83 -0
- package/dist/src/voice/realtime/omniEngine.js +72 -18
- package/dist/src/workflows/authoring/workflow-draft-store.d.ts +1 -5
- package/dist/src/workflows/authoring/workflow-draft-store.js +23 -43
- package/dist/src/workflows/index.js +2 -2
- package/dist/src/workflows/store/event-store.d.ts +1 -2
- package/dist/src/workflows/store/event-store.js +19 -64
- package/dist/src/workflows/store/paths.d.ts +0 -2
- package/dist/src/workflows/store/paths.js +1 -7
- package/dist/src/workflows/store/run-store.d.ts +0 -1
- package/dist/src/workflows/store/run-store.js +1 -24
- package/package.json +3 -3
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-0dRjnL2s.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-EpUZsl4h.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-BGQdHrip.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-DJGcm7rH.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-BcIr-_GM.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DNHqaZfX.js +0 -2
- package/dist/gateway/static/root/assets/home-page-CaVvW77l.js +0 -1
- package/dist/gateway/static/root/assets/index-Dbh5SXyV.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-D3K1XmOM.js +0 -2
- package/dist/gateway/static/root/assets/messages-BbdwoxVo.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-cache-88f4fzYS.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-CI30cDh3.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-jO_4I5zN.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-BrTGFME0.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CH70D5SH.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-hbfUNtNs.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-Vg3_jua6.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DkcpWSss.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-BL4DEt6p.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CafhNktn.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-anyomXsu.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-BBk9YdBn.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-RUTv0yvR.js +0 -5
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
CREATE TABLE durable_state (
|
|
2
|
+
namespace TEXT NOT NULL,
|
|
3
|
+
scope TEXT NOT NULL,
|
|
4
|
+
key TEXT NOT NULL,
|
|
5
|
+
payload TEXT NOT NULL CHECK(json_valid(payload)),
|
|
6
|
+
UNIQUE(namespace, scope, key)
|
|
7
|
+
);
|
|
8
|
+
CREATE TABLE workflow_events (
|
|
9
|
+
agent_id TEXT NOT NULL,
|
|
10
|
+
run_id TEXT NOT NULL,
|
|
11
|
+
sequence INTEGER NOT NULL CHECK(sequence > 0),
|
|
12
|
+
id TEXT NOT NULL UNIQUE,
|
|
13
|
+
payload TEXT NOT NULL CHECK(json_valid(payload)),
|
|
14
|
+
PRIMARY KEY(agent_id, run_id, sequence)
|
|
15
|
+
);
|
|
16
|
+
CREATE TABLE note_snapshots (
|
|
17
|
+
note_id TEXT NOT NULL REFERENCES notes(note_id) ON DELETE CASCADE,
|
|
18
|
+
timestamp INTEGER NOT NULL,
|
|
19
|
+
payload TEXT NOT NULL CHECK(json_valid(payload)),
|
|
20
|
+
PRIMARY KEY(note_id, timestamp)
|
|
21
|
+
);
|
|
22
|
+
CREATE TABLE durable_messages (
|
|
23
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
24
|
+
queue TEXT NOT NULL,
|
|
25
|
+
scope TEXT NOT NULL,
|
|
26
|
+
id TEXT NOT NULL,
|
|
27
|
+
payload TEXT NOT NULL CHECK(json_valid(payload)),
|
|
28
|
+
enqueued_at INTEGER NOT NULL,
|
|
29
|
+
processed_at INTEGER,
|
|
30
|
+
lease_token TEXT,
|
|
31
|
+
lease_until INTEGER,
|
|
32
|
+
UNIQUE(queue, scope, id)
|
|
33
|
+
);
|
|
34
|
+
CREATE INDEX durable_messages_pending ON durable_messages(queue, scope, processed_at, sequence);
|
|
35
|
+
|
|
36
|
+
CREATE UNIQUE INDEX durable_share_token ON durable_state(namespace, json_extract(payload, '$.token'))
|
|
37
|
+
WHERE namespace IN ('shares', 'site-shares');
|
|
38
|
+
CREATE UNIQUE INDEX durable_site_subdomain ON durable_state(json_extract(payload, '$.subdomain'))
|
|
39
|
+
WHERE namespace = 'site-shares' AND json_extract(payload, '$.subdomain') IS NOT NULL;
|
|
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
|
|
|
3
3
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
4
4
|
export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
5
5
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
6
|
-
export declare const XOPC_DB_SCHEMA_VERSION =
|
|
6
|
+
export declare const XOPC_DB_SCHEMA_VERSION = 147;
|
|
7
7
|
export declare function resolveMigrationsDir(override?: string): string;
|
|
8
8
|
/**
|
|
9
9
|
* Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
|
|
@@ -12,7 +12,7 @@ const log = createLogger("Sqlite:Migrations");
|
|
|
12
12
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
13
13
|
const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
14
14
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
15
|
-
const XOPC_DB_SCHEMA_VERSION =
|
|
15
|
+
const XOPC_DB_SCHEMA_VERSION = 147;
|
|
16
16
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
17
17
|
function backupBeforeTaskCutover(db, databasePath) {
|
|
18
18
|
db.exec("PRAGMA wal_checkpoint(FULL)");
|
|
@@ -57,7 +57,7 @@ function applySingleMigration(db, migration) {
|
|
|
57
57
|
* Each step runs in its own transaction and updates schema_meta on success.
|
|
58
58
|
*/
|
|
59
59
|
function applyPendingMigrations(db, options = {}) {
|
|
60
|
-
const targetVersion = options.targetVersion ??
|
|
60
|
+
const targetVersion = options.targetVersion ?? 147;
|
|
61
61
|
let currentVersion = readSchemaVersion(db);
|
|
62
62
|
if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
|
|
63
63
|
if (currentVersion >= targetVersion) return currentVersion;
|
|
@@ -94,7 +94,7 @@ function applyPendingMigrations(db, options = {}) {
|
|
|
94
94
|
}
|
|
95
95
|
/** Inspect schema version without mutating the database. */
|
|
96
96
|
function inspectSchemaMigrationStatus(db, options = {}) {
|
|
97
|
-
const appVersion = options.targetVersion ??
|
|
97
|
+
const appVersion = options.targetVersion ?? 147;
|
|
98
98
|
const dbVersion = readSchemaVersion(db);
|
|
99
99
|
if (dbVersion > appVersion) return {
|
|
100
100
|
dbVersion,
|
|
@@ -19,7 +19,7 @@ const log = createLogger('Sqlite:Migrations');
|
|
|
19
19
|
export const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
20
20
|
|
|
21
21
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
22
|
-
export const XOPC_DB_SCHEMA_VERSION =
|
|
22
|
+
export const XOPC_DB_SCHEMA_VERSION = 147;
|
|
23
23
|
|
|
24
24
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getSqliteDatabase } from "./transaction.js";
|
|
2
|
+
import { notifyUserContextChange } from "../../user-context/changes.js";
|
|
3
|
+
//#region src/storage/sqlite/understanding-focus-exclusions.ts
|
|
4
|
+
function listUnderstandingFocusExclusions() {
|
|
5
|
+
const rows = getSqliteDatabase().prepare("SELECT understanding_id, focus_id FROM understanding_focus_exclusions").all();
|
|
6
|
+
const result = /* @__PURE__ */ new Map();
|
|
7
|
+
for (const row of rows) {
|
|
8
|
+
const ids = result.get(row.understanding_id) ?? [];
|
|
9
|
+
ids.push(row.focus_id);
|
|
10
|
+
result.set(row.understanding_id, ids);
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
function setUnderstandingFocusExclusion(understandingId, focusId, excluded) {
|
|
15
|
+
const db = getSqliteDatabase();
|
|
16
|
+
if (excluded) db.prepare("INSERT OR IGNORE INTO understanding_focus_exclusions (understanding_id, focus_id, created_at) VALUES (?, ?, ?)").run(understandingId, focusId, Date.now());
|
|
17
|
+
else db.prepare("DELETE FROM understanding_focus_exclusions WHERE understanding_id = ? AND focus_id = ?").run(understandingId, focusId);
|
|
18
|
+
notifyUserContextChange({
|
|
19
|
+
kind: "understanding",
|
|
20
|
+
id: understandingId
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { listUnderstandingFocusExclusions, setUnderstandingFocusExclusion };
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
//#region src/tui/tui-scoped-models.ts
|
|
5
|
-
|
|
5
|
+
init_paths_state();
|
|
6
|
+
function storePath() {
|
|
7
|
+
return join(resolveStateDir(), "tui-scoped-models.json");
|
|
8
|
+
}
|
|
6
9
|
function normalizeWorkspaceKey(cwd) {
|
|
7
10
|
return cwd.replace(/\\/g, "/").replace(/\/+$/, "") || "/";
|
|
8
11
|
}
|
|
9
12
|
function readStore() {
|
|
10
13
|
try {
|
|
11
|
-
if (!existsSync(
|
|
12
|
-
const raw = readFileSync(
|
|
14
|
+
if (!existsSync(storePath())) return {};
|
|
15
|
+
const raw = readFileSync(storePath(), "utf8");
|
|
13
16
|
const parsed = JSON.parse(raw);
|
|
14
17
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
15
18
|
} catch {
|
|
@@ -17,9 +20,9 @@ function readStore() {
|
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
22
|
function writeStore(data) {
|
|
20
|
-
const dir =
|
|
23
|
+
const dir = resolveStateDir();
|
|
21
24
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
22
|
-
writeFileSync(
|
|
25
|
+
writeFileSync(storePath(), `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
23
26
|
}
|
|
24
27
|
/** Load scoped model refs for Ctrl+P cycling (`null` = all models). */
|
|
25
28
|
function loadScopedModelRefs(cwd = process.cwd()) {
|
|
@@ -5,9 +5,9 @@ import { resolveBootstrapFilesSync } from "../agent/bootstrap/bootstrap-files.js
|
|
|
5
5
|
import { createSkillConfigManager, isSkillEnabled } from "../agent/skills/config.js";
|
|
6
6
|
import { loadSkills } from "../agent/skills/index.js";
|
|
7
7
|
import { createWorkflowCatalog } from "../agent/workflow/catalog.js";
|
|
8
|
-
import { listConnectorInstances } from "../connectors/instances.js";
|
|
9
8
|
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
10
9
|
import "../config/index.js";
|
|
10
|
+
import { listConnectorInstances } from "../connectors/instances.js";
|
|
11
11
|
import { basename } from "node:path";
|
|
12
12
|
//#region src/tui/tui-startup-resources.ts
|
|
13
13
|
init_paths();
|
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
import { createLogger } from "../../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../../utils/logger.js";
|
|
1
3
|
import { createRequire } from "node:module";
|
|
2
4
|
import crypto from "node:crypto";
|
|
5
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
3
6
|
//#region src/voice/dashscope/streaming-tts-stream.ts
|
|
7
|
+
init_logger();
|
|
4
8
|
const { WebSocket } = createRequire(import.meta.url)("ws");
|
|
5
9
|
const DEFAULT_REALTIME_URL = "wss://dashscope.aliyuncs.com/api-ws/v1/realtime";
|
|
10
|
+
const log = createLogger("TTS:DashScope");
|
|
11
|
+
var TtsHandshakeError = class extends Error {
|
|
12
|
+
constructor(statusCode, retryAfterMs) {
|
|
13
|
+
super(`Realtime TTS WebSocket handshake failed (HTTP ${statusCode})${retryAfterMs === void 0 ? "" : `; retry after ${retryAfterMs} ms`}`);
|
|
14
|
+
this.statusCode = statusCode;
|
|
15
|
+
this.retryAfterMs = retryAfterMs;
|
|
16
|
+
this.name = "TtsHandshakeError";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
function parseRetryAfter(value) {
|
|
20
|
+
if (!value?.trim()) return void 0;
|
|
21
|
+
const seconds = Number(value);
|
|
22
|
+
if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
|
|
23
|
+
const timestamp = Date.parse(value);
|
|
24
|
+
return Number.isFinite(timestamp) ? Math.max(0, timestamp - Date.now()) : void 0;
|
|
25
|
+
}
|
|
6
26
|
function realtimeUrl(baseUrl, model) {
|
|
7
27
|
const configured = baseUrl ? new URL(baseUrl) : new URL(DEFAULT_REALTIME_URL);
|
|
8
28
|
const wasWebSocket = configured.protocol === "ws:" || configured.protocol === "wss:";
|
|
@@ -26,6 +46,31 @@ function event(type, extra = {}) {
|
|
|
26
46
|
});
|
|
27
47
|
}
|
|
28
48
|
async function openDashScopeStreamingTts(request) {
|
|
49
|
+
const deadline = Date.now() + request.timeoutMs;
|
|
50
|
+
for (let attempt = 1;; attempt += 1) {
|
|
51
|
+
request.signal.throwIfAborted();
|
|
52
|
+
try {
|
|
53
|
+
return await openStreamingTtsAttempt({
|
|
54
|
+
...request,
|
|
55
|
+
timeoutMs: Math.max(1, deadline - Date.now())
|
|
56
|
+
});
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if (request.signal.aborted) throw error;
|
|
59
|
+
if (!(error instanceof TtsHandshakeError) || error.statusCode !== 429 || attempt >= 3) throw error;
|
|
60
|
+
const delayMs = Math.max(error.retryAfterMs ?? 0, 500 * 2 ** (attempt - 1) + Math.floor(Math.random() * 250));
|
|
61
|
+
if (delayMs > 5e3 || Date.now() + delayMs >= deadline) throw error;
|
|
62
|
+
log.warn({
|
|
63
|
+
model: request.model,
|
|
64
|
+
statusCode: error.statusCode,
|
|
65
|
+
attempt,
|
|
66
|
+
delayMs
|
|
67
|
+
}, "Realtime TTS handshake rate limited; retrying");
|
|
68
|
+
await setTimeout$1(delayMs, void 0, { signal: request.signal });
|
|
69
|
+
if (Date.now() >= deadline) throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function openStreamingTtsAttempt(request) {
|
|
29
74
|
if (!request.apiKey) throw new Error("DashScope TTS API key is unavailable");
|
|
30
75
|
if (request.signal.aborted) throw request.signal.reason;
|
|
31
76
|
const socket = new WebSocket(realtimeUrl(request.baseUrl, request.model), {
|
|
@@ -72,6 +117,10 @@ async function openDashScopeStreamingTts(request) {
|
|
|
72
117
|
else if (socket.readyState === WebSocket.CONNECTING) socket.terminate();
|
|
73
118
|
};
|
|
74
119
|
request.signal.addEventListener("abort", onAbort, { once: true });
|
|
120
|
+
socket.on("unexpected-response", (_request, response) => {
|
|
121
|
+
fail(new TtsHandshakeError(response.statusCode ?? 0, parseRetryAfter(response.headers["retry-after"])));
|
|
122
|
+
response.destroy();
|
|
123
|
+
});
|
|
75
124
|
socket.on("message", (data, isBinary) => {
|
|
76
125
|
if (streamClosed || request.signal.aborted) return;
|
|
77
126
|
if (isBinary) return;
|
|
@@ -2,6 +2,7 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { speakStream } from "../tts/speak-core.js";
|
|
4
4
|
import { AudioPlaybackWindow } from "./audio-playback-window.js";
|
|
5
|
+
import { ConversationTurn } from "./conversationTurn.js";
|
|
5
6
|
import { SpeakableSegmenter } from "./speakable-segmenter.js";
|
|
6
7
|
import crypto from "node:crypto";
|
|
7
8
|
//#region src/voice/realtime/agentEngine.ts
|
|
@@ -29,6 +30,32 @@ function createAgentVoiceEngine(options) {
|
|
|
29
30
|
let finalCount = 0;
|
|
30
31
|
let committing = false;
|
|
31
32
|
const finalizedUtterances = /* @__PURE__ */ new Set();
|
|
33
|
+
let pendingTurn;
|
|
34
|
+
const turn = new ConversationTurn(claim.silenceDurationMs, (text) => {
|
|
35
|
+
if (closed || muted) return;
|
|
36
|
+
if (queuedTurns >= 8) {
|
|
37
|
+
send("session.error", {
|
|
38
|
+
code: "INPUT_BACKPRESSURE",
|
|
39
|
+
message: "Too many queued voice turns",
|
|
40
|
+
recoverable: false
|
|
41
|
+
});
|
|
42
|
+
options.onClose("input_backpressure", true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
queuedTurns += 1;
|
|
46
|
+
const generation = inputGeneration;
|
|
47
|
+
const pending = {
|
|
48
|
+
text,
|
|
49
|
+
cancelled: false
|
|
50
|
+
};
|
|
51
|
+
pendingTurn = pending;
|
|
52
|
+
conversationTail = conversationTail.then(() => {
|
|
53
|
+
if (pendingTurn === pending) pendingTurn = void 0;
|
|
54
|
+
if (generation === inputGeneration && !pending.cancelled) return runConversationTurn(text);
|
|
55
|
+
}).finally(() => {
|
|
56
|
+
if (generation === inputGeneration) queuedTurns -= 1;
|
|
57
|
+
});
|
|
58
|
+
});
|
|
32
59
|
function cancelActiveResponse(reason) {
|
|
33
60
|
const response = activeResponse;
|
|
34
61
|
if (!response) return false;
|
|
@@ -238,10 +265,23 @@ function createAgentVoiceEngine(options) {
|
|
|
238
265
|
}
|
|
239
266
|
});
|
|
240
267
|
}
|
|
268
|
+
function bufferFinal(utteranceId, text) {
|
|
269
|
+
try {
|
|
270
|
+
turn.final(utteranceId, text);
|
|
271
|
+
} catch {
|
|
272
|
+
send("session.error", {
|
|
273
|
+
code: "INPUT_BACKPRESSURE",
|
|
274
|
+
message: "Voice turn input limit reached",
|
|
275
|
+
recoverable: false
|
|
276
|
+
});
|
|
277
|
+
options.onClose("input_backpressure", true);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
241
280
|
function onSttEvent(event) {
|
|
242
281
|
if (closed) return;
|
|
243
282
|
if (event.type === "ready" || event.type === "usage") return;
|
|
244
283
|
if (event.type === "error") {
|
|
284
|
+
turn.reset();
|
|
245
285
|
log.warn({
|
|
246
286
|
err: event.error,
|
|
247
287
|
sessionId: claim.sessionId,
|
|
@@ -257,10 +297,21 @@ function createAgentVoiceEngine(options) {
|
|
|
257
297
|
}
|
|
258
298
|
if (muted || finalizedUtterances.has(event.utteranceId)) return;
|
|
259
299
|
if (event.type === "speech_started") {
|
|
300
|
+
if (claim.request.purpose === "conversation") {
|
|
301
|
+
if (pendingTurn) {
|
|
302
|
+
pendingTurn.cancelled = true;
|
|
303
|
+
turn.restore(pendingTurn.text);
|
|
304
|
+
pendingTurn = void 0;
|
|
305
|
+
}
|
|
306
|
+
turn.start(event.utteranceId);
|
|
307
|
+
}
|
|
260
308
|
if (claim.request.purpose === "conversation" && claim.config.voice?.realtime?.bargeIn && !activeResponse?.awaitingClarification) cancelActiveResponse("barge_in");
|
|
261
309
|
send("input.speech_started", { utteranceId: event.utteranceId });
|
|
262
310
|
}
|
|
263
|
-
if (event.type === "speech_stopped")
|
|
311
|
+
if (event.type === "speech_stopped") {
|
|
312
|
+
if (claim.request.purpose === "conversation") turn.stop(event.utteranceId);
|
|
313
|
+
send("input.speech_stopped", { utteranceId: event.utteranceId });
|
|
314
|
+
}
|
|
264
315
|
if (event.type === "transcript_delta") send("input.transcript.delta", {
|
|
265
316
|
utteranceId: event.utteranceId,
|
|
266
317
|
revision: event.revision,
|
|
@@ -268,7 +319,10 @@ function createAgentVoiceEngine(options) {
|
|
|
268
319
|
});
|
|
269
320
|
if (event.type === "transcript_final") {
|
|
270
321
|
const text = event.text.trim();
|
|
271
|
-
if (!text)
|
|
322
|
+
if (!text) {
|
|
323
|
+
if (claim.request.purpose === "conversation") bufferFinal(event.utteranceId, "");
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
272
326
|
if (finalizedUtterances.size >= 1e4) {
|
|
273
327
|
options.onClose("utterance_limit", true);
|
|
274
328
|
return;
|
|
@@ -282,28 +336,18 @@ function createAgentVoiceEngine(options) {
|
|
|
282
336
|
...event.language === "zh" || event.language === "en" ? { language: event.language } : {}
|
|
283
337
|
});
|
|
284
338
|
if (claim.request.purpose === "conversation") {
|
|
285
|
-
if (activeResponse?.awaitingClarification)
|
|
286
|
-
|
|
287
|
-
if (queuedTurns >= 8) {
|
|
288
|
-
send("session.error", {
|
|
289
|
-
code: "INPUT_BACKPRESSURE",
|
|
290
|
-
message: "Too many queued voice turns",
|
|
291
|
-
recoverable: false
|
|
292
|
-
});
|
|
293
|
-
options.onClose("input_backpressure", true);
|
|
339
|
+
if (activeResponse?.awaitingClarification) {
|
|
340
|
+
turn.reset();
|
|
294
341
|
return;
|
|
295
342
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
conversationTail = conversationTail.then(() => {
|
|
299
|
-
if (generation === inputGeneration) return runConversationTurn(text);
|
|
300
|
-
}).finally(() => {
|
|
301
|
-
if (generation === inputGeneration) queuedTurns -= 1;
|
|
302
|
-
});
|
|
343
|
+
if (claim.config.voice?.realtime?.bargeIn) cancelActiveResponse("barge_in");
|
|
344
|
+
bufferFinal(event.utteranceId, text);
|
|
303
345
|
}
|
|
304
346
|
}
|
|
305
347
|
}
|
|
306
348
|
function discardInput() {
|
|
349
|
+
turn.reset();
|
|
350
|
+
pendingTurn = void 0;
|
|
307
351
|
inputGeneration += 1;
|
|
308
352
|
queuedTurns = 0;
|
|
309
353
|
bufferedAudio = [];
|
|
@@ -387,6 +431,7 @@ function createAgentVoiceEngine(options) {
|
|
|
387
431
|
close() {
|
|
388
432
|
if (closing) return closing;
|
|
389
433
|
closed = true;
|
|
434
|
+
turn.reset();
|
|
390
435
|
cancelActiveResponse("session_closed");
|
|
391
436
|
sttAbort.abort("session_closed");
|
|
392
437
|
sttSession?.abort("session_closed");
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Conservative continuation hints, not a semantic model or punctuation-based endpoint detector. */
|
|
2
|
+
export declare function needsContinuation(text: string): boolean;
|
|
3
|
+
/** Joins provider utterances until both transcription and the continuation window have settled. */
|
|
4
|
+
export declare class ConversationTurn {
|
|
5
|
+
private readonly silenceDurationMs;
|
|
6
|
+
private readonly onTurn;
|
|
7
|
+
private readonly parts;
|
|
8
|
+
private timer;
|
|
9
|
+
private stoppedAt;
|
|
10
|
+
constructor(silenceDurationMs: number, onTurn: (text: string) => void);
|
|
11
|
+
start(id: string): void;
|
|
12
|
+
stop(id: string): void;
|
|
13
|
+
final(id: string, text: string): void;
|
|
14
|
+
reset(): void;
|
|
15
|
+
/** Restore a settled turn if generation was still queued when the user resumed. */
|
|
16
|
+
restore(text: string): void;
|
|
17
|
+
private text;
|
|
18
|
+
private clearTimer;
|
|
19
|
+
private schedule;
|
|
20
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/voice/realtime/conversationTurn.ts
|
|
2
|
+
const MIN_TURN_SILENCE_MS = 1200;
|
|
3
|
+
const FINAL_SETTLE_MS = 350;
|
|
4
|
+
const INCOMPLETE_HOLD_MS = 1800;
|
|
5
|
+
/** Conservative continuation hints, not a semantic model or punctuation-based endpoint detector. */
|
|
6
|
+
function needsContinuation(text) {
|
|
7
|
+
const tail = text.trim().replace(/[\s,。!?、;:,.!?;:]+$/u, "");
|
|
8
|
+
return /(?:…|\.\.\.)[\s,。!?,.!?]*$/u.test(text) || /(?:因为|但是|然后|而且|如果|所以|比如|或者|还有|我想|我要|我觉得|帮我|帮我查一下|帮我查查|请帮我|就是说|那个|这个|呃|嗯)$/u.test(tail) || /\b(?:because|but|and|or|if|so|then|um|uh|i want to|i would like to|can you|could you|let me)\s*$/iu.test(tail);
|
|
9
|
+
}
|
|
10
|
+
/** Joins provider utterances until both transcription and the continuation window have settled. */
|
|
11
|
+
var ConversationTurn = class {
|
|
12
|
+
parts = /* @__PURE__ */ new Map();
|
|
13
|
+
timer;
|
|
14
|
+
stoppedAt = 0;
|
|
15
|
+
constructor(silenceDurationMs, onTurn) {
|
|
16
|
+
this.silenceDurationMs = silenceDurationMs;
|
|
17
|
+
this.onTurn = onTurn;
|
|
18
|
+
}
|
|
19
|
+
start(id) {
|
|
20
|
+
if (this.parts.has(id)) return;
|
|
21
|
+
this.clearTimer();
|
|
22
|
+
this.parts.set(id, { stopped: false });
|
|
23
|
+
}
|
|
24
|
+
stop(id) {
|
|
25
|
+
const part = this.parts.get(id);
|
|
26
|
+
if (part?.stopped) return;
|
|
27
|
+
this.parts.set(id, {
|
|
28
|
+
...part,
|
|
29
|
+
stopped: true
|
|
30
|
+
});
|
|
31
|
+
this.stoppedAt = Date.now();
|
|
32
|
+
this.schedule();
|
|
33
|
+
}
|
|
34
|
+
final(id, text) {
|
|
35
|
+
const part = this.parts.get(id);
|
|
36
|
+
if (part?.text !== void 0) return;
|
|
37
|
+
if (!part?.stopped) this.stoppedAt = Date.now();
|
|
38
|
+
this.parts.set(id, {
|
|
39
|
+
text: text.trim(),
|
|
40
|
+
stopped: true
|
|
41
|
+
});
|
|
42
|
+
if (this.parts.size > 256 || this.text().length > 32e3) {
|
|
43
|
+
this.reset();
|
|
44
|
+
throw new Error("Voice turn input limit reached");
|
|
45
|
+
}
|
|
46
|
+
this.schedule();
|
|
47
|
+
}
|
|
48
|
+
reset() {
|
|
49
|
+
this.clearTimer();
|
|
50
|
+
this.parts.clear();
|
|
51
|
+
}
|
|
52
|
+
/** Restore a settled turn if generation was still queued when the user resumed. */
|
|
53
|
+
restore(text) {
|
|
54
|
+
this.parts.set("queued-turn", {
|
|
55
|
+
text,
|
|
56
|
+
stopped: true
|
|
57
|
+
});
|
|
58
|
+
this.clearTimer();
|
|
59
|
+
}
|
|
60
|
+
text() {
|
|
61
|
+
return [...this.parts.values()].map((part) => part.text ?? "").filter(Boolean).join(" ");
|
|
62
|
+
}
|
|
63
|
+
clearTimer() {
|
|
64
|
+
clearTimeout(this.timer);
|
|
65
|
+
this.timer = void 0;
|
|
66
|
+
}
|
|
67
|
+
schedule() {
|
|
68
|
+
this.clearTimer();
|
|
69
|
+
if ([...this.parts.values()].some((part) => !part.stopped || part.text === void 0)) return;
|
|
70
|
+
const text = this.text();
|
|
71
|
+
if (!text) {
|
|
72
|
+
this.reset();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const holdMs = Math.max(FINAL_SETTLE_MS, MIN_TURN_SILENCE_MS - this.silenceDurationMs, needsContinuation(text) ? INCOMPLETE_HOLD_MS : 0);
|
|
76
|
+
this.timer = setTimeout(() => {
|
|
77
|
+
this.reset();
|
|
78
|
+
this.onTurn(text);
|
|
79
|
+
}, Math.max(FINAL_SETTLE_MS, this.stoppedAt + holdMs - Date.now()));
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
83
|
+
export { ConversationTurn, needsContinuation };
|