@xopcai/xopc 0.0.161 → 0.0.162
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-o7GRljfD.js → activity-store-hpcNv9MZ.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-9R3szLMc.js → agent-avatar-dicebear-Zf9UQEmQ.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DfVkZlHc.js +2 -0
- package/dist/gateway/static/root/assets/{api-jSTqFMq9.js → api-Dnatri09.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-D81cyE76.js → app-management-settings-panel-BBTR9wJP.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-Ct6bZQCV.js → appearance-settings-C2zpLCHD.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BMtAa4Ra.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-CfD7AZKn.js → archive-plugin-9eR_ODY1.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CP_Gaxt3.js → attachment-load-DPuWYUeX.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-BGKM_NDZ.js → automation-suggestion-card-Dw49OJRl.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-BiSAMYTr.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-IPr2EVnS.js → binary-plugins-BdkJpDFm.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-B6aHEGA6.js → block-editor-CAi7SXYU.js} +47 -47
- package/dist/gateway/static/root/assets/browser-settings-page-DHmaEJS2.js +8 -0
- package/dist/gateway/static/root/assets/browser-workflow-inputs-Dx6wkGz1.js +1 -0
- package/dist/gateway/static/root/assets/browser-workflows-page-Skertc-A.js +3 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-B5wSgf4f.js +2 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-CCX9-LjU.js → capability-presets-api-CNFl7dM3.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DyvFZwBj.js +2 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-MmLMLDWf.js → channel-recipient-api-DYQyGDw4.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-BBKEqDZn.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-Drk110ve.js +1 -0
- package/dist/gateway/static/root/assets/{connector-logo-BbjzIs87.js → connector-logo-Bng6kxYF.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-HpgaUDQ1.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-Bpf6oegd.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DQLqGLc0.js → desktop-pet-settings-BVUyefSd.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-ClsiXhmz.js → directory-picker-path-field-DjSZAPz_.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-CjMPPdzg.js → dreaming-settings-CAZk2AM4.js} +3 -3
- package/dist/gateway/static/root/assets/{extension-debug-page-57eizjhB.js → extension-debug-page-C2F6vTTd.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CsbSb3u1.js → extension-page-AnIt4bn4.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DKA9-lyP.js → extension-settings-page-CLSc6682.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-DIPJuzBZ.js → gateway-config-api-DLFyZv33.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-CDLqAQY7.js → gateway-settings-DnQAA-qq.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DrfSJtvT.js → gateway-startup-retry-DbzLyJ3R.js} +1 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-DrnKFC6M.js +1 -0
- package/dist/gateway/static/root/assets/goal-detail-page-Cw1hpJkZ.js +4 -0
- package/dist/gateway/static/root/assets/{goals-config-api-lGC10UkU.js → goals-config-api-REmr3QCr.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-BDGkTVma.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-BWq0pdrA.js → goals-settings-Dz0F3uRO.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-D4o8BJVv.js → heartbeat-settings-CQFY5gYs.js} +1 -1
- package/dist/gateway/static/root/assets/index-C8JkTS6d.js +199 -0
- package/dist/gateway/static/root/assets/index-hmrG55qg.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6T2QYehS.js → keyboard-shortcuts-settings-BnOQXU5k.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-Bdef1b7F.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DCjg2K9f.js → local-apps-page-KsOtWOyM.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-Dar-xqQr.js → locale-store-0lpYdNDr.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CyYCBqym.js → logs-page-CwLPgrWh.js} +3 -3
- package/dist/gateway/static/root/assets/{markdown-split-rt1XO43g.js → markdown-split-D5GRg10r.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Bwo8CJuh.js → media-plugins-C1ryULGs.js} +1 -1
- package/dist/gateway/static/root/assets/messages-BwQ3WssU.js +5 -0
- package/dist/gateway/static/root/assets/{notes-page-Dp-pkX7d.js → notes-page-CIeZ1_DT.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-Cf06q19x.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-CzZ4iKOb.js → page-tabs-Caj1-E_X.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-3E_Qa-58.js → preview-open-alternatives-DKwEce-9.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-B2T48Sbt.js → product-open-page-B90ZskkN.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-SHTurM4t.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BcC2qUAw.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-6vGefBHv.js +1 -0
- package/dist/gateway/static/root/assets/save-bar-controls-BDYt53uQ.js +1 -0
- package/dist/gateway/static/root/assets/{schedule-field-TkqUL3wm.js → schedule-field-Bcdni4Pj.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-DC-iU5IG.js → schema-form-D7oCARF7.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-C5014a53.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-CDY3ZI1K.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-Dpqth3oA.js → settings-collapsible-section-6eNF8Jey.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-CNqF6IwY.js → settings-form-section-CARTHCxH.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-DkvwitK_.js → settings-loading-skeleton-DEwYqESe.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-B6vVdHeQ.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-layout-DWvNgISx.js → settings-page-layout-D3srt5Bi.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-z-rF0Hdg.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-DGpSPW-n.js → share-preview-page-Ck9SxiXw.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CHZFXE_d.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-B7p2QNXt.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-ncw3tX9P.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-8TxxSbUw.js → system-settings-panel-DLBUQSk2.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-B5FzMWOx.js → theme-store-C1oaqeD2.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-DEGtSA5h.js → typed-models-lib-Divbg_C4.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-BDU6FneG.js → use-channel-catalog-CP9a_rAf.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-iYfeSLKI.js +1 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-CrwkicvT.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-page-BQWxyPg8.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-50ZzGay5.js +1 -0
- package/dist/gateway/static/root/assets/work-page-DPqEahx7.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cwi8Pz7n.js → workflow-run-setup-panel-DbDPYQwB.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-C3eIC5HZ.js +11 -0
- package/dist/gateway/static/root/index.html +7 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +1 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/client-error-format.js +3 -3
- package/dist/src/agent/outcomes/task-evaluation.d.ts +20 -0
- package/dist/src/agent/outcomes/task-evaluation.js +48 -0
- package/dist/src/agent/outcomes/task-verifier.d.ts +29 -0
- package/dist/src/agent/outcomes/task-verifier.js +71 -0
- package/dist/src/agent/prompt/memory/index.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +32 -1
- package/dist/src/agent/service.js +1 -0
- package/dist/src/agent/service.types.d.ts +1 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +1 -7
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +2 -73
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +1 -13
- package/dist/src/agent/tools/browser/tool/schemas.js +1 -9
- package/dist/src/agent/tools/browser-recipe-tool.d.ts +12 -0
- package/dist/src/agent/tools/browser-recipe-tool.js +113 -0
- package/dist/src/agent/tools/factory.d.ts +2 -0
- package/dist/src/agent/tools/factory.js +2 -0
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/automations/domain/types.d.ts +13 -0
- package/dist/src/automations/domain/validation.d.ts +44 -24
- package/dist/src/automations/domain/validation.js +27 -18
- package/dist/src/automations/draft/automation-draft-validator.d.ts +6 -1
- package/dist/src/automations/draft/automation-draft-validator.js +1 -0
- package/dist/src/automations/service/action-executor.d.ts +1 -0
- package/dist/src/automations/service/action-executor.js +22 -0
- package/dist/src/browser/index.d.ts +0 -1
- package/dist/src/browser/index.js +1 -2
- package/dist/src/browser/pipeline/runner.d.ts +9 -2
- package/dist/src/browser/pipeline/runner.js +151 -105
- package/dist/src/browser/pipeline/schema.d.ts +21 -15
- package/dist/src/browser/pipeline/schema.js +93 -99
- package/dist/src/browser/recipes/index.d.ts +3 -0
- package/dist/src/browser/recipes/index.js +3 -0
- package/dist/src/browser/recipes/repository.d.ts +13 -0
- package/dist/src/browser/recipes/repository.js +81 -0
- package/dist/src/browser/recipes/runtime-service.d.ts +6 -0
- package/dist/src/browser/recipes/runtime-service.js +30 -0
- package/dist/src/browser/recipes/service.d.ts +36 -0
- package/dist/src/browser/recipes/service.js +186 -0
- package/dist/src/browser/recipes/types.d.ts +36 -0
- package/dist/src/browser/recipes/types.js +1 -0
- package/dist/src/cli/commands/browser-cli-helpers.js +6 -12
- package/dist/src/cli/commands/browser.js +4 -3
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/schema.d.ts +3 -3
- package/dist/src/config/schema.js +21 -21
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -1
- package/dist/src/gateway/hono/routes/browser-workflows.d.ts +3 -0
- package/dist/src/gateway/hono/routes/browser-workflows.js +78 -0
- package/dist/src/gateway/hono/routes/home.js +1 -0
- package/dist/src/gateway/hono/routes/index.js +4 -0
- package/dist/src/gateway/hono/routes/interaction-state.d.ts +3 -0
- package/dist/src/gateway/hono/routes/interaction-state.js +45 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/memory.js +33 -4
- package/dist/src/gateway/hono/routes/task-outcomes.d.ts +3 -0
- package/dist/src/gateway/hono/routes/task-outcomes.js +109 -0
- package/dist/src/gateway/hono/routes/you.d.ts +10 -2
- package/dist/src/gateway/hono/routes/you.js +184 -28
- package/dist/src/gateway/service/run-gateway-agent.js +84 -0
- package/dist/src/gateway/service.d.ts +3 -0
- package/dist/src/gateway/service.js +14 -0
- package/dist/src/proactive/insight-repository.d.ts +2 -0
- package/dist/src/proactive/insight-repository.js +5 -2
- package/dist/src/proactive/run-processor.js +22 -1
- package/dist/src/proactive/types.d.ts +2 -0
- package/dist/src/proactive/value-score.d.ts +13 -0
- package/dist/src/proactive/value-score.js +30 -0
- package/dist/src/share/share-types.js +5 -5
- package/dist/src/share/site-share-types.d.ts +1 -1
- package/dist/src/share/site-share-types.js +5 -5
- package/dist/src/storage/sqlite/index.d.ts +3 -0
- package/dist/src/storage/sqlite/index.js +4 -1
- package/dist/src/storage/sqlite/interaction-state-repository.d.ts +17 -0
- package/dist/src/storage/sqlite/interaction-state-repository.js +60 -0
- package/dist/src/storage/sqlite/memory-records-repository.js +1 -1
- package/dist/src/storage/sqlite/migrations/053_browser_recipes.sql +45 -0
- package/dist/src/storage/sqlite/migrations/054_task_outcomes.sql +24 -0
- package/dist/src/storage/sqlite/migrations/055_relationship_settings.sql +14 -0
- package/dist/src/storage/sqlite/migrations/056_task_verification.sql +6 -0
- package/dist/src/storage/sqlite/migrations/057_interaction_states.sql +11 -0
- package/dist/src/storage/sqlite/migrations/058_proactive_value.sql +3 -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/relationship-settings-repository.d.ts +17 -0
- package/dist/src/storage/sqlite/relationship-settings-repository.js +64 -0
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +46 -0
- package/dist/src/storage/sqlite/task-outcome-repository.d.ts +90 -0
- package/dist/src/storage/sqlite/task-outcome-repository.js +138 -0
- package/dist/src/user-context/interaction-state.d.ts +13 -0
- package/dist/src/user-context/interaction-state.js +69 -0
- package/dist/src/user-context/memory-use-audit.d.ts +10 -0
- package/dist/src/user-context/memory-use-audit.js +25 -0
- package/dist/src/user-context/personal-playbook.d.ts +11 -0
- package/dist/src/user-context/personal-playbook.js +41 -0
- package/dist/src/user-context/projection.d.ts +4 -0
- package/dist/src/user-context/projection.js +5 -1
- package/dist/src/user-context/relationship-continuity.d.ts +14 -0
- package/dist/src/user-context/relationship-continuity.js +51 -0
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/action-boundary-settings-panel-BIVBUiNT.js +0 -1
- package/dist/gateway/static/root/assets/agents-_qbUaYbs.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-0sPqD0FK.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-BxWBuBsE.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-C499b9AH.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Dva9SiPK.js +0 -2
- package/dist/gateway/static/root/assets/channels-settings-DNAU7u9o.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-CIOH7tgn.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-TwiBp8vY.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-CYH5ZSXy.js +0 -1
- package/dist/gateway/static/root/assets/goal-create-dialog-Q3B0E-0s.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-C5VAK04G.js +0 -4
- package/dist/gateway/static/root/assets/goals-page-BJb-5IYw.js +0 -2
- package/dist/gateway/static/root/assets/index-CkUHH170.css +0 -1
- package/dist/gateway/static/root/assets/index-vq_cJZJC.js +0 -199
- package/dist/gateway/static/root/assets/local-app-workbench-page-euH17Kvb.js +0 -2
- package/dist/gateway/static/root/assets/messages-CxySDn9d.js +0 -5
- package/dist/gateway/static/root/assets/models-hub-panel-DObxxjc9.js +0 -2
- package/dist/gateway/static/root/assets/notes-workbench-CCb4RXcZ.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-BvEcriRC.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B_e79MRJ.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DGcqnYfR.js +0 -1
- package/dist/gateway/static/root/assets/save-bar-controls-CkeKasGm.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DQZhrDJ8.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BkdeN99Y.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-qPG7I2zd.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-lwRAh9aw.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-BGj9IVUr.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-B2UBAs5U.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-DdjzFZ8I.js +0 -2
- package/dist/gateway/static/root/assets/user-context-page-BTTZpAGV.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-DuDQd-WU.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-BUVkVCsW.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-DeEPPu4n.js +0 -1
- package/dist/gateway/static/root/assets/work-page-DQNUyTUq.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-BIy4wrzO.js +0 -11
- package/dist/src/browser/pipeline/source.d.ts +0 -9
- package/dist/src/browser/pipeline/source.js +0 -77
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { runSqliteWriteTransaction } from "../../../storage/sqlite/transaction.js";
|
|
2
|
+
import { getRelationshipSettings, updateRelationshipSettings } from "../../../storage/sqlite/relationship-settings-repository.js";
|
|
2
3
|
import { deleteMemoryRecord, getMemoryRecord, listMemoryRecords, upsertMemoryRecord } from "../../../storage/sqlite/memory-records-repository.js";
|
|
3
4
|
import { listKnowledgeSourceItems, listKnowledgeSyncRuns } from "../../../storage/sqlite/knowledge-repository.js";
|
|
4
5
|
import { getConnectorConnection, listConnectorConnections } from "../../../storage/sqlite/connector-repository.js";
|
|
@@ -15,6 +16,7 @@ import "../../../goals/index.js";
|
|
|
15
16
|
import { revokeComposioConnection } from "../../../connectors/composio.js";
|
|
16
17
|
import { listConnectorCatalog } from "../../../connectors/catalog.js";
|
|
17
18
|
import { nextMemoryReviewAt, resolveMemoryStability } from "../../../agent/memory/lifecycle.js";
|
|
19
|
+
import { PERSONAL_PLAYBOOK_DISABLED_TAG, PERSONAL_PLAYBOOK_ORDER_PREFIX, PERSONAL_PLAYBOOK_RULE_TAG, patchPersonalPlaybookContextTags, personalPlaybookContext } from "../../../user-context/personal-playbook.js";
|
|
18
20
|
import { listConnectorInstances } from "../../../connectors/instances.js";
|
|
19
21
|
import { uninstallConnector } from "../../../connectors/install.js";
|
|
20
22
|
import { readUserProfileFile, writeUserProfileFile } from "../../agents-admin.js";
|
|
@@ -44,8 +46,13 @@ const PLAYBOOK_IDS = [
|
|
|
44
46
|
"execution",
|
|
45
47
|
"routines"
|
|
46
48
|
];
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
+
const PLAYBOOK_SUPPORT_NEEDS = new Set([
|
|
50
|
+
"listen",
|
|
51
|
+
"clarify",
|
|
52
|
+
"advise",
|
|
53
|
+
"act",
|
|
54
|
+
"unknown"
|
|
55
|
+
]);
|
|
49
56
|
const PROFILE_FIELD_LIMITS = {
|
|
50
57
|
callName: 80,
|
|
51
58
|
pronouns: 80,
|
|
@@ -154,34 +161,57 @@ function parseProfilePatch(body) {
|
|
|
154
161
|
return Object.keys(patch).length > 0 ? { patch } : { error: "No profile fields provided" };
|
|
155
162
|
}
|
|
156
163
|
function playbookForRecord(record) {
|
|
164
|
+
if (!record.tags?.includes("playbook:rule")) return void 0;
|
|
157
165
|
if (record.kind === "preference" || record.kind === "boundary" || record.kind === "tool_preference") return "communication";
|
|
158
166
|
if (record.kind === "task_lesson" || record.kind === "derived_insight") return "execution";
|
|
159
167
|
if (record.kind === "routine") return "routines";
|
|
160
168
|
}
|
|
161
169
|
function playbookRuleOrder(record) {
|
|
162
|
-
const tag = record.tags?.find((value) => value.startsWith(
|
|
163
|
-
const parsed = tag ? Number.parseInt(tag.slice(
|
|
170
|
+
const tag = record.tags?.find((value) => value.startsWith(PERSONAL_PLAYBOOK_ORDER_PREFIX));
|
|
171
|
+
const parsed = tag ? Number.parseInt(tag.slice(PERSONAL_PLAYBOOK_ORDER_PREFIX.length), 10) : NaN;
|
|
164
172
|
return Number.isFinite(parsed) ? parsed : 1e3;
|
|
165
173
|
}
|
|
166
174
|
function patchPlaybookRuleTags(record, patch) {
|
|
167
|
-
let tags = (record.tags ?? []).filter((tag) => !tag.startsWith(
|
|
168
|
-
if (patch.enabled === true) tags = tags.filter((tag) => tag !==
|
|
169
|
-
if (patch.enabled === false) tags.push(
|
|
170
|
-
if (patch.order !== void 0) tags.push(`${
|
|
175
|
+
let tags = (record.tags ?? []).filter((tag) => !tag.startsWith(PERSONAL_PLAYBOOK_ORDER_PREFIX));
|
|
176
|
+
if (patch.enabled === true) tags = tags.filter((tag) => tag !== PERSONAL_PLAYBOOK_DISABLED_TAG);
|
|
177
|
+
if (patch.enabled === false) tags.push(PERSONAL_PLAYBOOK_DISABLED_TAG);
|
|
178
|
+
if (patch.order !== void 0) tags.push(`${PERSONAL_PLAYBOOK_ORDER_PREFIX}${patch.order}`);
|
|
171
179
|
return [...new Set(tags)];
|
|
172
180
|
}
|
|
181
|
+
function parsePlaybookContext(value) {
|
|
182
|
+
if (value === void 0) return { context: {} };
|
|
183
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { error: "context must be an object" };
|
|
184
|
+
const input = value;
|
|
185
|
+
const context = {};
|
|
186
|
+
if ("channel" in input) {
|
|
187
|
+
if (input.channel !== null && (typeof input.channel !== "string" || !/^[a-z0-9_-]{1,40}$/i.test(input.channel))) return { error: "context.channel is invalid" };
|
|
188
|
+
context.channel = input.channel === null ? void 0 : String(input.channel);
|
|
189
|
+
}
|
|
190
|
+
if ("supportNeed" in input) {
|
|
191
|
+
if (input.supportNeed !== null && !PLAYBOOK_SUPPORT_NEEDS.has(String(input.supportNeed))) return { error: "context.supportNeed is invalid" };
|
|
192
|
+
context.supportNeed = input.supportNeed === null ? void 0 : input.supportNeed;
|
|
193
|
+
}
|
|
194
|
+
return { context };
|
|
195
|
+
}
|
|
173
196
|
function buildPersonalPlaybooks(records) {
|
|
174
197
|
return PLAYBOOK_IDS.map((id) => {
|
|
175
|
-
const rules = records.filter((record) => playbookForRecord(record) === id).sort((left, right) => playbookRuleOrder(left) - playbookRuleOrder(right) || left.updatedAt.localeCompare(right.updatedAt));
|
|
198
|
+
const rules = records.filter((record) => record.status === "active" && playbookForRecord(record) === id).sort((left, right) => playbookRuleOrder(left) - playbookRuleOrder(right) || left.updatedAt.localeCompare(right.updatedAt));
|
|
176
199
|
return {
|
|
177
200
|
id,
|
|
178
|
-
enabled: rules.some((record) => !record.tags?.includes(
|
|
201
|
+
enabled: rules.some((record) => !record.tags?.includes(PERSONAL_PLAYBOOK_DISABLED_TAG)),
|
|
179
202
|
rules: rules.map((record) => ({
|
|
180
203
|
id: record.id,
|
|
181
204
|
statement: record.content,
|
|
182
205
|
origin: record.explicitness,
|
|
183
|
-
enabled: !record.tags?.includes(
|
|
184
|
-
order: playbookRuleOrder(record)
|
|
206
|
+
enabled: !record.tags?.includes(PERSONAL_PLAYBOOK_DISABLED_TAG),
|
|
207
|
+
order: playbookRuleOrder(record),
|
|
208
|
+
context: personalPlaybookContext(record),
|
|
209
|
+
versions: playbookVersionChain(records, record.id).map((version) => ({
|
|
210
|
+
id: version.id,
|
|
211
|
+
statement: version.content,
|
|
212
|
+
updatedAt: version.updatedAt,
|
|
213
|
+
current: version.id === record.id
|
|
214
|
+
}))
|
|
185
215
|
})),
|
|
186
216
|
updatedAt: rules.map((record) => record.updatedAt).sort().at(-1)
|
|
187
217
|
};
|
|
@@ -195,7 +225,7 @@ function buildInsightSuggestions(records) {
|
|
|
195
225
|
id: record.id,
|
|
196
226
|
insight: record.content,
|
|
197
227
|
kind: record.kind,
|
|
198
|
-
action: record.kind === "routine" ? "make_repeatable" : "start_progress",
|
|
228
|
+
action: record.kind === "routine" ? "make_repeatable" : record.kind === "task_lesson" || record.kind === "derived_insight" ? "add_playbook" : "start_progress",
|
|
199
229
|
evidenceCount: record.evidence?.length ?? 0,
|
|
200
230
|
confidence: record.confidence,
|
|
201
231
|
sourceName: record.source.provider ?? "local"
|
|
@@ -216,11 +246,11 @@ function editableRecord(recordId) {
|
|
|
216
246
|
if (!record || !VISIBLE_STATUSES.has(record.status) || !isUserContextRecord(record)) return null;
|
|
217
247
|
return record;
|
|
218
248
|
}
|
|
219
|
-
function
|
|
220
|
-
return
|
|
221
|
-
id: record.id,
|
|
249
|
+
function memoryRecordInput(record) {
|
|
250
|
+
return {
|
|
222
251
|
providerId: record.source.provider ?? "local",
|
|
223
252
|
kind: record.kind,
|
|
253
|
+
userId: record.scope.userId,
|
|
224
254
|
sourceAgentId: record.provenance.sourceAgentId,
|
|
225
255
|
workspaceId: record.scope.workspaceId,
|
|
226
256
|
sessionKey: record.scope.sessionKey,
|
|
@@ -242,8 +272,41 @@ function preserveRecord(record, patch) {
|
|
|
242
272
|
validFrom: record.validFrom,
|
|
243
273
|
validTo: record.validTo,
|
|
244
274
|
supersedesRecordId: record.supersedesRecordId,
|
|
245
|
-
conflictGroupId: record.conflictGroupId
|
|
246
|
-
|
|
275
|
+
conflictGroupId: record.conflictGroupId
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function preserveRecord(record, patch) {
|
|
279
|
+
return upsertMemoryRecord({
|
|
280
|
+
...memoryRecordInput(record),
|
|
281
|
+
...patch,
|
|
282
|
+
id: record.id
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
function playbookVersionChain(records, recordId) {
|
|
286
|
+
const relatedIds = new Set([recordId]);
|
|
287
|
+
let previousSize = 0;
|
|
288
|
+
while (previousSize !== relatedIds.size) {
|
|
289
|
+
previousSize = relatedIds.size;
|
|
290
|
+
for (const record of records) {
|
|
291
|
+
if (!record.supersedesRecordId) continue;
|
|
292
|
+
if (relatedIds.has(record.id) || relatedIds.has(record.supersedesRecordId)) {
|
|
293
|
+
relatedIds.add(record.id);
|
|
294
|
+
relatedIds.add(record.supersedesRecordId);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return records.filter((record) => relatedIds.has(record.id) && playbookForRecord(record) !== void 0).sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt));
|
|
299
|
+
}
|
|
300
|
+
function versionPlaybookRule(record, patch) {
|
|
301
|
+
return upsertMemoryRecord({
|
|
302
|
+
...memoryRecordInput(record),
|
|
303
|
+
...patch,
|
|
304
|
+
status: "active",
|
|
305
|
+
supersedesRecordId: record.id,
|
|
306
|
+
source: {
|
|
307
|
+
provider: "local",
|
|
308
|
+
path: "you://playbook/version"
|
|
309
|
+
}
|
|
247
310
|
});
|
|
248
311
|
}
|
|
249
312
|
function registerYouRoutes(authenticated, deps) {
|
|
@@ -291,13 +354,14 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
291
354
|
}),
|
|
292
355
|
conflictGroups: buildConflictGroups(allUserContextRecords),
|
|
293
356
|
insights: buildInsightSuggestions(records),
|
|
294
|
-
playbooks: buildPersonalPlaybooks(
|
|
357
|
+
playbooks: buildPersonalPlaybooks(allUserContextRecords),
|
|
295
358
|
sources,
|
|
296
359
|
sourceRecommendations: buildGoalSourceRecommendations(sourceDefinitions.filter((definition) => definition.capabilities.includes("context") || definition.capabilities.includes("memory_source")), new Set(sourceInstances.map((instance) => instance.connectorId)), activeGoals),
|
|
297
360
|
controls: {
|
|
298
361
|
mode: config.userContext.memory.mode,
|
|
299
362
|
sensitiveWritePolicy: config.userContext.privacy.sensitiveWritePolicy
|
|
300
363
|
},
|
|
364
|
+
relationship: getRelationshipSettings(),
|
|
301
365
|
trust: {
|
|
302
366
|
defaultActionLevel: trustPolicy.defaultActionLevel,
|
|
303
367
|
levels: USER_TRUST_LEVELS,
|
|
@@ -305,6 +369,41 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
305
369
|
}
|
|
306
370
|
});
|
|
307
371
|
});
|
|
372
|
+
authenticated.patch("/api/you/relationship", deps.strictRateLimitMiddleware, async (c) => {
|
|
373
|
+
const body = await c.req.json().catch(() => null);
|
|
374
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return c.json({ error: "Invalid relationship settings" }, 400);
|
|
375
|
+
const input = body;
|
|
376
|
+
const patch = {};
|
|
377
|
+
if ("supportMode" in input) {
|
|
378
|
+
if (![
|
|
379
|
+
"efficient",
|
|
380
|
+
"coach",
|
|
381
|
+
"companion",
|
|
382
|
+
"auto"
|
|
383
|
+
].includes(String(input.supportMode))) return c.json({ error: "Invalid supportMode" }, 400);
|
|
384
|
+
patch.supportMode = input.supportMode;
|
|
385
|
+
}
|
|
386
|
+
if ("proactiveEnabled" in input) {
|
|
387
|
+
if (typeof input.proactiveEnabled !== "boolean") return c.json({ error: "proactiveEnabled must be boolean" }, 400);
|
|
388
|
+
patch.proactiveEnabled = input.proactiveEnabled;
|
|
389
|
+
}
|
|
390
|
+
for (const field of ["quietStart", "quietEnd"]) {
|
|
391
|
+
if (!(field in input)) continue;
|
|
392
|
+
const value = input[field];
|
|
393
|
+
if (value !== null && (typeof value !== "string" || !/^([01]\d|2[0-3]):[0-5]\d$/.test(value))) return c.json({ error: `${field} must use HH:mm` }, 400);
|
|
394
|
+
patch[field] = value === null ? void 0 : String(value);
|
|
395
|
+
}
|
|
396
|
+
for (const field of ["allowedTopics", "blockedTopics"]) {
|
|
397
|
+
if (!(field in input)) continue;
|
|
398
|
+
if (!Array.isArray(input[field]) || input[field].length > 20 || input[field].some((value) => typeof value !== "string" || !value.trim() || value.length > 80)) return c.json({ error: `${field} must contain up to 20 short topics` }, 400);
|
|
399
|
+
patch[field] = [...new Set(input[field].map((value) => value.trim()))];
|
|
400
|
+
}
|
|
401
|
+
if (Object.keys(patch).length === 0) return c.json({ error: "No relationship settings provided" }, 400);
|
|
402
|
+
return c.json({
|
|
403
|
+
ok: true,
|
|
404
|
+
relationship: updateRelationshipSettings(patch)
|
|
405
|
+
});
|
|
406
|
+
});
|
|
308
407
|
authenticated.get("/api/you/profile", async (c) => {
|
|
309
408
|
return c.json(await readProfileBundle(deps.service.currentConfig));
|
|
310
409
|
});
|
|
@@ -523,7 +622,7 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
523
622
|
limit: 500
|
|
524
623
|
}).filter(isUserContextRecord).filter((record) => playbookForRecord(record) === id);
|
|
525
624
|
runSqliteWriteTransaction(() => {
|
|
526
|
-
for (const record of active)
|
|
625
|
+
for (const record of active) versionPlaybookRule(record, { tags: patchPlaybookRuleTags(record, { enabled }) });
|
|
527
626
|
});
|
|
528
627
|
const current = active.map((record) => ({
|
|
529
628
|
...record,
|
|
@@ -540,6 +639,8 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
540
639
|
const body = await c.req.json().catch(() => ({}));
|
|
541
640
|
const statement = typeof body.statement === "string" ? body.statement.trim() : "";
|
|
542
641
|
if (!statement || statement.length > 5e3) return c.json({ error: "Rule statement is required" }, 400);
|
|
642
|
+
const parsedContext = parsePlaybookContext(body.context);
|
|
643
|
+
if ("error" in parsedContext) return c.json({ error: parsedContext.error }, 400);
|
|
543
644
|
const record = upsertMemoryRecord({
|
|
544
645
|
providerId: "local",
|
|
545
646
|
kind: id === "communication" ? "preference" : id === "execution" ? "task_lesson" : "routine",
|
|
@@ -550,11 +651,11 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
550
651
|
path: "you://playbook"
|
|
551
652
|
},
|
|
552
653
|
confidence: 1,
|
|
553
|
-
tags: [
|
|
654
|
+
tags: patchPersonalPlaybookContextTags([
|
|
554
655
|
"user-understanding",
|
|
555
|
-
|
|
556
|
-
`${
|
|
557
|
-
],
|
|
656
|
+
PERSONAL_PLAYBOOK_RULE_TAG,
|
|
657
|
+
`${PERSONAL_PLAYBOOK_ORDER_PREFIX}${Number.isInteger(body.order) ? body.order : 1e3}`
|
|
658
|
+
], parsedContext.context),
|
|
558
659
|
status: "active",
|
|
559
660
|
sensitivity: "normal",
|
|
560
661
|
explicitness: "explicit",
|
|
@@ -576,12 +677,14 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
576
677
|
if (!content || content.length > 5e3) return c.json({ error: "Rule statement is required" }, 400);
|
|
577
678
|
if (body.enabled !== void 0 && typeof body.enabled !== "boolean") return c.json({ error: "enabled must be boolean" }, 400);
|
|
578
679
|
if (body.order !== void 0 && (!Number.isInteger(body.order) || body.order < 0 || body.order > 1e4)) return c.json({ error: "order must be an integer between 0 and 10000" }, 400);
|
|
579
|
-
const
|
|
680
|
+
const parsedContext = parsePlaybookContext(body.context);
|
|
681
|
+
if ("error" in parsedContext) return c.json({ error: parsedContext.error }, 400);
|
|
682
|
+
const updated = versionPlaybookRule(record, {
|
|
580
683
|
content,
|
|
581
|
-
tags: patchPlaybookRuleTags(record, {
|
|
684
|
+
tags: patchPersonalPlaybookContextTags(patchPlaybookRuleTags(record, {
|
|
582
685
|
enabled: body.enabled,
|
|
583
686
|
order: body.order
|
|
584
|
-
}),
|
|
687
|
+
}), parsedContext.context),
|
|
585
688
|
explicitness: body.statement === void 0 ? record.explicitness : "explicit"
|
|
586
689
|
});
|
|
587
690
|
return c.json({
|
|
@@ -593,9 +696,32 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
593
696
|
const id = c.req.param("id");
|
|
594
697
|
const record = editableRecord(c.req.param("recordId"));
|
|
595
698
|
if (!PLAYBOOK_IDS.includes(id) || !record || playbookForRecord(record) !== id) return c.json({ error: "Playbook rule not found" }, 404);
|
|
596
|
-
|
|
699
|
+
preserveRecord(record, {
|
|
700
|
+
status: "archived",
|
|
701
|
+
validTo: (/* @__PURE__ */ new Date()).toISOString()
|
|
702
|
+
});
|
|
597
703
|
return c.json({ ok: true });
|
|
598
704
|
});
|
|
705
|
+
authenticated.post("/api/you/playbooks/:id/rules/:recordId/rollback", deps.strictRateLimitMiddleware, async (c) => {
|
|
706
|
+
const id = c.req.param("id");
|
|
707
|
+
const current = editableRecord(c.req.param("recordId"));
|
|
708
|
+
if (!PLAYBOOK_IDS.includes(id) || !current || playbookForRecord(current) !== id) return c.json({ error: "Playbook rule not found" }, 404);
|
|
709
|
+
const body = await c.req.json().catch(() => ({}));
|
|
710
|
+
const versionId = typeof body.versionId === "string" ? body.versionId : "";
|
|
711
|
+
const all = listAllUserContextRecords(ALL_MEMORY_STATUSES);
|
|
712
|
+
const target = playbookVersionChain(all, current.id).find((record) => record.id === versionId);
|
|
713
|
+
if (!target || target.id === current.id) return c.json({ error: "Previous version not found" }, 404);
|
|
714
|
+
const rolledBack = versionPlaybookRule(current, {
|
|
715
|
+
content: target.content,
|
|
716
|
+
tags: target.tags,
|
|
717
|
+
evidence: target.evidence,
|
|
718
|
+
explicitness: "explicit"
|
|
719
|
+
});
|
|
720
|
+
return c.json({
|
|
721
|
+
ok: true,
|
|
722
|
+
rule: buildPersonalPlaybooks([...all, rolledBack]).find((playbook) => playbook.id === id)?.rules.find((rule) => rule.id === rolledBack.id)
|
|
723
|
+
});
|
|
724
|
+
});
|
|
599
725
|
authenticated.patch("/api/you/insights/:id", deps.strictRateLimitMiddleware, async (c) => {
|
|
600
726
|
const config = deps.service.currentConfig;
|
|
601
727
|
const existing = editableRecord(c.req.param("id"));
|
|
@@ -622,6 +748,36 @@ function registerYouRoutes(authenticated, deps) {
|
|
|
622
748
|
status: "drafting",
|
|
623
749
|
href: buildRoutineAutomationDraftHref(existing)
|
|
624
750
|
});
|
|
751
|
+
if (existing.kind === "task_lesson" || existing.kind === "derived_insight") {
|
|
752
|
+
upsertMemoryRecord({
|
|
753
|
+
providerId: "local",
|
|
754
|
+
kind: "task_lesson",
|
|
755
|
+
sourceAgentId: selectedAgentId(config),
|
|
756
|
+
content: existing.content,
|
|
757
|
+
source: {
|
|
758
|
+
provider: "local",
|
|
759
|
+
path: "you://insight-proposal"
|
|
760
|
+
},
|
|
761
|
+
confidence: 1,
|
|
762
|
+
tags: [
|
|
763
|
+
"user-understanding",
|
|
764
|
+
PERSONAL_PLAYBOOK_RULE_TAG,
|
|
765
|
+
`${PERSONAL_PLAYBOOK_ORDER_PREFIX}1000`
|
|
766
|
+
],
|
|
767
|
+
status: "active",
|
|
768
|
+
sensitivity: existing.sensitivity,
|
|
769
|
+
explicitness: "explicit",
|
|
770
|
+
durability: "durable",
|
|
771
|
+
importance: existing.importance,
|
|
772
|
+
disclosurePolicy: existing.disclosurePolicy,
|
|
773
|
+
evidence: existing.evidence
|
|
774
|
+
});
|
|
775
|
+
preserveRecord(existing, { tags: [...new Set([...existing.tags ?? [], INSIGHT_ACCEPTED_TAG])] });
|
|
776
|
+
return c.json({
|
|
777
|
+
ok: true,
|
|
778
|
+
status: "saved"
|
|
779
|
+
});
|
|
780
|
+
}
|
|
625
781
|
const title = existing.content.trim().split(/\r?\n/)[0].slice(0, 72);
|
|
626
782
|
const uiLocale = body.uiLocale === "zh" ? "zh" : "en";
|
|
627
783
|
const contractDraft = await draftGoalContract({
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { inboundCorrelationMetadataFromAsyncLogContext, updateAsyncLogContext } from "../../utils/logger/context.js";
|
|
2
2
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
3
|
import { init_logger } from "../../utils/logger.js";
|
|
4
|
+
import { updateInteractionStateFromMessage } from "../../storage/sqlite/interaction-state-repository.js";
|
|
5
|
+
import { completeTaskOutcome, startTaskOutcome, updateTaskOutcome } from "../../storage/sqlite/task-outcome-repository.js";
|
|
6
|
+
import "../../storage/sqlite/index.js";
|
|
7
|
+
import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
|
|
8
|
+
import { recordExplicitRelationshipFollowUp } from "../../user-context/relationship-continuity.js";
|
|
4
9
|
import { formatAgentRunErrorForClient } from "../../agent/client-error-format.js";
|
|
5
10
|
import { prependEnvelopeTimestamp } from "../../channels/envelope-timestamp.js";
|
|
6
11
|
import { shouldSkipWebchatInboundByAbortCutoff } from "../../session/abort-cutoff.js";
|
|
@@ -11,6 +16,7 @@ import { coalesceThinkingDeltas } from "../chat-stream/thinking-delta-coalescer.
|
|
|
11
16
|
import crypto from "crypto";
|
|
12
17
|
//#region src/gateway/service/run-gateway-agent.ts
|
|
13
18
|
init_logger();
|
|
19
|
+
init_session_key();
|
|
14
20
|
const log = createLogger("Gateway:Service");
|
|
15
21
|
/**
|
|
16
22
|
* @param runOptions.signal — When set (e.g. client disconnect), aborts in-flight generation and persists partial output.
|
|
@@ -24,6 +30,11 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
24
30
|
const runId = crypto.randomUUID();
|
|
25
31
|
const { agentService, bus, runRelay, runAbortControllers, activeWebchatRunBySession, sessionIndex: sessionIndexFromDeps, emit } = deps;
|
|
26
32
|
const sessionIndex = sessionIndexFromDeps;
|
|
33
|
+
let taskOutcomeStarted = false;
|
|
34
|
+
let taskOutcomeStatus = "failed";
|
|
35
|
+
let taskOutcomeSummary = "Agent run ended unexpectedly";
|
|
36
|
+
let taskContract;
|
|
37
|
+
const taskEvidence = [];
|
|
27
38
|
let webchatSessionKey;
|
|
28
39
|
let webchatSessionId;
|
|
29
40
|
let webchatStaleSkip = false;
|
|
@@ -40,15 +51,65 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
40
51
|
runAbortControllers.set(runId, new AbortController());
|
|
41
52
|
}
|
|
42
53
|
const streamSessionKey = webchatSessionKey ?? chatId;
|
|
54
|
+
if (webchatSessionKey) {
|
|
55
|
+
const parsedSession = parseSessionKey(webchatSessionKey);
|
|
56
|
+
if (!parsedSession) throw new Error("Resolved webchat session key is invalid");
|
|
57
|
+
updateInteractionStateFromMessage({
|
|
58
|
+
sessionKey: webchatSessionKey,
|
|
59
|
+
message
|
|
60
|
+
});
|
|
61
|
+
recordExplicitRelationshipFollowUp({
|
|
62
|
+
sessionKey: webchatSessionKey,
|
|
63
|
+
sourceAgentId: parsedSession.agentId,
|
|
64
|
+
message
|
|
65
|
+
});
|
|
66
|
+
startTaskOutcome({
|
|
67
|
+
runId,
|
|
68
|
+
sessionKey: webchatSessionKey,
|
|
69
|
+
channel,
|
|
70
|
+
objective: message.trim()
|
|
71
|
+
});
|
|
72
|
+
taskOutcomeStarted = true;
|
|
73
|
+
}
|
|
43
74
|
const mapper = new ChatStreamMapper({
|
|
44
75
|
runId,
|
|
45
76
|
sessionKey: streamSessionKey,
|
|
46
77
|
channel
|
|
47
78
|
});
|
|
48
79
|
let registeredActiveWebchatRun = false;
|
|
80
|
+
const addTaskEvidence = (evidence) => {
|
|
81
|
+
if (taskEvidence.some((item) => item.kind === evidence.kind && item.title === evidence.title)) return;
|
|
82
|
+
taskEvidence.push(evidence);
|
|
83
|
+
};
|
|
84
|
+
const captureTaskEvent = (event) => {
|
|
85
|
+
if (event.type === "turn_plan") {
|
|
86
|
+
taskContract = {
|
|
87
|
+
objective: message.trim(),
|
|
88
|
+
deliverables: [],
|
|
89
|
+
acceptanceCriteria: event.payload.plan.map((item) => item.step),
|
|
90
|
+
constraints: [],
|
|
91
|
+
approvalRequired: []
|
|
92
|
+
};
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (event.type === "patch_applied") {
|
|
96
|
+
addTaskEvidence({
|
|
97
|
+
kind: "state",
|
|
98
|
+
title: "Changes applied",
|
|
99
|
+
summary: `${event.payload.added} additions and ${event.payload.removed} removals`
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (event.type === "command_completed" && event.payload.exitCode === 0 && /(^|\s)(test|vitest|jest|pytest|lint|typecheck|build)(\s|$|:)/i.test(event.payload.command)) addTaskEvidence({
|
|
104
|
+
kind: "test",
|
|
105
|
+
title: event.payload.command.slice(0, 120),
|
|
106
|
+
summary: event.payload.durationMs === void 0 ? "Command completed successfully" : `Command completed successfully in ${event.payload.durationMs} ms`
|
|
107
|
+
});
|
|
108
|
+
};
|
|
49
109
|
const publishStreamEvent = (event) => channel === "webchat" ? runRelay.publish(runId, event) ?? event : event;
|
|
50
110
|
const emitAndYield = function* (events) {
|
|
51
111
|
for (const event of events) {
|
|
112
|
+
if (taskOutcomeStarted) captureTaskEvent(event);
|
|
52
113
|
const relayedEvent = publishStreamEvent(event);
|
|
53
114
|
if (channel === "webchat") emit("agent.stream", {
|
|
54
115
|
sessionKey: streamSessionKey,
|
|
@@ -61,6 +122,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
61
122
|
try {
|
|
62
123
|
if (channel === "webchat" && webchatSessionKey) {
|
|
63
124
|
if (webchatStaleSkip) {
|
|
125
|
+
taskOutcomeStatus = "cancelled";
|
|
126
|
+
taskOutcomeSummary = "Stale inbound message skipped";
|
|
64
127
|
yield* emitAndYield(mapper.end("cancelled", "Stale inbound after abort (clientCreatedAtMs before cutoff)"));
|
|
65
128
|
runRelay.complete(runId);
|
|
66
129
|
runAbortControllers.delete(runId);
|
|
@@ -97,6 +160,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
97
160
|
for await (const event of coalesceThinkingDeltas(mappedEvents)) yield* emitAndYield([event]);
|
|
98
161
|
const endStatus = mergedSignal.aborted ? "cancelled" : "success";
|
|
99
162
|
const endSummary = mergedSignal.aborted ? "Interrupted" : "Message processed successfully";
|
|
163
|
+
taskOutcomeStatus = mergedSignal.aborted ? "cancelled" : "succeeded";
|
|
164
|
+
taskOutcomeSummary = endSummary;
|
|
100
165
|
yield* emitAndYield(mapper.end(endStatus, endSummary));
|
|
101
166
|
runRelay.complete(runId);
|
|
102
167
|
try {
|
|
@@ -121,6 +186,8 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
121
186
|
channel: "webchat"
|
|
122
187
|
}, `Agent processing failed: ${em}`);
|
|
123
188
|
streamError = em;
|
|
189
|
+
taskOutcomeStatus = "failed";
|
|
190
|
+
taskOutcomeSummary = em;
|
|
124
191
|
const errorContent = formatAgentRunErrorForClient(streamError);
|
|
125
192
|
yield* emitAndYield(mapper.error(errorContent));
|
|
126
193
|
yield* emitAndYield(mapper.end("error", streamError));
|
|
@@ -198,12 +265,16 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
198
265
|
payload: { messageId }
|
|
199
266
|
}]);
|
|
200
267
|
yield* emitAndYield(mapper.end("success", "Message processed"));
|
|
268
|
+
taskOutcomeStatus = "succeeded";
|
|
269
|
+
taskOutcomeSummary = "Message processed";
|
|
201
270
|
return {
|
|
202
271
|
status: "ok",
|
|
203
272
|
summary: "Message processed"
|
|
204
273
|
};
|
|
205
274
|
} catch (error) {
|
|
206
275
|
const em = error instanceof Error ? error.message : String(error);
|
|
276
|
+
taskOutcomeStatus = "failed";
|
|
277
|
+
taskOutcomeSummary = em;
|
|
207
278
|
log.error({
|
|
208
279
|
err: error,
|
|
209
280
|
errorMessage: em,
|
|
@@ -213,6 +284,19 @@ async function* runGatewayAgent(deps, message, channel, chatId, attachments, thi
|
|
|
213
284
|
chatId
|
|
214
285
|
}, `Agent run failed: ${em}`);
|
|
215
286
|
throw error;
|
|
287
|
+
} finally {
|
|
288
|
+
if (taskOutcomeStarted) {
|
|
289
|
+
updateTaskOutcome({
|
|
290
|
+
runId,
|
|
291
|
+
...taskContract ? { contract: taskContract } : {},
|
|
292
|
+
evidence: taskEvidence
|
|
293
|
+
});
|
|
294
|
+
completeTaskOutcome({
|
|
295
|
+
runId,
|
|
296
|
+
status: taskOutcomeStatus,
|
|
297
|
+
summary: taskOutcomeSummary
|
|
298
|
+
});
|
|
299
|
+
}
|
|
216
300
|
}
|
|
217
301
|
}
|
|
218
302
|
//#endregion
|
|
@@ -11,6 +11,7 @@ import { AgentRunRelay } from './agent-run-relay.js';
|
|
|
11
11
|
import { type EnqueueGoalRunOptions } from '../goals/index.js';
|
|
12
12
|
import { ProjectService } from '../projects/index.js';
|
|
13
13
|
import { LocalAppService } from '../local-apps/index.js';
|
|
14
|
+
import { type BrowserRecipeService } from '../browser/recipes/index.js';
|
|
14
15
|
import { GatewaySessionsApi } from './service/sessions-api.js';
|
|
15
16
|
import { GatewayMarketplaceService } from './service/marketplace-service.js';
|
|
16
17
|
import { GatewayAgentRunner } from './service/agent-runner.js';
|
|
@@ -26,6 +27,7 @@ export declare class GatewayService {
|
|
|
26
27
|
private _agentService;
|
|
27
28
|
private channelManager;
|
|
28
29
|
private automationService;
|
|
30
|
+
private browserRecipeService;
|
|
29
31
|
private notesService;
|
|
30
32
|
private extensionLoader;
|
|
31
33
|
private extensionMetadataSnapshot;
|
|
@@ -42,6 +44,7 @@ export declare class GatewayService {
|
|
|
42
44
|
private auth;
|
|
43
45
|
private readonly sse;
|
|
44
46
|
getConfig(): Config;
|
|
47
|
+
get browserRecipes(): BrowserRecipeService;
|
|
45
48
|
private stopGatewayUpdateCheck;
|
|
46
49
|
/** When set (e.g. by `GatewayServer`), `triggerGatewayProcessRestart` can stop HTTP then exit. */
|
|
47
50
|
private gatewayShutdownForRestart;
|
|
@@ -78,6 +78,8 @@ import { runBootstrapMigrationsSync } from "../migrations/runner.js";
|
|
|
78
78
|
import { MobileNotificationService } from "../mobile/notification-service.js";
|
|
79
79
|
import { LocalAppService } from "../local-apps/service.js";
|
|
80
80
|
import "../local-apps/index.js";
|
|
81
|
+
import { createRuntimeBrowserRecipeService } from "../browser/recipes/runtime-service.js";
|
|
82
|
+
import "../browser/recipes/index.js";
|
|
81
83
|
import { scheduleGatewayUpdateCheck } from "../infra/update-startup.js";
|
|
82
84
|
import { resolveChannelConnectDeferSet } from "./resolve-channel-connect-defer.js";
|
|
83
85
|
import { restartGatewayProcessWithFreshPid } from "./respawn.js";
|
|
@@ -108,6 +110,7 @@ var GatewayService = class {
|
|
|
108
110
|
_agentService = null;
|
|
109
111
|
channelManager;
|
|
110
112
|
automationService;
|
|
113
|
+
browserRecipeService = null;
|
|
111
114
|
notesService;
|
|
112
115
|
extensionLoader = null;
|
|
113
116
|
extensionMetadataSnapshot = null;
|
|
@@ -126,6 +129,13 @@ var GatewayService = class {
|
|
|
126
129
|
getConfig() {
|
|
127
130
|
return this.config;
|
|
128
131
|
}
|
|
132
|
+
get browserRecipes() {
|
|
133
|
+
if (!this.browserRecipeService) this.browserRecipeService = createRuntimeBrowserRecipeService({
|
|
134
|
+
getConfig: () => this.config,
|
|
135
|
+
emit: (type, payload) => this.emit(type, payload)
|
|
136
|
+
});
|
|
137
|
+
return this.browserRecipeService;
|
|
138
|
+
}
|
|
129
139
|
stopGatewayUpdateCheck = null;
|
|
130
140
|
/** When set (e.g. by `GatewayServer`), `triggerGatewayProcessRestart` can stop HTTP then exit. */
|
|
131
141
|
gatewayShutdownForRestart = null;
|
|
@@ -322,6 +332,7 @@ var GatewayService = class {
|
|
|
322
332
|
},
|
|
323
333
|
extensionRegistry: this.extensionLoader?.getRegistry(),
|
|
324
334
|
getAutomationService: () => this.automationService,
|
|
335
|
+
getBrowserRecipeService: () => this.browserRecipes,
|
|
325
336
|
getNotesService: () => this.notesService,
|
|
326
337
|
getProjectService: () => this.projects,
|
|
327
338
|
getWorkItemService: () => new WorkItemService(),
|
|
@@ -361,6 +372,7 @@ var GatewayService = class {
|
|
|
361
372
|
getDefaultAgentId: () => getDefaultAgentId(this.config),
|
|
362
373
|
getProjectWorkspaceRoot: (projectId) => this.projects.get(projectId)?.workspaceRoot,
|
|
363
374
|
workflowRunService: this.createWorkflowRunService(),
|
|
375
|
+
browserRecipeService: this.browserRecipes,
|
|
364
376
|
onRunCompleted: (run) => this.handleAutomationRunCompleted(run)
|
|
365
377
|
});
|
|
366
378
|
this._agentService.persistentGoals.setWebchatContinuationScheduler((sessionKey, message) => {
|
|
@@ -671,6 +683,7 @@ var GatewayService = class {
|
|
|
671
683
|
agentService: this.agentService,
|
|
672
684
|
getDefaultAgentId: () => getDefaultAgentId(this.config),
|
|
673
685
|
workflowRunService: this.createWorkflowRunService(),
|
|
686
|
+
browserRecipeService: this.browserRecipes,
|
|
674
687
|
onRunCompleted: (run) => this.handleAutomationRunCompleted(run)
|
|
675
688
|
});
|
|
676
689
|
this.startAutomationProductEventBridge();
|
|
@@ -822,6 +835,7 @@ var GatewayService = class {
|
|
|
822
835
|
this.connectorMemorySyncCoordinator = null;
|
|
823
836
|
this.connectedKnowledgeCoordinator?.stop();
|
|
824
837
|
this.connectedKnowledgeCoordinator = null;
|
|
838
|
+
await this.browserRecipeService?.shutdown();
|
|
825
839
|
if (this.browserExtensionRelease) {
|
|
826
840
|
await this.browserExtensionRelease();
|
|
827
841
|
this.browserExtensionRelease = null;
|
|
@@ -13,6 +13,8 @@ export declare function createProactiveInsight(input: {
|
|
|
13
13
|
whyItMatters: string;
|
|
14
14
|
nextAction: string;
|
|
15
15
|
evidence: ProactiveEvidence[];
|
|
16
|
+
valueScore: number;
|
|
17
|
+
valueReasons: string[];
|
|
16
18
|
nowMs?: number;
|
|
17
19
|
}): ProactiveInsight | null;
|
|
18
20
|
export declare function setProactiveInsightStatus(id: string, status: ProactiveInsightStatus, nowMs?: number, expectedStatus?: ProactiveInsightStatus): ProactiveInsight | null;
|
|
@@ -14,6 +14,8 @@ function insightFromRow(row) {
|
|
|
14
14
|
nextAction: row.next_action,
|
|
15
15
|
evidence: JSON.parse(row.evidence_json),
|
|
16
16
|
status: row.status,
|
|
17
|
+
valueScore: row.value_score,
|
|
18
|
+
valueReasons: JSON.parse(row.value_reasons_json),
|
|
17
19
|
createdAt: row.created_at,
|
|
18
20
|
updatedAt: row.updated_at
|
|
19
21
|
};
|
|
@@ -58,8 +60,9 @@ function createProactiveInsight(input) {
|
|
|
58
60
|
runSqliteWriteTransaction((db) => {
|
|
59
61
|
created = db.prepare(`INSERT OR IGNORE INTO proactive_insights (
|
|
60
62
|
insight_id, watch_id, run_id, kind, title, summary, why_it_matters,
|
|
61
|
-
next_action, evidence_json, content_hash, status,
|
|
62
|
-
|
|
63
|
+
next_action, evidence_json, content_hash, status, value_score,
|
|
64
|
+
value_reasons_json, created_at, updated_at
|
|
65
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'unread', ?, ?, ?, ?)`).run(id, input.watchId, input.runId, input.kind, input.title, input.summary, input.whyItMatters, input.nextAction, JSON.stringify(input.evidence), contentHash, input.valueScore, JSON.stringify(input.valueReasons), now, now).changes > 0;
|
|
63
66
|
});
|
|
64
67
|
return created ? listProactiveInsights({ limit: 100 }).find((item) => item.id === id) ?? null : null;
|
|
65
68
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { getRelationshipSettings, isProactiveSupportAllowed } from "../storage/sqlite/relationship-settings-repository.js";
|
|
4
|
+
import "../storage/sqlite/index.js";
|
|
3
5
|
import { getFocusWatchByAutomationId, recordFocusWatchRun } from "./watch-repository.js";
|
|
4
|
-
import { createProactiveInsight } from "./insight-repository.js";
|
|
6
|
+
import { createProactiveInsight, listProactiveInsights } from "./insight-repository.js";
|
|
7
|
+
import { scoreProactiveValue } from "./value-score.js";
|
|
5
8
|
//#region src/proactive/run-processor.ts
|
|
6
9
|
init_logger();
|
|
7
10
|
const log = createLogger("ProactiveRunProcessor");
|
|
@@ -105,6 +108,22 @@ function processFocusAutomationRun(run) {
|
|
|
105
108
|
nowMs: run.endedAtMs
|
|
106
109
|
})) return { handled: true };
|
|
107
110
|
if (!result.meaningful) return { handled: true };
|
|
111
|
+
if (!isProactiveSupportAllowed(getRelationshipSettings(), {
|
|
112
|
+
now: new Date(run.endedAtMs),
|
|
113
|
+
topic: watch.kind
|
|
114
|
+
})) return { handled: true };
|
|
115
|
+
const history = listProactiveInsights({
|
|
116
|
+
status: ["approved", "dismissed"],
|
|
117
|
+
limit: 50
|
|
118
|
+
});
|
|
119
|
+
const value = scoreProactiveValue({
|
|
120
|
+
kind: watch.kind,
|
|
121
|
+
evidenceCount: result.evidence.length,
|
|
122
|
+
hasNextAction: Boolean(result.nextAction),
|
|
123
|
+
approvedCount: history.filter((item) => item.status === "approved").length,
|
|
124
|
+
dismissedCount: history.filter((item) => item.status === "dismissed").length
|
|
125
|
+
});
|
|
126
|
+
if (!value.shouldDeliver) return { handled: true };
|
|
108
127
|
const insight = createProactiveInsight({
|
|
109
128
|
watchId: watch.id,
|
|
110
129
|
runId: run.id,
|
|
@@ -114,6 +133,8 @@ function processFocusAutomationRun(run) {
|
|
|
114
133
|
whyItMatters: result.whyItMatters,
|
|
115
134
|
nextAction: result.nextAction,
|
|
116
135
|
evidence: result.evidence,
|
|
136
|
+
valueScore: value.score,
|
|
137
|
+
valueReasons: value.reasons,
|
|
117
138
|
nowMs: run.endedAtMs
|
|
118
139
|
});
|
|
119
140
|
return insight ? {
|