@xopcai/xopc 0.0.264 → 0.0.266
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/dist/assets/auth-CknJ00ae.js +5844 -0
- package/dist/browser-ext/dist/assets/sidepanel-C69P3v9u.css +113 -0
- package/dist/browser-ext/dist/background.js +200 -68
- package/dist/browser-ext/dist/sidepanel.html +14 -0
- package/dist/browser-ext/dist/sidepanel.js +18832 -0
- package/dist/browser-ext/manifest.json +20 -20
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-BYBCpt7_.js → activity-store-Bhyy6ENz.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-D20aBHPJ.js → agent-avatar-dicebear-Qrp5ALCF.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-BZvMqNrU.js → agent-defaults-settings-panel-DwinST48.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-6foBELwt.js → agents-Dlr0YyNt.js} +1 -1
- package/dist/gateway/static/root/assets/{api-YbtjDbuG.js → api-B2y7ZjZk.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-4ps1RrDU.js → app-management-settings-panel-bLNvz93c.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-C7nBHnkG.js → appearance-settings-D5qgIepF.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-B_g-rL5b.js → apps-page-BQVlXhIb.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-DfKK1iJO.js → archive-plugin-BEA7VAA4.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-BOU1pdnQ.js → attachment-load-B1RyF3uu.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BePzexAH.js → automations-page-BfH0FdKa.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-7-m5pBEZ.js → automations-workspace-C37AlD3E.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-Cly8XDyt.js → binary-plugins-EU884ZXi.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DzSu62js.js → block-editor-Bjr3naHb.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automation-inputs-8bHj7Fv2.js → browser-automation-inputs-s5I78Iko.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-CzL7Aj2k.js → browser-automations-page-CDrYrNGy.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-Dum3mTiz.js → browser-settings-page-DOmUkj2k.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-Ci6qVS-O.js → capabilities-settings-panel-slt1o04n.js} +2 -2
- package/dist/gateway/static/root/assets/{channels-settings-BOGEZnSv.js → channels-settings-oHTTX6Jy.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-BR8oQ_eP.js → channels-status-swr-_OsWr_vS.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BF9ZXa5Z.js → chat-terminal-dock-DEYQdv6n.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-DBvEvupa.js → connectors-page-olrbxHIT.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-expression-BszT_gjK.js → cron-expression-DFrbDWpP.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-D2MKBJ0G.js → date-picker-CYriYKpH.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-DqigBx-G.js → dependency-picker-XY3qUErs.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-CapspBGG.js → desktop-pet-Dsc__ynA.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DMPk4CaK.js → desktop-pet-settings-EpuX3C08.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CXLsDtrW.js → extension-debug-page-B_NeLV4K.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-B2j87ROw.js → extension-page-D3JC6mLB.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-t1BApw-u.js → extension-settings-page-CXTQt1lp.js} +1 -1
- package/dist/gateway/static/root/assets/{files-BArWTfr7.js → files-Be5viEFY.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-BFSesvAC.js → gateway-config-swr-OObCK8jM.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-BFAecoGy.js → gateway-settings-yeYm_UPE.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-D1giYgI-.js → gateway-startup-retry-D_TxKN_A.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-CyD9zDcU.js → heartbeat-settings-coh1LFsg.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-uItZMiBE.js → home-page-CAgoBZqp.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-BeB-OPqO.js → image-generation-api-fPU9yGsw.js} +1 -1
- package/dist/gateway/static/root/assets/index-Cn__9Un2.js +74 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Q_CM-ZCs.js → keyboard-shortcuts-settings-Cu1bI3Bg.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-DaiBWfOt.js → local-app-workbench-page-C9s2lFaI.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-BALMNCSp.js → local-apps-page-CJ03Umjr.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-RJHYFoq9.js → locale-store-DFQX9kTl.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-C-TS7oFg.js → logs-page-CY_DQKJ2.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-BajkJeYl.js → management-settings-YPEemeMo.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-BxoQJqHx.js → markdown-view-D-5jHRWg.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-C_8Hl6KG.js → media-plugins-BjT6jlrA.js} +1 -1
- package/dist/gateway/static/root/assets/{messages-Cf1h5WXB.js → messages-Dj8QuS6e.js} +2 -2
- package/dist/gateway/static/root/assets/{mobile-pairing-wizard-CsWIZrZW.js → mobile-pairing-wizard-A8eLtV6v.js} +1 -1
- package/dist/gateway/static/root/assets/{note-detail-panel-CCbPg_GP.js → note-detail-panel-DHT2QksJ.js} +3 -3
- package/dist/gateway/static/root/assets/{notes-page-BdxxcUKa.js → notes-page-BRFQiivM.js} +1 -1
- package/dist/gateway/static/root/assets/{page-tabs-BMYQef5D.js → page-tabs-DNUwulnl.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-CKZ-H5hJ.js → preview-open-alternatives-B33KsKkJ.js} +1 -1
- package/dist/gateway/static/root/assets/{product-delivery-CV4pDOtG.js → product-delivery-CCC4FJ3Y.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-zXJIptXs.js → product-open-page-CIGLPFm7.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-DRhhxhZB.js → project-detail-page-CItEFVt9.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-Wt7gF3Sx.js → projects-page-Bmy-c_lL.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-BSfFaxVN.js → registry-api-CsZLatKo.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-B6de5Zrb.js → remote-access-hub-H6B1cA2V.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DcUB5h1f.js → runtime-tools-settings-panel-BsCovC39.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-CquWhe7r.js → schema-form-NsPb_Vam.js} +1 -1
- package/dist/gateway/static/root/assets/{schemas-BHS7bo06.js → schemas-BaskVM5g.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-BNWO2EVF.js → sessions-page-CyYLSXk_.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-3T4rPk4A.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-DwswAefc.js → settings-form-section-BzPIPe1-.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-CoAVmjjs.js → settings-page-4idpMhsw.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-C9EIcWtH.js → setup-status-panel-D2ds_TTD.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-DWwy_4zh.js → share-preview-page-Djo3VTaC.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-CIUvq27-.js → shares-settings-fhRzNfRp.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-Ct8tUju_.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-CqsgVtVh.js → skills-page-riM7FytZ.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-B-N73248.js → skills-page.utils-B3G8LBb-.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-BndjXuBZ.js → system-settings-panel-CW91jjnB.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-CG6Ha9t7.js → task-detail-page-BBXKvl0k.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-C5ssn64t.js → theme-store-zRT6vaZc.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-BxZdcp3h.js → tunnel-api-DILER0Yb.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-mj9CUuz1.js → use-autosave-GxnP8vLO.js} +1 -1
- package/dist/gateway/static/root/assets/{user-model-page-DKeHMXI4.js → user-model-page-I1H4XRfA.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CzxVMYlr.js → voice-api-key-field-CI3sXyl4.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-COA0V1cK.js → voice-config-api-DpJEu2RQ.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-DMiPK8dp.js → work-discovery-overlay-DZC9Exn3.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C82OXCJK.js → workflow-run-setup-panel-CaBaQER2.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-HLCUV3rQ.js → workflows-page-C-_Dxihw.js} +1 -1
- package/dist/gateway/static/root/index.html +12 -12
- package/dist/package.js +1 -1
- package/dist/packages/browser-control-contract/src/index.js +14 -0
- package/dist/packages/endpoint-tools-protocol/src/index.js +2 -1
- package/dist/packages/gateway-contract/src/browser-page-context.js +43 -0
- package/dist/packages/gateway-contract/src/browser-tab-binding.js +29 -0
- package/dist/packages/gateway-contract/src/device-pairing.js +18 -2
- package/dist/packages/realtime-protocol/src/index.js +1 -0
- package/dist/packages/realtime-protocol/src/voice-audio.js +70 -9
- package/dist/packages/realtime-protocol/src/voice.js +65 -17
- package/dist/src/agent/agent-manager.js +4 -4
- package/dist/src/agent/background-review/run-background-review.js +1 -1
- package/dist/src/agent/embedded/model-runtime.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +1 -1
- package/dist/src/agent/image/tool-model-config.js +1 -1
- package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
- package/dist/src/agent/service.js +2 -2
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/source-context/browser-page.d.ts +3 -0
- package/dist/src/agent/source-context/browser-page.js +39 -0
- package/dist/src/agent/source-context/injector.js +9 -2
- package/dist/src/agent/source-context/types.d.ts +7 -1
- package/dist/src/agent/source-context/types.js +4 -1
- package/dist/src/agent/tasks/task-judge-service.js +3 -3
- package/dist/src/agent/tools/factory.js +9 -1
- package/dist/src/ai-assist/text-assist.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/oauth/xopc-cloud.js +1 -1
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +2 -2
- package/dist/src/browser/automations/schema.d.ts +1 -1
- package/dist/src/browser/automations/service.d.ts +1 -1
- package/dist/src/browser/native-messaging-host.d.ts +15 -0
- package/dist/src/browser/native-messaging-host.js +105 -0
- package/dist/src/browser/providers/browser-ext-install.d.ts +17 -1
- package/dist/src/browser/providers/browser-ext-install.js +82 -16
- package/dist/src/browser/providers/extension.d.ts +4 -0
- package/dist/src/browser/providers/extension.js +104 -38
- package/dist/src/browser/runtime/browser-runtime.d.ts +2 -1
- package/dist/src/browser/runtime/browser-runtime.js +6 -2
- package/dist/src/cli/commands/browser.js +13 -3
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/config/index.js +4 -4
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/endpoint-tools/runtime.js +2 -0
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/chat-stream/mapper.js +3 -2
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/hono/app.js +19 -3
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/middleware/auth.d.ts +4 -1
- package/dist/src/gateway/hono/middleware/auth.js +12 -1
- package/dist/src/gateway/hono/routes/browser-install.js +1 -1
- package/dist/src/gateway/hono/routes/browser.js +106 -7
- package/dist/src/gateway/hono/routes/devices.js +36 -3
- package/dist/src/gateway/hono/routes/endpoint-tools.js +15 -0
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/session-input-handler.d.ts +20 -2
- package/dist/src/gateway/hono/routes/session-input-handler.js +18 -0
- package/dist/src/gateway/hono/routes/sessions.js +12 -6
- package/dist/src/gateway/hono/routes/voice.js +5 -4
- package/dist/src/gateway/security/gateway-scopes.d.ts +1 -0
- package/dist/src/gateway/security/gateway-scopes.js +10 -1
- package/dist/src/gateway/security/origin-check.d.ts +1 -0
- package/dist/src/gateway/security/origin-check.js +5 -1
- package/dist/src/gateway/service/agent-runner.js +2 -1
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service/session-input-coordinator.d.ts +1 -0
- package/dist/src/gateway/service/session-input-coordinator.js +5 -4
- package/dist/src/gateway/service.js +22 -21
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/providers/register-runtime-providers.js +1 -1
- package/dist/src/realtime/runtime.js +2 -1
- package/dist/src/session/client-history.d.ts +4 -1
- package/dist/src/session/client-history.js +6 -3
- package/dist/src/storage/sqlite/browser-tab-binding-repository.d.ts +7 -0
- package/dist/src/storage/sqlite/browser-tab-binding-repository.js +60 -0
- package/dist/src/storage/sqlite/device-access-repository.d.ts +3 -1
- package/dist/src/storage/sqlite/device-access-repository.js +4 -3
- package/dist/src/storage/sqlite/device-pairing-approval.js +6 -4
- package/dist/src/storage/sqlite/device-pairing-repository.d.ts +1 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -0
- package/dist/src/storage/sqlite/index.js +2 -1
- package/dist/src/storage/sqlite/migrations/155_browser_extension.sql +120 -0
- package/dist/src/storage/sqlite/migrations/156_browser_tab_bindings.sql +14 -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/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/voice/realtime/agentBroker.d.ts +54 -0
- package/dist/src/voice/realtime/agentBroker.js +116 -0
- package/dist/src/voice/realtime/agentEngine.js +62 -15
- package/dist/src/voice/realtime/engine.d.ts +2 -1
- package/dist/src/voice/realtime/omniEngine.js +36 -7
- package/dist/src/voice/realtime/pcmFrameBuffer.d.ts +6 -0
- package/dist/src/voice/realtime/pcmFrameBuffer.js +29 -0
- package/dist/src/voice/realtime/runtime.js +97 -21
- package/dist/src/voice/realtime/runtime.types.d.ts +5 -21
- package/dist/src/voice/realtime/turnPolicy.d.ts +36 -0
- package/dist/src/voice/realtime/turnPolicy.js +134 -0
- package/dist/src/work-discovery/service.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +2 -2
- package/dist/browser-ext/dist/content.js +0 -191
- package/dist/browser-ext/dist/popup.js +0 -32
- package/dist/browser-ext/popup.html +0 -37
- package/dist/gateway/static/root/assets/index-DQtjs2x3.js +0 -74
- package/dist/gateway/static/root/assets/settings-advanced-gate-DK1yTYE4.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DfE3zFVw.js +0 -1
- package/dist/src/voice/realtime/conversationTurn.d.ts +0 -20
- package/dist/src/voice/realtime/conversationTurn.js +0 -83
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
2
2
|
import { buildDevicePairingProof, devicePairingCompleteSchema, devicePairingDeviceSchema } from "../../../packages/gateway-contract/src/device-pairing.js";
|
|
3
|
-
import { DEFAULT_MOBILE_SCOPES } from "../../gateway/security/gateway-scopes.js";
|
|
3
|
+
import { DEFAULT_BROWSER_EXTENSION_SCOPES, DEFAULT_MOBILE_SCOPES } from "../../gateway/security/gateway-scopes.js";
|
|
4
4
|
import { createDevice, getDevice, registerInitialDeviceRefreshToken, revokeDevice } from "./device-access-repository.js";
|
|
5
5
|
import { getOrCreateGatewayIdentity } from "./gateway-identity-repository.js";
|
|
6
6
|
import crypto from "node:crypto";
|
|
@@ -19,6 +19,7 @@ const hash = (value) => crypto.createHash("sha256").update(value).digest("hex");
|
|
|
19
19
|
const fail = (code, status) => {
|
|
20
20
|
throw new DevicePairingError(code, status);
|
|
21
21
|
};
|
|
22
|
+
const scopesForPlatform = (platform) => platform === "chrome" ? DEFAULT_BROWSER_EXTENSION_SCOPES : DEFAULT_MOBILE_SCOPES;
|
|
22
23
|
function requestRow(id, now) {
|
|
23
24
|
const db = getSqliteDatabase();
|
|
24
25
|
db.prepare(`UPDATE device_pairing_requests SET status = 'expired', revision = revision + 1
|
|
@@ -133,9 +134,10 @@ function operateDevicePairingRequest(action, body, now = Date.now()) {
|
|
|
133
134
|
return;
|
|
134
135
|
}
|
|
135
136
|
if (current.status !== "approved") fail("PAIRING_NOT_APPROVED");
|
|
137
|
+
const device = devicePairingDeviceSchema.parse(JSON.parse(current.device_json));
|
|
136
138
|
const created = createDevice({
|
|
137
|
-
...
|
|
138
|
-
scopes:
|
|
139
|
+
...device,
|
|
140
|
+
scopes: scopesForPlatform(device.platform),
|
|
139
141
|
now
|
|
140
142
|
});
|
|
141
143
|
registerInitialDeviceRefreshToken(created.id, complete.initialRefreshToken, now);
|
|
@@ -147,7 +149,7 @@ function operateDevicePairingRequest(action, body, now = Date.now()) {
|
|
|
147
149
|
return {
|
|
148
150
|
request: statusFromRow(requestRow(row.request_id, now), now),
|
|
149
151
|
routes: JSON.parse(setup.routes_json),
|
|
150
|
-
...action === "complete" ? { scopes:
|
|
152
|
+
...action === "complete" ? { scopes: scopesForPlatform(devicePairingDeviceSchema.parse(JSON.parse(row.device_json)).platform) } : {}
|
|
151
153
|
};
|
|
152
154
|
}
|
|
153
155
|
//#endregion
|
|
@@ -6,6 +6,7 @@ export { discoverSqlMigrations, listRegisteredMigrationTargets } from './migrati
|
|
|
6
6
|
export { closeXopcDatabase, getXopcDatabase, isXopcDatabaseOpen, openXopcDatabase, requireXopcDatabase, resetXopcDatabaseSingletonForTest, type OpenXopcDatabaseOptions, type XopcDatabase, } from './connection.js';
|
|
7
7
|
export { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';
|
|
8
8
|
export { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding, type StoredEndpointSessionBinding, } from './endpoint-session-binding-repository.js';
|
|
9
|
+
export { deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, getBrowserTabBinding, getBrowserTabBindingById, setBrowserTabBinding, } from './browser-tab-binding-repository.js';
|
|
9
10
|
export { authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, issueDeviceTokenPair, listDevices, revokeDevice, rotateDeviceRefreshToken, type DeviceAccessIdentity, type DevicePlatform, type DevicePublicKeyJwk, type DeviceRecord, type DeviceTokenPair, } from './device-access-repository.js';
|
|
10
11
|
export { clearGatewayIdentityForTest, getOrCreateGatewayIdentity, signGatewayPayload, type GatewayIdentity, } from './gateway-identity-repository.js';
|
|
11
12
|
export { consumeDevicePairingToken, createDevicePairingSetup, isDevicePairingSetupActive, type DevicePairingSetup, type DeviceRoute, type PairingConsumeResult, } from './device-pairing-repository.js';
|
|
@@ -7,6 +7,7 @@ import { ensureXopcDatabaseSchema } from "./schema.js";
|
|
|
7
7
|
import { closeXopcDatabase, getXopcDatabase, isXopcDatabaseOpen, openXopcDatabase, requireXopcDatabase, resetXopcDatabaseSingletonForTest } from "./connection.js";
|
|
8
8
|
import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
|
|
9
9
|
import { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding } from "./endpoint-session-binding-repository.js";
|
|
10
|
+
import { deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, getBrowserTabBinding, getBrowserTabBindingById, setBrowserTabBinding } from "./browser-tab-binding-repository.js";
|
|
10
11
|
import { authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, issueDeviceTokenPair, listDevices, revokeDevice, rotateDeviceRefreshToken } from "./device-access-repository.js";
|
|
11
12
|
import { clearGatewayIdentityForTest, getOrCreateGatewayIdentity, signGatewayPayload } from "./gateway-identity-repository.js";
|
|
12
13
|
import { consumeDevicePairingToken, createDevicePairingSetup, isDevicePairingSetupActive } from "./device-pairing-repository.js";
|
|
@@ -39,4 +40,4 @@ import { appendConnectorExecutionAudit, claimConnectorWebhookDelivery, completeC
|
|
|
39
40
|
import { getConnectorAccount, listConnectorAccounts, reconcileConnectorAccount, refreshConnectorAccountCurrent } from "./connector-account-repository.js";
|
|
40
41
|
import { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, listConnectorSyncPolicies, upsertConnectorSyncPolicy } from "./connector-sync-policy-repository.js";
|
|
41
42
|
import { getUserTrustPolicy, setUserTrustPolicy } from "./user-trust-repository.js";
|
|
42
|
-
export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, consumeDevicePairingToken, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
|
|
43
|
+
export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, consumeDevicePairingToken, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getBrowserTabBinding, getBrowserTabBindingById, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setBrowserTabBinding, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
PRAGMA defer_foreign_keys = ON;
|
|
2
|
+
|
|
3
|
+
-- Rebuild the device table and every table that references it. SQLite rewrites
|
|
4
|
+
-- foreign-key targets on table rename, so rebuilding only `devices` would leave
|
|
5
|
+
-- references pointing at the temporary table name.
|
|
6
|
+
ALTER TABLE notification_deliveries RENAME TO notification_deliveries_v154;
|
|
7
|
+
ALTER TABLE device_pairing_requests RENAME TO device_pairing_requests_v154;
|
|
8
|
+
ALTER TABLE device_refresh_credentials RENAME TO device_refresh_credentials_v154;
|
|
9
|
+
ALTER TABLE device_access_sessions RENAME TO device_access_sessions_v154;
|
|
10
|
+
ALTER TABLE device_push_endpoints RENAME TO device_push_endpoints_v154;
|
|
11
|
+
ALTER TABLE devices RENAME TO devices_v154;
|
|
12
|
+
|
|
13
|
+
DROP INDEX idx_notification_deliveries_due;
|
|
14
|
+
DROP INDEX idx_device_pairing_requests_expiry;
|
|
15
|
+
DROP INDEX idx_device_refresh_credentials_device;
|
|
16
|
+
DROP INDEX idx_device_access_sessions_device;
|
|
17
|
+
|
|
18
|
+
CREATE TABLE devices (
|
|
19
|
+
device_id TEXT PRIMARY KEY,
|
|
20
|
+
display_name TEXT NOT NULL,
|
|
21
|
+
platform TEXT NOT NULL CHECK (platform IN ('ios', 'android', 'chrome')),
|
|
22
|
+
extension_id TEXT CHECK (extension_id IS NULL OR length(extension_id) = 32),
|
|
23
|
+
public_key_jwk TEXT NOT NULL,
|
|
24
|
+
scopes_json TEXT NOT NULL,
|
|
25
|
+
created_at INTEGER NOT NULL,
|
|
26
|
+
last_seen_at INTEGER,
|
|
27
|
+
revoked_at INTEGER,
|
|
28
|
+
CHECK ((platform = 'chrome') = (extension_id IS NOT NULL))
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE device_refresh_credentials (
|
|
32
|
+
credential_id TEXT PRIMARY KEY,
|
|
33
|
+
device_id TEXT NOT NULL REFERENCES devices(device_id) ON DELETE CASCADE,
|
|
34
|
+
token_hash TEXT NOT NULL,
|
|
35
|
+
expires_at INTEGER NOT NULL,
|
|
36
|
+
created_at INTEGER NOT NULL,
|
|
37
|
+
last_used_at INTEGER,
|
|
38
|
+
replaced_by TEXT REFERENCES device_refresh_credentials(credential_id),
|
|
39
|
+
rotation_request_id TEXT,
|
|
40
|
+
revoked_at INTEGER
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
CREATE TABLE device_access_sessions (
|
|
44
|
+
session_id TEXT PRIMARY KEY,
|
|
45
|
+
device_id TEXT NOT NULL REFERENCES devices(device_id) ON DELETE CASCADE,
|
|
46
|
+
token_hash TEXT NOT NULL,
|
|
47
|
+
expires_at INTEGER NOT NULL,
|
|
48
|
+
created_at INTEGER NOT NULL,
|
|
49
|
+
revoked_at INTEGER
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
CREATE TABLE device_push_endpoints (
|
|
53
|
+
device_id TEXT PRIMARY KEY REFERENCES devices(device_id) ON DELETE CASCADE,
|
|
54
|
+
platform TEXT NOT NULL CHECK (platform IN ('ios', 'android')),
|
|
55
|
+
push_token TEXT NOT NULL UNIQUE,
|
|
56
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
57
|
+
permissions TEXT NOT NULL CHECK (permissions IN ('granted', 'denied', 'unknown')),
|
|
58
|
+
preferences_json TEXT NOT NULL DEFAULT '{}',
|
|
59
|
+
locale TEXT NOT NULL CHECK (locale IN ('en', 'zh')),
|
|
60
|
+
app_version TEXT,
|
|
61
|
+
lease_expires_at INTEGER NOT NULL,
|
|
62
|
+
last_seen_at INTEGER NOT NULL,
|
|
63
|
+
created_at INTEGER NOT NULL,
|
|
64
|
+
updated_at INTEGER NOT NULL
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
CREATE TABLE device_pairing_requests (
|
|
68
|
+
request_id TEXT PRIMARY KEY,
|
|
69
|
+
pairing_id TEXT NOT NULL UNIQUE REFERENCES device_pairing_sessions(pairing_id) ON DELETE CASCADE,
|
|
70
|
+
device_json TEXT NOT NULL,
|
|
71
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'approved', 'completed', 'rejected', 'cancelled', 'expired')),
|
|
72
|
+
revision INTEGER NOT NULL DEFAULT 1,
|
|
73
|
+
confirmation_code TEXT NOT NULL,
|
|
74
|
+
expires_at INTEGER NOT NULL,
|
|
75
|
+
recovery_until INTEGER NOT NULL,
|
|
76
|
+
completion_key TEXT,
|
|
77
|
+
initial_token_hash TEXT,
|
|
78
|
+
device_id TEXT REFERENCES devices(device_id),
|
|
79
|
+
created_at INTEGER NOT NULL
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
CREATE TABLE notification_deliveries (
|
|
83
|
+
event_id TEXT NOT NULL,
|
|
84
|
+
device_id TEXT NOT NULL,
|
|
85
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'accepted', 'delivered', 'dead')),
|
|
86
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
87
|
+
next_attempt_at INTEGER NOT NULL,
|
|
88
|
+
provider_ticket_id TEXT,
|
|
89
|
+
last_error TEXT,
|
|
90
|
+
updated_at INTEGER NOT NULL,
|
|
91
|
+
PRIMARY KEY (event_id, device_id),
|
|
92
|
+
FOREIGN KEY (event_id) REFERENCES notification_events(event_id) ON DELETE CASCADE,
|
|
93
|
+
FOREIGN KEY (device_id) REFERENCES device_push_endpoints(device_id) ON DELETE CASCADE
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
INSERT INTO devices
|
|
97
|
+
SELECT device_id, display_name, platform, NULL, public_key_jwk, scopes_json,
|
|
98
|
+
created_at, last_seen_at, revoked_at
|
|
99
|
+
FROM devices_v154;
|
|
100
|
+
INSERT INTO device_refresh_credentials SELECT * FROM device_refresh_credentials_v154;
|
|
101
|
+
INSERT INTO device_access_sessions SELECT * FROM device_access_sessions_v154;
|
|
102
|
+
INSERT INTO device_push_endpoints SELECT * FROM device_push_endpoints_v154;
|
|
103
|
+
INSERT INTO device_pairing_requests SELECT * FROM device_pairing_requests_v154;
|
|
104
|
+
INSERT INTO notification_deliveries SELECT * FROM notification_deliveries_v154;
|
|
105
|
+
|
|
106
|
+
DROP TABLE notification_deliveries_v154;
|
|
107
|
+
DROP TABLE device_pairing_requests_v154;
|
|
108
|
+
DROP TABLE device_refresh_credentials_v154;
|
|
109
|
+
DROP TABLE device_access_sessions_v154;
|
|
110
|
+
DROP TABLE device_push_endpoints_v154;
|
|
111
|
+
DROP TABLE devices_v154;
|
|
112
|
+
|
|
113
|
+
CREATE INDEX idx_notification_deliveries_due
|
|
114
|
+
ON notification_deliveries(status, next_attempt_at);
|
|
115
|
+
CREATE INDEX idx_device_pairing_requests_expiry
|
|
116
|
+
ON device_pairing_requests(recovery_until);
|
|
117
|
+
CREATE INDEX idx_device_refresh_credentials_device
|
|
118
|
+
ON device_refresh_credentials(device_id, expires_at);
|
|
119
|
+
CREATE INDEX idx_device_access_sessions_device
|
|
120
|
+
ON device_access_sessions(device_id, expires_at);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE TABLE browser_tab_bindings (
|
|
2
|
+
binding_id TEXT PRIMARY KEY,
|
|
3
|
+
session_key TEXT NOT NULL UNIQUE,
|
|
4
|
+
principal_id TEXT NOT NULL REFERENCES devices(device_id) ON DELETE CASCADE,
|
|
5
|
+
endpoint_id TEXT NOT NULL,
|
|
6
|
+
tab_id TEXT NOT NULL,
|
|
7
|
+
window_id TEXT NOT NULL,
|
|
8
|
+
document_id TEXT NOT NULL,
|
|
9
|
+
url_origin TEXT NOT NULL,
|
|
10
|
+
mode TEXT NOT NULL CHECK (mode IN ('read', 'act')),
|
|
11
|
+
created_at INTEGER NOT NULL,
|
|
12
|
+
expires_at INTEGER NOT NULL
|
|
13
|
+
);
|
|
14
|
+
CREATE INDEX idx_browser_tab_bindings_expiry ON browser_tab_bindings(expires_at);
|
|
@@ -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 = 156;
|
|
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 = 156;
|
|
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 ?? 156;
|
|
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 ?? 156;
|
|
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 = 156;
|
|
23
23
|
|
|
24
24
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveStateDir } from "../config/paths-state.js";
|
|
2
|
-
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
3
2
|
import { init_paths, resolveAgentProfileDir, resolveBundledSkillsDir } from "../config/paths.js";
|
|
3
|
+
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
4
4
|
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";
|
package/dist/src/tui/tui.js
CHANGED
|
@@ -2,10 +2,10 @@ import { version } from "../../package.js";
|
|
|
2
2
|
import { resolveStateDir, resolveXopcDatabasePath } from "../config/paths-state.js";
|
|
3
3
|
import { parseAgentSessionKey } from "../routing/session-key-utils.js";
|
|
4
4
|
import { init_agent_session_key, normalizeAgentId } from "../routing/agent-session-key.js";
|
|
5
|
-
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
6
5
|
import { init_paths } from "../config/paths.js";
|
|
7
6
|
import { loadConfig } from "../config/loader.js";
|
|
8
7
|
import { getAllModels, getAllProviders, getApiKey, init_providers, isProviderConfiguredSync } from "../providers/index.js";
|
|
8
|
+
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
9
9
|
import { ProjectTrustStore, hasTrustRequiringProjectResources } from "../project-trust/trust-store.js";
|
|
10
10
|
import { renderWorkflowFinalSummary, renderWorkflowPanel } from "../agent/workflow/snapshot.js";
|
|
11
11
|
import { ensureStarterAgentsInitialized } from "../agent/starter-agents.js";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { RealtimeEvent, RealtimeSubscriptionHandle } from '../../realtime/broker.js';
|
|
2
|
+
import type { SessionInput, SessionInputState } from '../../storage/sqlite/session-input-repository.js';
|
|
3
|
+
import type { SubmitSessionInput } from '../../gateway/service/session-input-coordinator.js';
|
|
4
|
+
export interface VoiceAgentEvent {
|
|
5
|
+
type: string;
|
|
6
|
+
payload?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface VoiceAgentTask {
|
|
9
|
+
taskId: string;
|
|
10
|
+
runId: string;
|
|
11
|
+
events: AsyncIterable<VoiceAgentEvent>;
|
|
12
|
+
}
|
|
13
|
+
export interface VoiceAgentBroker {
|
|
14
|
+
delegate(input: {
|
|
15
|
+
sessionKey: string;
|
|
16
|
+
expectedSessionId: string;
|
|
17
|
+
turnId: string;
|
|
18
|
+
text: string;
|
|
19
|
+
signal: AbortSignal;
|
|
20
|
+
}): Promise<VoiceAgentTask>;
|
|
21
|
+
cancel(taskId: string): Promise<boolean>;
|
|
22
|
+
}
|
|
23
|
+
type SubmitResult = {
|
|
24
|
+
ok: true;
|
|
25
|
+
effectiveDelivery: 'next' | 'steer';
|
|
26
|
+
state: SessionInputState;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
code: string;
|
|
30
|
+
};
|
|
31
|
+
type BrokerDependencies = {
|
|
32
|
+
submit(input: SubmitSessionInput): Promise<SubmitResult>;
|
|
33
|
+
find(sessionKey: string, clientMessageId: string): SessionInput | undefined;
|
|
34
|
+
snapshot(sessionKey: string): SessionInputState;
|
|
35
|
+
currentSequence(topic: string): number;
|
|
36
|
+
subscribe(topic: string, afterSeq: number, listener: (event: RealtimeEvent) => void): RealtimeSubscriptionHandle;
|
|
37
|
+
cancelRun(runId: string): Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
/** Durable voice-to-Agent boundary. Playback and socket cancellation only detach event delivery. */
|
|
40
|
+
export declare class DurableVoiceAgentBroker implements VoiceAgentBroker {
|
|
41
|
+
private readonly deps;
|
|
42
|
+
private readonly runByTask;
|
|
43
|
+
constructor(deps: BrokerDependencies);
|
|
44
|
+
delegate(input: {
|
|
45
|
+
sessionKey: string;
|
|
46
|
+
expectedSessionId: string;
|
|
47
|
+
turnId: string;
|
|
48
|
+
text: string;
|
|
49
|
+
signal: AbortSignal;
|
|
50
|
+
}): Promise<VoiceAgentTask>;
|
|
51
|
+
cancel(taskId: string): Promise<boolean>;
|
|
52
|
+
private events;
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
//#region src/voice/realtime/agentBroker.ts
|
|
2
|
+
const RUN_ASSIGNMENT_TIMEOUT_MS = 5e3;
|
|
3
|
+
const RUN_ASSIGNMENT_POLL_MS = 20;
|
|
4
|
+
const MAX_TRACKED_TASKS = 256;
|
|
5
|
+
function sleep(ms, signal) {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
const finish = () => {
|
|
8
|
+
signal.removeEventListener("abort", abort);
|
|
9
|
+
resolve();
|
|
10
|
+
};
|
|
11
|
+
const timer = setTimeout(finish, ms);
|
|
12
|
+
const abort = () => {
|
|
13
|
+
clearTimeout(timer);
|
|
14
|
+
reject(signal.reason ?? /* @__PURE__ */ new Error("Voice task subscription cancelled"));
|
|
15
|
+
};
|
|
16
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
17
|
+
if (signal.aborted) abort();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function eventData(delivery) {
|
|
21
|
+
if (delivery.kind !== "realtime.event") return void 0;
|
|
22
|
+
const value = delivery.payload.data;
|
|
23
|
+
return value && typeof value === "object" && typeof value.type === "string" ? value : void 0;
|
|
24
|
+
}
|
|
25
|
+
/** Durable voice-to-Agent boundary. Playback and socket cancellation only detach event delivery. */
|
|
26
|
+
var DurableVoiceAgentBroker = class {
|
|
27
|
+
runByTask = /* @__PURE__ */ new Map();
|
|
28
|
+
constructor(deps) {
|
|
29
|
+
this.deps = deps;
|
|
30
|
+
}
|
|
31
|
+
async delegate(input) {
|
|
32
|
+
const clientMessageId = `voice:${input.expectedSessionId}:${input.turnId}`;
|
|
33
|
+
const activeRunId = this.deps.snapshot(input.sessionKey).activeRunId;
|
|
34
|
+
const activeRunCursor = activeRunId ? this.deps.currentSequence(`run:${activeRunId}`) : 0;
|
|
35
|
+
const result = await this.deps.submit({
|
|
36
|
+
sessionKey: input.sessionKey,
|
|
37
|
+
expectedSessionId: input.expectedSessionId,
|
|
38
|
+
clientMessageId,
|
|
39
|
+
delivery: activeRunId ? "steer" : "next",
|
|
40
|
+
content: input.text,
|
|
41
|
+
origin: {
|
|
42
|
+
type: "channel",
|
|
43
|
+
channel: "voice"
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
if (result.ok === false) throw new Error(`Voice task submission failed: ${result.code}`);
|
|
47
|
+
const deadline = Date.now() + RUN_ASSIGNMENT_TIMEOUT_MS;
|
|
48
|
+
let row = this.deps.find(input.sessionKey, clientMessageId);
|
|
49
|
+
while (!row?.runId && !row?.targetRunId) {
|
|
50
|
+
if (row && [
|
|
51
|
+
"completed",
|
|
52
|
+
"cancelled",
|
|
53
|
+
"failed",
|
|
54
|
+
"interrupted"
|
|
55
|
+
].includes(row.status)) throw new Error(row.error ?? `Voice task ended before assignment: ${row.status}`);
|
|
56
|
+
if (Date.now() >= deadline) throw new Error("Voice task run assignment timed out");
|
|
57
|
+
await sleep(RUN_ASSIGNMENT_POLL_MS, input.signal);
|
|
58
|
+
row = this.deps.find(input.sessionKey, clientMessageId);
|
|
59
|
+
}
|
|
60
|
+
const runId = row.runId ?? row.targetRunId;
|
|
61
|
+
this.runByTask.set(row.id, runId);
|
|
62
|
+
if (this.runByTask.size > MAX_TRACKED_TASKS) this.runByTask.delete(this.runByTask.keys().next().value);
|
|
63
|
+
const afterSeq = result.effectiveDelivery === "steer" && runId === activeRunId ? activeRunCursor : 0;
|
|
64
|
+
return {
|
|
65
|
+
taskId: row.id,
|
|
66
|
+
runId,
|
|
67
|
+
events: this.events(row.id, runId, afterSeq, input.signal)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async cancel(taskId) {
|
|
71
|
+
const runId = this.runByTask.get(taskId);
|
|
72
|
+
if (!runId) return false;
|
|
73
|
+
await this.deps.cancelRun(runId);
|
|
74
|
+
this.runByTask.delete(taskId);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
async *events(taskId, runId, afterSeq, signal) {
|
|
78
|
+
const queued = [];
|
|
79
|
+
let wake;
|
|
80
|
+
const push = (event) => {
|
|
81
|
+
queued.push(event);
|
|
82
|
+
wake?.();
|
|
83
|
+
wake = void 0;
|
|
84
|
+
};
|
|
85
|
+
const subscription = this.deps.subscribe(`run:${runId}`, afterSeq, push);
|
|
86
|
+
subscription.initial.forEach(push);
|
|
87
|
+
const abort = () => {
|
|
88
|
+
wake?.();
|
|
89
|
+
wake = void 0;
|
|
90
|
+
};
|
|
91
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
92
|
+
try {
|
|
93
|
+
while (!signal.aborted) {
|
|
94
|
+
if (!queued.length) await new Promise((resolve) => {
|
|
95
|
+
wake = resolve;
|
|
96
|
+
});
|
|
97
|
+
if (signal.aborted) return;
|
|
98
|
+
const delivery = queued.shift();
|
|
99
|
+
if (!delivery) continue;
|
|
100
|
+
if (delivery.kind === "realtime.gap") throw new Error("Voice task event history is unavailable");
|
|
101
|
+
const event = eventData(delivery);
|
|
102
|
+
if (!event) continue;
|
|
103
|
+
yield event;
|
|
104
|
+
if (event.type === "stream_end") {
|
|
105
|
+
this.runByTask.delete(taskId);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} finally {
|
|
110
|
+
signal.removeEventListener("abort", abort);
|
|
111
|
+
subscription.unsubscribe();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
//#endregion
|
|
116
|
+
export { DurableVoiceAgentBroker };
|
|
@@ -2,8 +2,9 @@ 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 {
|
|
5
|
+
import { TurnCoordinator } from "./turnPolicy.js";
|
|
6
6
|
import { isLikelyPlaybackEcho } from "./playback-echo.js";
|
|
7
|
+
import { PcmFrameBuffer } from "./pcmFrameBuffer.js";
|
|
7
8
|
import { SpeakableSegmenter } from "./speakable-segmenter.js";
|
|
8
9
|
import crypto from "node:crypto";
|
|
9
10
|
//#region src/voice/realtime/agentEngine.ts
|
|
@@ -34,8 +35,24 @@ function createAgentVoiceEngine(options) {
|
|
|
34
35
|
let committing = false;
|
|
35
36
|
const finalizedUtterances = /* @__PURE__ */ new Set();
|
|
36
37
|
let pendingTurn;
|
|
37
|
-
const turn = new
|
|
38
|
+
const turn = new TurnCoordinator(claim.silenceDurationMs, (text, decision, turnId) => {
|
|
38
39
|
if (closed || muted) return;
|
|
40
|
+
log.info({
|
|
41
|
+
sessionId: claim.sessionId,
|
|
42
|
+
turnId,
|
|
43
|
+
disposition: decision.disposition,
|
|
44
|
+
confidence: decision.confidence,
|
|
45
|
+
source: decision.source,
|
|
46
|
+
transcriptCharacters: text.length
|
|
47
|
+
}, "Realtime voice turn committed");
|
|
48
|
+
send("turn.decision", {
|
|
49
|
+
turnId,
|
|
50
|
+
disposition: decision.disposition,
|
|
51
|
+
confidence: decision.confidence,
|
|
52
|
+
source: decision.source,
|
|
53
|
+
committed: true
|
|
54
|
+
});
|
|
55
|
+
send("turn.committed", { turnId });
|
|
39
56
|
if (queuedTurns >= 8) {
|
|
40
57
|
send("session.error", {
|
|
41
58
|
code: "INPUT_BACKPRESSURE",
|
|
@@ -48,13 +65,14 @@ function createAgentVoiceEngine(options) {
|
|
|
48
65
|
queuedTurns += 1;
|
|
49
66
|
const generation = inputGeneration;
|
|
50
67
|
const pending = {
|
|
68
|
+
turnId,
|
|
51
69
|
text,
|
|
52
70
|
cancelled: false
|
|
53
71
|
};
|
|
54
72
|
pendingTurn = pending;
|
|
55
73
|
conversationTail = conversationTail.then(() => {
|
|
56
74
|
if (pendingTurn === pending) pendingTurn = void 0;
|
|
57
|
-
if (generation === inputGeneration && !pending.cancelled) return
|
|
75
|
+
if (generation === inputGeneration && !pending.cancelled) return runAssistantTurn(text, turnId);
|
|
58
76
|
}).finally(() => {
|
|
59
77
|
if (generation === inputGeneration) queuedTurns -= 1;
|
|
60
78
|
});
|
|
@@ -129,11 +147,10 @@ function createAgentVoiceEngine(options) {
|
|
|
129
147
|
}
|
|
130
148
|
});
|
|
131
149
|
}
|
|
132
|
-
for (
|
|
133
|
-
|
|
134
|
-
await response.playback.reserve(chunk.byteLength, response.abortController.signal);
|
|
150
|
+
for (const frame of response.pcm.push(item.value)) {
|
|
151
|
+
await response.playback.reserve(frame.byteLength, response.abortController.signal);
|
|
135
152
|
if (activeResponse !== response || closed) return;
|
|
136
|
-
options.sendAudio(response.id,
|
|
153
|
+
options.sendAudio(response.id, frame);
|
|
137
154
|
}
|
|
138
155
|
}
|
|
139
156
|
} finally {
|
|
@@ -204,7 +221,7 @@ function createAgentVoiceEngine(options) {
|
|
|
204
221
|
if (response.speechWorker) prefetchNextSpeech(response);
|
|
205
222
|
else startSpeechWorker(response);
|
|
206
223
|
}
|
|
207
|
-
async function
|
|
224
|
+
async function runAssistantTurn(text, turnId) {
|
|
208
225
|
if (!claim.tts || !claim.request.sessionKey || !text.trim() || closed) return;
|
|
209
226
|
cancelActiveResponse("barge_in");
|
|
210
227
|
const response = {
|
|
@@ -219,14 +236,28 @@ function createAgentVoiceEngine(options) {
|
|
|
219
236
|
queuedSpeechCharacters: 0,
|
|
220
237
|
startedAt: Date.now(),
|
|
221
238
|
firstTextSeen: false,
|
|
222
|
-
awaitingClarification: false
|
|
239
|
+
awaitingClarification: false,
|
|
240
|
+
pcm: new PcmFrameBuffer()
|
|
223
241
|
};
|
|
224
242
|
activeResponse = response;
|
|
225
243
|
send("response.created", { responseId: response.id });
|
|
226
244
|
try {
|
|
227
245
|
await interruptionWrites;
|
|
228
246
|
if (response.abortController.signal.aborted || closed) return;
|
|
229
|
-
|
|
247
|
+
if (!claim.conversationSessionId) throw new Error("Conversation identity is unavailable");
|
|
248
|
+
const task = await options.runtime.agentBroker.delegate({
|
|
249
|
+
text,
|
|
250
|
+
turnId,
|
|
251
|
+
sessionKey: claim.request.sessionKey,
|
|
252
|
+
expectedSessionId: claim.conversationSessionId,
|
|
253
|
+
signal: response.abortController.signal
|
|
254
|
+
});
|
|
255
|
+
response.taskId = task.taskId;
|
|
256
|
+
send("task.created", {
|
|
257
|
+
responseId: response.id,
|
|
258
|
+
taskId: task.taskId
|
|
259
|
+
});
|
|
260
|
+
for await (const event of task.events) {
|
|
230
261
|
if (activeResponse !== response || response.abortController.signal.aborted) return;
|
|
231
262
|
if (event.type === "assistant_delta" || event.type === "tool_end" && event.payload?.toolName !== "clarify") response.awaitingClarification = false;
|
|
232
263
|
if (event.type === "assistant_delta" && typeof event.payload?.delta === "string") {
|
|
@@ -247,12 +278,19 @@ function createAgentVoiceEngine(options) {
|
|
|
247
278
|
queuePhrases(response, response.segmenter.push(event.payload.delta));
|
|
248
279
|
}
|
|
249
280
|
if (event.type === "tool_start") queuePhrases(response, response.segmenter.flush());
|
|
250
|
-
if ((event.type === "tool_start" || event.type === "tool_end") && typeof event.payload?.toolCallId === "string" && typeof event.payload?.toolName === "string") send("
|
|
251
|
-
|
|
281
|
+
if ((event.type === "tool_start" || event.type === "tool_end") && typeof event.payload?.toolCallId === "string" && typeof event.payload?.toolName === "string") send("task.activity", {
|
|
282
|
+
taskId: task.taskId,
|
|
252
283
|
toolCallId: event.payload.toolCallId.slice(0, 160),
|
|
253
284
|
toolName: event.payload.toolName.slice(0, 256),
|
|
254
285
|
status: event.type === "tool_start" ? "running" : event.payload.status === "error" ? "failed" : "completed"
|
|
255
286
|
});
|
|
287
|
+
if (event.type === "stream_end") {
|
|
288
|
+
const status = event.payload?.status;
|
|
289
|
+
send("task.done", {
|
|
290
|
+
taskId: task.taskId,
|
|
291
|
+
status: status === "cancelled" ? "cancelled" : status === "suspended" ? "suspended" : status === "error" ? "failed" : "completed"
|
|
292
|
+
});
|
|
293
|
+
}
|
|
256
294
|
if (event.type === "clarify_request" && typeof event.payload?.requestId === "string" && typeof event.payload?.question === "string") {
|
|
257
295
|
response.awaitingClarification = true;
|
|
258
296
|
send("response.clarification", {
|
|
@@ -274,6 +312,12 @@ function createAgentVoiceEngine(options) {
|
|
|
274
312
|
send("response.text.done", { responseId: response.id });
|
|
275
313
|
await waitForSpeech(response);
|
|
276
314
|
if (response.speechError) throw response.speechError;
|
|
315
|
+
const finalFrame = response.pcm.finish();
|
|
316
|
+
if (finalFrame) {
|
|
317
|
+
await response.playback.reserve(finalFrame.byteLength, response.abortController.signal);
|
|
318
|
+
if (activeResponse !== response || closed) return;
|
|
319
|
+
options.sendAudio(response.id, finalFrame);
|
|
320
|
+
}
|
|
277
321
|
await response.playback.drain(response.abortController.signal);
|
|
278
322
|
if (activeResponse !== response || response.abortController.signal.aborted) return;
|
|
279
323
|
if (response.audioStarted) send("response.audio.done", { responseId: response.id });
|
|
@@ -367,7 +411,7 @@ function createAgentVoiceEngine(options) {
|
|
|
367
411
|
if (claim.request.purpose === "conversation") {
|
|
368
412
|
if (pendingTurn) {
|
|
369
413
|
pendingTurn.cancelled = true;
|
|
370
|
-
turn.restore(pendingTurn.text);
|
|
414
|
+
turn.restore(pendingTurn.turnId, pendingTurn.text);
|
|
371
415
|
pendingTurn = void 0;
|
|
372
416
|
}
|
|
373
417
|
turn.start(event.utteranceId);
|
|
@@ -500,8 +544,11 @@ function createAgentVoiceEngine(options) {
|
|
|
500
544
|
});
|
|
501
545
|
return cancelActiveResponse(reason);
|
|
502
546
|
},
|
|
503
|
-
|
|
504
|
-
|
|
547
|
+
cancelTask(taskId) {
|
|
548
|
+
return options.runtime.agentBroker.cancel(taskId);
|
|
549
|
+
},
|
|
550
|
+
acknowledge(responseId, playedDurationMs) {
|
|
551
|
+
if (activeResponse?.id === responseId) activeResponse.playback.acknowledge(playedDurationMs * 48);
|
|
505
552
|
},
|
|
506
553
|
close() {
|
|
507
554
|
if (closing) return closing;
|
|
@@ -8,6 +8,7 @@ export interface VoiceEngine {
|
|
|
8
8
|
setInputMuted(muted: boolean): void | Promise<void>;
|
|
9
9
|
commit(): Promise<void>;
|
|
10
10
|
cancel(responseId: string, reason: 'client_cancelled' | 'barge_in'): boolean;
|
|
11
|
-
|
|
11
|
+
cancelTask(taskId: string): Promise<boolean>;
|
|
12
|
+
acknowledge(responseId: string, playedDurationMs: number): void;
|
|
12
13
|
close(): void | Promise<void>;
|
|
13
14
|
}
|