@xopcai/xopc 0.0.173 → 0.0.175
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-ByVA0N5n.js → activity-store-CM6mQUS2.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CJ5HvqE7.js → agent-avatar-dicebear-eckyE9AY.js} +1 -1
- package/dist/gateway/static/root/assets/agents-D-OIB_r0.js +2 -0
- package/dist/gateway/static/root/assets/api-2SLLStKp.js +1 -0
- package/dist/gateway/static/root/assets/{api-BZtCKzg4.js → api-BfMRS6FX.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-B0oNNcFn.js → app-management-settings-panel-DYkzZQzZ.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DbIj4NQ1.js → appearance-settings-CDXXN57j.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-CuvFyvuu.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BICLQFWJ.js → archive-plugin-k909a76t.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DV3PteSU.js → attachment-load-CqNzyhdJ.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-CZUImis0.js → automation-suggestion-card-snNG6u0v.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-DetGVTjI.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-D6zkab6N.js → binary-plugins-PfQ9ZHDF.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-zCzoQI-g.js → block-editor-Xrw-DnE_.js} +6 -6
- package/dist/gateway/static/root/assets/browser-settings-page-G92AdEnX.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-CY3X83xQ.js → browser-workflow-inputs-DJPF2lUY.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DDRtZLuM.js → browser-workflows-page-BoXs4pgc.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-nS_AMN1K.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-pYLW6P7g.js → capability-presets-api-BgY-Ysmi.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DIO8ZNHW.js +1 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-DxyOH3BO.js → channel-recipient-api-D32T1EJM.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-4Im3vtnO.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-CMctpuqb.js +1 -0
- package/dist/gateway/static/root/assets/{connector-logo-BgANwjt-.js → connector-logo-C-l8haIK.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-vL3SjHSc.js +2 -0
- package/dist/gateway/static/root/assets/copy-VueTIC2x.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-BPjQbPeA.js → desktop-pet-CwOI_Hei.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-8CaU1Mhm.js → desktop-pet-settings-Cldo_pA3.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-BtNRUvzM.js → directory-picker-path-field-CMASXbgJ.js} +1 -1
- package/dist/gateway/static/root/assets/dreaming-settings-BnMx02w0.js +3 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-DFjTfx6f.js → extension-debug-page-mUFs3ign.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-NyEYtWWg.js → extension-page-BsFBOZ5N.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BynTCfgf.js → extension-settings-page-CTEoovnV.js} +1 -1
- package/dist/gateway/static/root/assets/focus-detail-page-CCaZthpU.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-api-BzOWImvU.js → gateway-config-api-Bwx-EetD.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DXepE_Jw.js → gateway-settings-CvgyqhR_.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-C2JXXtwg.js → gateway-startup-retry-C8f5KwkT.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-create-dialog-ClOZyG52.js → goal-create-dialog-Bhynl9LN.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-ChS2rU0w.js +4 -0
- package/dist/gateway/static/root/assets/{goals-config-api-CU3JR9MI.js → goals-config-api-CUnfbgHa.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-BAS_liXl.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-DSZguLEx.js → goals-settings-Bkk-tOcf.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-KRkYziEF.js → heartbeat-settings-D9Pldf5E.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-Y-n6TaZ_.js → image-generation-api-D7aCMgOv.js} +1 -1
- package/dist/gateway/static/root/assets/index-DJ5vdaHk.css +1 -0
- package/dist/gateway/static/root/assets/index-TnouSpay.js +212 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CwrQv952.js → keyboard-shortcuts-settings-CBhtXhHb.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-HQeu_F1C.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DtITcS4K.js → local-apps-page-BtJGF3M8.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-Ccv7tH8B.js → locale-store-DO-u1yS7.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-0lvwfLAA.js +7 -0
- package/dist/gateway/static/root/assets/{markdown-split-D1oZlq1m.js → markdown-split-BGPaeTch.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BKz5V32t.js → media-plugins-C_Cx8v6u.js} +1 -1
- package/dist/gateway/static/root/assets/messages-BP8aQX-5.js +3 -0
- package/dist/gateway/static/root/assets/{notes-page-DLekBQPa.js → notes-page-CIYy5BKF.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-_FgNPlOx.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-pT4nLfqS.js → page-tabs-C2vsdfJO.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-OtAiaJm2.js → preview-open-alternatives-D_VT83bW.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-CfryBKD9.js → product-open-page-BNP9kZ3Q.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-MNi-3mZU.js +1 -0
- package/dist/gateway/static/root/assets/{projects-page-3ubcbqHr.js → projects-page-xx8nUKZO.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-H5DSn2bR.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-nP1SB3Lf.js → save-bar-controls-BJL6Xb-F.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-OEQTsUNz.js → schedule-field-CxCPSLbu.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-DIcAa7CJ.js → schema-form-Cao1wGbk.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CMQsupwM.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-OBUdG6bV.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-BxNcTbYO.js → settings-form-section-9pgClEud.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-Dpdxu4sf.js → settings-loading-skeleton-CQz0gEUK.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-DwPeOm1c.js → settings-page-DgsMzZLm.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-CqirFmMn.js → settings-page-layout-BhqupMfG.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-B7BsWxJt.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-D72gYeux.js → share-preview-page-CC4dQsQN.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-Bhz21P05.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CBP-UB88.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-A0rNObNB.js +2 -0
- package/dist/gateway/static/root/assets/skills-page.utils-CF4AYPQg.js +1 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-U0tBgW46.js → system-settings-panel-CzZHWI4u.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-DCKDVPFF.js → theme-store-BZWNdSZC.js} +1 -1
- package/dist/gateway/static/root/assets/time-picker-BC922Mdg.js +1 -0
- package/dist/gateway/static/root/assets/{typed-models-lib-D0XCOCAM.js → typed-models-lib-C1S-B1pk.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-mq_Inao2.js → use-channel-catalog-DTiLxcLF.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-8XdpiAyP.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-CKaDitO6.js → voice-api-key-field-CtIYRNfI.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-page-DBer86NF.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-BUPyfYaq.js +1 -0
- package/dist/gateway/static/root/assets/work-page-G8phwwI1.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-s_kS_FYA.js → workflow-run-setup-panel-IKxqDAXw.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-CNls7g6v.js +11 -0
- package/dist/gateway/static/root/index.html +7 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +1 -1
- package/dist/src/agent/service.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/skills/index.d.ts +2 -0
- package/dist/src/agent/skills/index.js +14 -5
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/test-framework.js +1 -1
- package/dist/src/automations/domain/defaults.d.ts +1 -0
- package/dist/src/automations/domain/defaults.js +4 -0
- package/dist/src/automations/domain/index.d.ts +1 -0
- package/dist/src/automations/domain/index.js +2 -1
- package/dist/src/automations/index.js +2 -1
- package/dist/src/automations/service/action-executor.js +2 -2
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/skills.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/focuses/candidate-repository.d.ts +15 -0
- package/dist/src/focuses/candidate-repository.js +91 -0
- package/dist/src/focuses/index.d.ts +7 -0
- package/dist/src/focuses/index.js +7 -0
- package/dist/src/focuses/insight-repository.d.ts +22 -0
- package/dist/src/focuses/insight-repository.js +77 -0
- package/dist/src/focuses/prompts.d.ts +2 -0
- package/dist/src/focuses/prompts.js +18 -0
- package/dist/src/focuses/reconciler.d.ts +5 -0
- package/dist/src/focuses/reconciler.js +26 -0
- package/dist/src/focuses/repository.d.ts +61 -0
- package/dist/src/focuses/repository.js +214 -0
- package/dist/src/focuses/run-processor.d.ts +18 -0
- package/dist/src/focuses/run-processor.js +162 -0
- package/dist/src/focuses/service.d.ts +42 -0
- package/dist/src/focuses/service.js +241 -0
- package/dist/src/focuses/types.d.ts +89 -0
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/routes/focuses.d.ts +3 -0
- package/dist/src/gateway/hono/routes/focuses.js +319 -0
- package/dist/src/gateway/hono/routes/home.d.ts +16 -3
- package/dist/src/gateway/hono/routes/home.js +113 -42
- package/dist/src/gateway/hono/routes/index.js +4 -0
- package/dist/src/gateway/hono/routes/local-apps.js +1 -1
- package/dist/src/gateway/hono/routes/project-skills.d.ts +3 -0
- package/dist/src/gateway/hono/routes/project-skills.js +119 -0
- package/dist/src/gateway/hono/routes/projects.js +2 -103
- package/dist/src/gateway/hono/routes/work-discovery.js +0 -239
- package/dist/src/gateway/service.d.ts +1 -1
- package/dist/src/gateway/service.js +17 -13
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/projects/index.d.ts +1 -0
- package/dist/src/projects/index.js +2 -1
- package/dist/src/projects/project-skill-service.d.ts +67 -0
- package/dist/src/projects/project-skill-service.js +131 -0
- package/dist/src/storage/sqlite/home-attention-repository.d.ts +3 -0
- package/dist/src/storage/sqlite/home-attention-repository.js +21 -0
- 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/066_first_class_focuses.sql +126 -0
- package/dist/src/storage/sqlite/migrations/067_home_attention_acknowledgements.sql +9 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +10 -0
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/work-discovery/index.d.ts +0 -2
- package/dist/src/work-discovery/index.js +1 -3
- package/dist/src/work-discovery/service.d.ts +0 -30
- package/dist/src/work-discovery/service.js +1 -35
- package/dist/src/work-discovery/thread-service.d.ts +5 -0
- package/dist/src/work-discovery/thread-service.js +36 -88
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents--TQ9jM_1.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-BDsoZDEn.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-CHrNcppN.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-BQoRuQzH.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BOcU0qeM.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-CJ1F_hlX.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-C4vDwRil.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-B0Pgq5x2.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-D6JEqDEj.js +0 -2
- package/dist/gateway/static/root/assets/dreaming-settings-Byv-h8XZ.js +0 -3
- package/dist/gateway/static/root/assets/goal-detail-page-UbZB77De.js +0 -4
- package/dist/gateway/static/root/assets/goals-page-GMqV8Fwv.js +0 -2
- package/dist/gateway/static/root/assets/index-BCkNJ5cR.css +0 -1
- package/dist/gateway/static/root/assets/index-CAZ9343h.js +0 -212
- package/dist/gateway/static/root/assets/local-app-workbench-page-m5HEyrHT.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-Bf_nk75f.js +0 -7
- package/dist/gateway/static/root/assets/messages-DWrg3c4K.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-BTDmprHM.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-C7kntu4H.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DoUkN3ik.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-ElAAlZ-R.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CQn_KBqr.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DX_LdcTN.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-nSfe-5xK.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-1tYpZrJf.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-BUJl8LJG.js +0 -2
- package/dist/gateway/static/root/assets/time-picker-BpiBF5-d.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-BOC6Hn19.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-DWGYp5yV.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-CpeWcpSp.js +0 -1
- package/dist/gateway/static/root/assets/work-page-MsEKzmSt.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-ByhHaUHB.js +0 -11
- package/dist/src/proactive/calendar-signals.d.ts +0 -4
- package/dist/src/proactive/calendar-signals.js +0 -120
- package/dist/src/proactive/focus-service.d.ts +0 -62
- package/dist/src/proactive/focus-service.js +0 -173
- package/dist/src/proactive/index.d.ts +0 -7
- package/dist/src/proactive/index.js +0 -7
- package/dist/src/proactive/insight-repository.d.ts +0 -21
- package/dist/src/proactive/insight-repository.js +0 -109
- package/dist/src/proactive/run-processor.d.ts +0 -19
- package/dist/src/proactive/run-processor.js +0 -146
- package/dist/src/proactive/trial-expiry-reconciler.d.ts +0 -5
- package/dist/src/proactive/trial-expiry-reconciler.js +0 -30
- package/dist/src/proactive/types.d.ts +0 -66
- package/dist/src/proactive/value-score.d.ts +0 -13
- package/dist/src/proactive/value-score.js +0 -30
- package/dist/src/proactive/watch-repository.d.ts +0 -28
- package/dist/src/proactive/watch-repository.js +0 -129
- package/dist/src/work-discovery/governance.d.ts +0 -25
- package/dist/src/work-discovery/governance.js +0 -96
- package/dist/src/work-discovery/thread-repository.d.ts +0 -34
- package/dist/src/work-discovery/thread-repository.js +0 -112
- /package/dist/src/{proactive → focuses}/types.js +0 -0
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import type { Hono } from 'hono';
|
|
2
|
+
import { type HomeAttentionSubjectKind } from '../../../storage/sqlite/index.js';
|
|
2
3
|
import type { AuthenticatedRouteDeps } from './deps.js';
|
|
3
|
-
type HomeDecisionKind = 'work_item' | 'goal' | '
|
|
4
|
-
type HomeDecisionReason = 'needs_input' | 'in_review' | 'blocked' | 'overdue' | 'due_soon' | '
|
|
4
|
+
type HomeDecisionKind = 'work_item' | 'goal' | 'connector_approval' | 'goal_evidence';
|
|
5
|
+
type HomeDecisionReason = 'needs_input' | 'in_review' | 'blocked' | 'overdue' | 'due_soon' | 'approval_required';
|
|
6
|
+
type HomeAttention = {
|
|
7
|
+
id: string;
|
|
8
|
+
kind: HomeAttentionSubjectKind;
|
|
9
|
+
runId: string;
|
|
10
|
+
title: string;
|
|
11
|
+
detail: string;
|
|
12
|
+
reason: 'run_failed' | 'run_timeout';
|
|
13
|
+
href: string;
|
|
14
|
+
updatedAt: number;
|
|
15
|
+
sessionKey?: string;
|
|
16
|
+
};
|
|
5
17
|
type HomeDecision = {
|
|
6
18
|
id: string;
|
|
7
19
|
kind: HomeDecisionKind;
|
|
@@ -39,6 +51,7 @@ type HomeAutomation = {
|
|
|
39
51
|
export declare function buildHomeBriefing(input: {
|
|
40
52
|
locale?: string;
|
|
41
53
|
decisions: HomeDecision[];
|
|
54
|
+
attention: HomeAttention[];
|
|
42
55
|
activeWorkCount: number;
|
|
43
56
|
activeWorkflowCount: number;
|
|
44
57
|
activeGoalCount: number;
|
|
@@ -68,7 +81,7 @@ export declare function buildHomeBriefing(input: {
|
|
|
68
81
|
* - recentSessions: last 5 active AI sessions (threads)
|
|
69
82
|
* - activeAgent: default agent identity for this gateway
|
|
70
83
|
* - gateway: readiness + public tunnel status
|
|
71
|
-
* - workflowRuns: active
|
|
84
|
+
* - workflowRuns: active and recent workflow runs
|
|
72
85
|
* - upcomingAutomations: upcoming enabled automations
|
|
73
86
|
* - recentAutomationRuns: latest automation executions
|
|
74
87
|
*/
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
import { acknowledgeHomeAttention, isHomeAttentionAcknowledged } from "../../../storage/sqlite/home-attention-repository.js";
|
|
1
2
|
import { decideConnectorApproval, listConnectorApprovals } from "../../../storage/sqlite/connector-repository.js";
|
|
2
3
|
import "../../../storage/sqlite/index.js";
|
|
3
4
|
import { GoalService } from "../../../goals/goal-service.js";
|
|
4
5
|
import "../../../goals/index.js";
|
|
6
|
+
import "../../../automations/domain/defaults.js";
|
|
7
|
+
import "../../../automations/index.js";
|
|
5
8
|
import { listGatewayAgents } from "../../agents-admin.js";
|
|
6
|
-
import { listFocusCalendarSignals } from "../../../proactive/calendar-signals.js";
|
|
7
|
-
import { FocusService } from "../../../proactive/focus-service.js";
|
|
8
|
-
import { listProactiveInsights } from "../../../proactive/insight-repository.js";
|
|
9
|
-
import "../../../proactive/index.js";
|
|
10
9
|
import { WorkItemService } from "../../../work-items/work-item-service.js";
|
|
11
10
|
import "../../../work-items/index.js";
|
|
12
11
|
import { getTunnelService } from "../../../tunnel/tunnel-service.js";
|
|
@@ -87,6 +86,19 @@ function toHomeAutomationRun(run) {
|
|
|
87
86
|
workflowRunId: run.workflowRunId
|
|
88
87
|
};
|
|
89
88
|
}
|
|
89
|
+
function effectiveAutomationTimeoutSeconds(run, automation) {
|
|
90
|
+
return run.actionSnapshot.timeoutSeconds ?? automation?.reliability?.timeoutSeconds ?? 300;
|
|
91
|
+
}
|
|
92
|
+
function attentionDetail(kind, status, locale, timeoutSeconds) {
|
|
93
|
+
const isChinese = locale?.toLowerCase().startsWith("zh") ?? false;
|
|
94
|
+
if (status === "timeout") {
|
|
95
|
+
const seconds = timeoutSeconds ?? 300;
|
|
96
|
+
const duration = seconds % 60 === 0 ? `${seconds / 60} ${isChinese ? "分钟" : seconds === 60 ? "minute" : "minutes"}` : `${seconds} ${isChinese ? "秒" : seconds === 1 ? "second" : "seconds"}`;
|
|
97
|
+
return isChinese ? `运行超过 ${duration},系统已停止本次执行。` : `The run exceeded ${duration} and was stopped.`;
|
|
98
|
+
}
|
|
99
|
+
if (isChinese) return kind === "automation_run" ? "自动化未能完成,请查看详情后重试。" : "工作流未能完成,请查看详情后重试。";
|
|
100
|
+
return kind === "automation_run" ? "The automation did not complete. Review the details and retry." : "The workflow did not complete. Review the details and retry.";
|
|
101
|
+
}
|
|
90
102
|
function decisionFromGoal(goal, projectName) {
|
|
91
103
|
if (goal.status !== "needs_input" && goal.status !== "blocked") return null;
|
|
92
104
|
return {
|
|
@@ -128,7 +140,8 @@ function decisionFromWorkItem(item, projectName, nowMs) {
|
|
|
128
140
|
function buildHomeBriefing(input) {
|
|
129
141
|
const isChinese = input.locale?.toLowerCase().startsWith("zh") ?? false;
|
|
130
142
|
const movingCount = input.activeWorkCount + input.activeWorkflowCount + input.activeGoalCount;
|
|
131
|
-
const
|
|
143
|
+
const attentionCount = input.decisions.length + input.attention.length;
|
|
144
|
+
const summary = attentionCount > 0 ? isChinese ? movingCount > 0 ? `有 ${attentionCount} 件事需要你处理;我正在继续推进 ${movingCount} 件工作。` : `有 ${attentionCount} 件事需要你处理。` : movingCount > 0 ? `${attentionCount} ${attentionCount === 1 ? "item needs" : "items need"} your attention; I’m continuing ${movingCount} in the background.` : `${attentionCount} ${attentionCount === 1 ? "item needs" : "items need"} your attention.` : movingCount > 0 ? isChinese ? `目前没有事情需要你处理;我正在继续推进 ${movingCount} 件工作。` : `Nothing needs you right now; I’m continuing ${movingCount} ${movingCount === 1 ? "item" : "items"} in the background.` : isChinese ? "今天还没有正在推进的事项。把想要的结果交给我,我会从这里开始。" : "Nothing is moving yet today. Hand me an outcome and I’ll take it from here.";
|
|
132
145
|
return {
|
|
133
146
|
generatedAt: input.nowMs,
|
|
134
147
|
summary,
|
|
@@ -153,14 +166,13 @@ function buildHomeBriefing(input) {
|
|
|
153
166
|
* - recentSessions: last 5 active AI sessions (threads)
|
|
154
167
|
* - activeAgent: default agent identity for this gateway
|
|
155
168
|
* - gateway: readiness + public tunnel status
|
|
156
|
-
* - workflowRuns: active
|
|
169
|
+
* - workflowRuns: active and recent workflow runs
|
|
157
170
|
* - upcomingAutomations: upcoming enabled automations
|
|
158
171
|
* - recentAutomationRuns: latest automation executions
|
|
159
172
|
*/
|
|
160
173
|
function registerHomeRoutes(authenticated, deps) {
|
|
161
174
|
const { service } = deps;
|
|
162
175
|
const goals = new GoalService();
|
|
163
|
-
const focuses = new FocusService(service.automationServiceInstance);
|
|
164
176
|
authenticated.get("/api/home", async (c) => {
|
|
165
177
|
const notes = service.notesServiceInstance;
|
|
166
178
|
const sessions = service.sessions;
|
|
@@ -171,8 +183,7 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
171
183
|
const health = service.getHealth();
|
|
172
184
|
const workItems = new WorkItemService();
|
|
173
185
|
const nowMs = Date.now();
|
|
174
|
-
const
|
|
175
|
-
const [recentlyOpened, inbox, pendingTasks, recentSessions, workflowRuns, automations, automationRuns, projects, allWorkItems, activeGoals, connectorApprovals, proactiveInsights, calendarSignals] = await Promise.all([
|
|
186
|
+
const [recentlyOpened, inbox, pendingTasks, recentSessions, workflowRuns, automations, automationRuns, projects, allWorkItems, activeGoals, connectorApprovals] = await Promise.all([
|
|
176
187
|
notes.listNotes({
|
|
177
188
|
sortBy: "lastOpenedAt",
|
|
178
189
|
sortOrder: "desc",
|
|
@@ -189,9 +200,10 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
189
200
|
limit: 10
|
|
190
201
|
}),
|
|
191
202
|
sessions.listSessions({
|
|
203
|
+
channel: "webchat",
|
|
192
204
|
sortBy: "updatedAt",
|
|
193
205
|
sortOrder: "desc",
|
|
194
|
-
limit:
|
|
206
|
+
limit: 50
|
|
195
207
|
}),
|
|
196
208
|
workflowRunStore.listRunSummaries(20),
|
|
197
209
|
service.automationServiceInstance.list(),
|
|
@@ -211,14 +223,15 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
211
223
|
principalId: "local-owner",
|
|
212
224
|
status: "pending",
|
|
213
225
|
limit: 100
|
|
214
|
-
}))
|
|
215
|
-
Promise.resolve(listProactiveInsights({
|
|
216
|
-
status: ["unread"],
|
|
217
|
-
limit: 10
|
|
218
|
-
})),
|
|
219
|
-
Promise.resolve(listFocusCalendarSignals(focusViews, nowMs))
|
|
226
|
+
}))
|
|
220
227
|
]);
|
|
221
228
|
const projectsById = new Map(projects.items.map((project) => [project.id, project]));
|
|
229
|
+
const workChats = recentSessions.items.filter((session) => (session.messageCount ?? 0) > 0).map((session) => ({
|
|
230
|
+
key: session.key,
|
|
231
|
+
name: session.name || "Conversation",
|
|
232
|
+
updatedAt: session.updatedAt,
|
|
233
|
+
active: sessions.getActiveRun(session.key).active
|
|
234
|
+
}));
|
|
222
235
|
const activeWorkItems = allWorkItems.items.filter((item) => item.status !== "done" && item.status !== "cancelled").sort((left, right) => {
|
|
223
236
|
return workItemAttentionRank(left, nowMs) - workItemAttentionRank(right, nowMs) || right.updatedAt - left.updatedAt;
|
|
224
237
|
});
|
|
@@ -226,33 +239,14 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
226
239
|
const currentWorkItems = activeWorkItems.slice(0, 30).map((item) => toHomeWorkItem(item, projectsById.get(item.projectId)?.name ?? "Project"));
|
|
227
240
|
const recentlyCompletedWorkItems = allWorkItems.items.filter((item) => item.status === "done").sort((left, right) => (right.completedAt ?? right.updatedAt) - (left.completedAt ?? left.updatedAt)).slice(0, 8).map((item) => toHomeWorkItem(item, projectsById.get(item.projectId)?.name ?? "Project"));
|
|
228
241
|
const activeWorkflowRuns = workflowRuns.filter((run) => run.status === "queued" || run.status === "running").slice(0, 5).map(toHomeWorkflowRun);
|
|
229
|
-
const
|
|
242
|
+
const failedWorkflowRuns = workflowRuns.filter((run) => run.status === "failed" || run.status === "timeout").slice(0, 5).map(toHomeWorkflowRun);
|
|
230
243
|
const recentWorkflowRuns = workflowRuns.slice(0, 5).map(toHomeWorkflowRun);
|
|
231
244
|
const upcomingAutomations = automations.map(toHomeAutomation).filter((automation) => Boolean(automation)).sort((a, b) => Date.parse(a.nextRunAt) - Date.parse(b.nextRunAt)).slice(0, 5);
|
|
232
245
|
const latestAutomationRuns = [...automationRuns].sort((left, right) => right.createdAtMs - left.createdAtMs).filter((run, index, all) => all.findIndex((candidate) => candidate.automationId === run.automationId) === index);
|
|
246
|
+
const automationsById = new Map(automations.map((automation) => [automation.id, automation]));
|
|
233
247
|
const decisions = [
|
|
234
248
|
...activeWorkItems.map((item) => decisionFromWorkItem(item, projectsById.get(item.projectId)?.name ?? "Project", nowMs)).filter((item) => Boolean(item)),
|
|
235
249
|
...activeGoals.map((goal) => decisionFromGoal(goal, goal.projectId ? projectsById.get(goal.projectId)?.name : void 0)).filter((item) => Boolean(item)),
|
|
236
|
-
...attentionWorkflowRuns.map((run) => ({
|
|
237
|
-
id: `workflow:${run.id}`,
|
|
238
|
-
kind: "workflow_run",
|
|
239
|
-
title: run.title,
|
|
240
|
-
detail: run.status,
|
|
241
|
-
reason: "run_failed",
|
|
242
|
-
urgency: "now",
|
|
243
|
-
href: `/workflows?runId=${encodeURIComponent(run.id)}`,
|
|
244
|
-
updatedAt: run.completedAtMs ?? run.startedAtMs ?? run.createdAtMs
|
|
245
|
-
})),
|
|
246
|
-
...latestAutomationRuns.filter((run) => run.status === "failed" || run.status === "timeout").map((run) => ({
|
|
247
|
-
id: `automation:${run.id}`,
|
|
248
|
-
kind: "automation_run",
|
|
249
|
-
title: run.automationName || run.automationId,
|
|
250
|
-
detail: run.error || run.summary,
|
|
251
|
-
reason: "run_failed",
|
|
252
|
-
urgency: "now",
|
|
253
|
-
href: "/automations",
|
|
254
|
-
updatedAt: run.endedAtMs ?? run.startedAtMs ?? run.createdAtMs
|
|
255
|
-
})),
|
|
256
250
|
...connectorApprovals.filter((approval) => Date.parse(approval.expiresAt) > nowMs).map((approval) => ({
|
|
257
251
|
id: `connector-approval:${approval.id}`,
|
|
258
252
|
kind: "connector_approval",
|
|
@@ -287,6 +281,28 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
287
281
|
].sort((left, right) => {
|
|
288
282
|
return (left.urgency === "now" ? 0 : 1) - (right.urgency === "now" ? 0 : 1) || right.updatedAt - left.updatedAt;
|
|
289
283
|
}).slice(0, 20);
|
|
284
|
+
const locale = c.req.query("locale");
|
|
285
|
+
const attention = [...failedWorkflowRuns.filter((run) => !isHomeAttentionAcknowledged("workflow_run", run.id)).map((run) => ({
|
|
286
|
+
id: `workflow_run:${run.id}`,
|
|
287
|
+
kind: "workflow_run",
|
|
288
|
+
runId: run.id,
|
|
289
|
+
title: run.title,
|
|
290
|
+
detail: attentionDetail("workflow_run", run.status === "timeout" ? "timeout" : "failed", locale),
|
|
291
|
+
reason: run.status === "timeout" ? "run_timeout" : "run_failed",
|
|
292
|
+
href: `/workflows?runId=${encodeURIComponent(run.id)}`,
|
|
293
|
+
updatedAt: run.completedAtMs ?? run.startedAtMs ?? run.createdAtMs,
|
|
294
|
+
sessionKey: run.sessionKey
|
|
295
|
+
})), ...latestAutomationRuns.filter((run) => run.status === "failed" || run.status === "timeout").filter((run) => !isHomeAttentionAcknowledged("automation_run", run.id)).map((run) => ({
|
|
296
|
+
id: `automation_run:${run.id}`,
|
|
297
|
+
kind: "automation_run",
|
|
298
|
+
runId: run.id,
|
|
299
|
+
title: run.automationName || run.automationId,
|
|
300
|
+
detail: attentionDetail("automation_run", run.status === "timeout" ? "timeout" : "failed", locale, effectiveAutomationTimeoutSeconds(run, automationsById.get(run.automationId))),
|
|
301
|
+
reason: run.status === "timeout" ? "run_timeout" : "run_failed",
|
|
302
|
+
href: `/automations?run=${encodeURIComponent(run.id)}`,
|
|
303
|
+
updatedAt: run.endedAtMs ?? run.startedAtMs ?? run.createdAtMs,
|
|
304
|
+
sessionKey: run.sessionKey
|
|
305
|
+
}))].sort((left, right) => right.updatedAt - left.updatedAt).slice(0, 10);
|
|
290
306
|
const wins = [
|
|
291
307
|
...recentlyCompletedWorkItems.map((item) => ({
|
|
292
308
|
id: `work:${item.id}`,
|
|
@@ -311,8 +327,9 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
311
327
|
}))
|
|
312
328
|
].sort((left, right) => right.completedAt - left.completedAt);
|
|
313
329
|
const briefing = buildHomeBriefing({
|
|
314
|
-
locale
|
|
330
|
+
locale,
|
|
315
331
|
decisions,
|
|
332
|
+
attention,
|
|
316
333
|
activeWorkCount: activeWorkItems.filter((item) => item.status === "in_progress").length,
|
|
317
334
|
activeWorkflowCount: activeWorkflowRuns.length,
|
|
318
335
|
activeGoalCount: activeGoals.filter((goal) => goal.status === "active").length,
|
|
@@ -325,7 +342,7 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
325
342
|
inboxCount: inbox.total,
|
|
326
343
|
pendingTasks: pendingTasks.items,
|
|
327
344
|
pendingTaskCount: pendingTasks.total,
|
|
328
|
-
recentSessions: recentSessions.items,
|
|
345
|
+
recentSessions: recentSessions.items.slice(0, 5),
|
|
329
346
|
activeAgent: defaultAgent ? {
|
|
330
347
|
id: defaultAgent.id,
|
|
331
348
|
name: defaultAgent.name,
|
|
@@ -345,13 +362,15 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
345
362
|
},
|
|
346
363
|
workflowRuns: {
|
|
347
364
|
active: activeWorkflowRuns,
|
|
348
|
-
attention: attentionWorkflowRuns,
|
|
349
365
|
recent: recentWorkflowRuns
|
|
350
366
|
},
|
|
351
367
|
briefing,
|
|
352
368
|
decisions,
|
|
353
|
-
|
|
354
|
-
|
|
369
|
+
attention,
|
|
370
|
+
chats: {
|
|
371
|
+
running: workChats.filter((chat) => chat.active),
|
|
372
|
+
recent: workChats.filter((chat) => !chat.active).slice(0, 8)
|
|
373
|
+
},
|
|
355
374
|
work: {
|
|
356
375
|
attentionCount: activeWorkItems.filter((item) => workItemAttentionRank(item, nowMs) < 3).length,
|
|
357
376
|
overdueCount: activeWorkItems.filter((item) => item.dueAt != null && item.dueAt < nowMs).length,
|
|
@@ -414,6 +433,58 @@ function registerHomeRoutes(authenticated, deps) {
|
|
|
414
433
|
error: "Unsupported decision kind"
|
|
415
434
|
}, 400);
|
|
416
435
|
});
|
|
436
|
+
authenticated.post("/api/home/attention/acknowledge", deps.strictRateLimitMiddleware, async (c) => {
|
|
437
|
+
const body = await c.req.json().catch(() => ({}));
|
|
438
|
+
const kind = body.kind === "automation_run" || body.kind === "workflow_run" ? body.kind : void 0;
|
|
439
|
+
const runId = typeof body.runId === "string" ? body.runId.trim() : "";
|
|
440
|
+
if (!kind || !runId) return c.json({
|
|
441
|
+
ok: false,
|
|
442
|
+
error: "kind and runId are required"
|
|
443
|
+
}, 400);
|
|
444
|
+
acknowledgeHomeAttention(kind, runId);
|
|
445
|
+
return c.json({
|
|
446
|
+
ok: true,
|
|
447
|
+
status: "acknowledged"
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
authenticated.post("/api/home/attention/retry", deps.strictRateLimitMiddleware, async (c) => {
|
|
451
|
+
const body = await c.req.json().catch(() => ({}));
|
|
452
|
+
const kind = body.kind === "automation_run" || body.kind === "workflow_run" ? body.kind : void 0;
|
|
453
|
+
const runId = typeof body.runId === "string" ? body.runId.trim() : "";
|
|
454
|
+
if (!kind || !runId) return c.json({
|
|
455
|
+
ok: false,
|
|
456
|
+
error: "kind and runId are required"
|
|
457
|
+
}, 400);
|
|
458
|
+
if (kind === "automation_run") try {
|
|
459
|
+
const run = await service.automationServiceInstance.rerunFromRun(runId);
|
|
460
|
+
acknowledgeHomeAttention(kind, runId);
|
|
461
|
+
return c.json({
|
|
462
|
+
ok: true,
|
|
463
|
+
runId: run.id
|
|
464
|
+
}, 202);
|
|
465
|
+
} catch (error) {
|
|
466
|
+
return c.json({
|
|
467
|
+
ok: false,
|
|
468
|
+
error: error instanceof Error ? error.message : "Failed to retry automation"
|
|
469
|
+
}, 400);
|
|
470
|
+
}
|
|
471
|
+
const agentId = (await listGatewayAgents(service.currentConfig)).defaultId;
|
|
472
|
+
const result = await service.createWorkflowRunService().retryWorkflowRun({
|
|
473
|
+
agentId,
|
|
474
|
+
runId
|
|
475
|
+
});
|
|
476
|
+
if (result.ok === false) return c.json({
|
|
477
|
+
ok: false,
|
|
478
|
+
error: result.message,
|
|
479
|
+
code: result.code
|
|
480
|
+
}, result.httpStatus);
|
|
481
|
+
acknowledgeHomeAttention(kind, runId);
|
|
482
|
+
return c.json({
|
|
483
|
+
ok: true,
|
|
484
|
+
runId: result.runId,
|
|
485
|
+
sessionKey: result.sessionKey
|
|
486
|
+
}, 202);
|
|
487
|
+
});
|
|
417
488
|
}
|
|
418
489
|
//#endregion
|
|
419
490
|
export { buildHomeBriefing, registerHomeRoutes };
|
|
@@ -4,6 +4,7 @@ import { registerSessionsRoutes } from "./sessions.js";
|
|
|
4
4
|
import { registerStatusRoutes } from "./status.js";
|
|
5
5
|
import { registerMemoryRoutes } from "./memory.js";
|
|
6
6
|
import { registerProjectsRoutes } from "./projects.js";
|
|
7
|
+
import { registerProjectSkillRoutes } from "./project-skills.js";
|
|
7
8
|
import { registerSearchRoutes } from "./search.js";
|
|
8
9
|
import { registerMobileRoutes } from "./mobile.js";
|
|
9
10
|
import { registerTaskOutcomeRoutes } from "./task-outcomes.js";
|
|
@@ -11,6 +12,7 @@ import { registerInteractionStateRoutes } from "./interaction-state.js";
|
|
|
11
12
|
import { registerComposerHistoryRoutes } from "./composer-history.js";
|
|
12
13
|
import { registerLocalAppsRoutes } from "./local-apps.js";
|
|
13
14
|
import { registerWorkDiscoveryRoutes } from "./work-discovery.js";
|
|
15
|
+
import { registerFocusRoutes } from "./focuses.js";
|
|
14
16
|
import { mountAppLazyRoutePrefixes, registerAuthenticatedLazyRouteFallback } from "./lazy-fallback.js";
|
|
15
17
|
//#region src/gateway/hono/routes/index.ts
|
|
16
18
|
function registerCoreAuthenticatedRoutes(authenticated, deps) {
|
|
@@ -20,8 +22,10 @@ function registerCoreAuthenticatedRoutes(authenticated, deps) {
|
|
|
20
22
|
registerMemoryRoutes(authenticated, deps);
|
|
21
23
|
registerActivityRoutes(authenticated, deps);
|
|
22
24
|
registerProjectsRoutes(authenticated, deps);
|
|
25
|
+
registerProjectSkillRoutes(authenticated, deps);
|
|
23
26
|
registerLocalAppsRoutes(authenticated, deps);
|
|
24
27
|
registerWorkDiscoveryRoutes(authenticated, deps);
|
|
28
|
+
registerFocusRoutes(authenticated, deps);
|
|
25
29
|
registerSearchRoutes(authenticated, deps);
|
|
26
30
|
registerMobileRoutes(authenticated, deps);
|
|
27
31
|
registerTaskOutcomeRoutes(authenticated, deps);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readLocalAppAcceptanceConfig } from "../../../local-apps/acceptance.js";
|
|
2
|
-
import { LOCAL_APP_RUNTIME_BRIDGE_HASH, injectLocalAppRuntimeBridge } from "../../../local-apps/preview-runtime-bridge.js";
|
|
3
2
|
import { extensionAssetMimeType } from "../lib/extension-assets.js";
|
|
3
|
+
import { LOCAL_APP_RUNTIME_BRIDGE_HASH, injectLocalAppRuntimeBridge } from "../../../local-apps/preview-runtime-bridge.js";
|
|
4
4
|
import { relative, resolve } from "node:path";
|
|
5
5
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
6
6
|
//#region src/gateway/hono/routes/local-apps.ts
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ProjectSkillError, ProjectSkillService } from "../../../projects/project-skill-service.js";
|
|
2
|
+
import "../../../projects/index.js";
|
|
3
|
+
//#region src/gateway/hono/routes/project-skills.ts
|
|
4
|
+
function projectSkills(deps) {
|
|
5
|
+
return new ProjectSkillService({
|
|
6
|
+
projects: deps.service.projects,
|
|
7
|
+
getConfig: () => deps.service.currentConfig,
|
|
8
|
+
refreshSkills: () => deps.service.agentService.refreshSkillsAfterDiskChange()
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function errorResponse(c, error) {
|
|
12
|
+
if (error instanceof ProjectSkillError) return c.json({
|
|
13
|
+
ok: false,
|
|
14
|
+
code: error.code,
|
|
15
|
+
error: error.message
|
|
16
|
+
}, error.status);
|
|
17
|
+
return c.json({
|
|
18
|
+
ok: false,
|
|
19
|
+
code: "project_skill_operation_failed",
|
|
20
|
+
error: error instanceof Error ? error.message : String(error)
|
|
21
|
+
}, 400);
|
|
22
|
+
}
|
|
23
|
+
function registerProjectSkillRoutes(authenticated, deps) {
|
|
24
|
+
authenticated.get("/api/projects/:projectId/skills", (c) => {
|
|
25
|
+
try {
|
|
26
|
+
return c.json({
|
|
27
|
+
ok: true,
|
|
28
|
+
...projectSkills(deps).list(c.req.param("projectId"))
|
|
29
|
+
});
|
|
30
|
+
} catch (error) {
|
|
31
|
+
return errorResponse(c, error);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
authenticated.get("/api/projects/:projectId/skills/:skillId", (c) => {
|
|
35
|
+
try {
|
|
36
|
+
return c.json({
|
|
37
|
+
ok: true,
|
|
38
|
+
skill: projectSkills(deps).getContent(c.req.param("projectId"), c.req.param("skillId"))
|
|
39
|
+
});
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return errorResponse(c, error);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
authenticated.post("/api/projects/:projectId/skills/upload", async (c) => {
|
|
45
|
+
try {
|
|
46
|
+
const body = await c.req.parseBody();
|
|
47
|
+
const file = body.file;
|
|
48
|
+
if (!(file instanceof File)) return c.json({
|
|
49
|
+
ok: false,
|
|
50
|
+
error: "Skill zip file is required"
|
|
51
|
+
}, 400);
|
|
52
|
+
const skill = await projectSkills(deps).installZip(c.req.param("projectId"), Buffer.from(await file.arrayBuffer()), {
|
|
53
|
+
skillId: typeof body.skillId === "string" ? body.skillId : void 0,
|
|
54
|
+
overwrite: body.overwrite === "true"
|
|
55
|
+
});
|
|
56
|
+
return c.json({
|
|
57
|
+
ok: true,
|
|
58
|
+
skill
|
|
59
|
+
}, 201);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return errorResponse(c, error);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
authenticated.post("/api/projects/:projectId/skills/marketplace/install", async (c) => {
|
|
65
|
+
try {
|
|
66
|
+
const body = await c.req.json();
|
|
67
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
68
|
+
if (!name) return c.json({
|
|
69
|
+
ok: false,
|
|
70
|
+
error: "Marketplace skill name is required"
|
|
71
|
+
}, 400);
|
|
72
|
+
const skill = await projectSkills(deps).installMarketplace(c.req.param("projectId"), {
|
|
73
|
+
name,
|
|
74
|
+
version: typeof body.version === "string" ? body.version : void 0,
|
|
75
|
+
provider: typeof body.provider === "string" ? body.provider : void 0,
|
|
76
|
+
overwrite: body.overwrite === true
|
|
77
|
+
});
|
|
78
|
+
return c.json({
|
|
79
|
+
ok: true,
|
|
80
|
+
skill
|
|
81
|
+
}, 201);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return errorResponse(c, error);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
authenticated.post("/api/projects/:projectId/skills/source/install", async (c) => {
|
|
87
|
+
try {
|
|
88
|
+
const body = await c.req.json();
|
|
89
|
+
const source = typeof body.source === "string" ? body.source.trim() : "";
|
|
90
|
+
if (!source) return c.json({
|
|
91
|
+
ok: false,
|
|
92
|
+
error: "Skill source is required"
|
|
93
|
+
}, 400);
|
|
94
|
+
const skill = await projectSkills(deps).installSource(c.req.param("projectId"), {
|
|
95
|
+
source,
|
|
96
|
+
skillId: typeof body.skillId === "string" ? body.skillId : void 0,
|
|
97
|
+
ref: typeof body.ref === "string" ? body.ref : void 0,
|
|
98
|
+
subpath: typeof body.subpath === "string" ? body.subpath : void 0,
|
|
99
|
+
force: body.force === true
|
|
100
|
+
});
|
|
101
|
+
return c.json({
|
|
102
|
+
ok: true,
|
|
103
|
+
skill
|
|
104
|
+
}, 201);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return errorResponse(c, error);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
authenticated.delete("/api/projects/:projectId/skills/:skillId", async (c) => {
|
|
110
|
+
try {
|
|
111
|
+
await projectSkills(deps).remove(c.req.param("projectId"), c.req.param("skillId"));
|
|
112
|
+
return c.json({ ok: true });
|
|
113
|
+
} catch (error) {
|
|
114
|
+
return errorResponse(c, error);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { registerProjectSkillRoutes };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getSqliteDatabase
|
|
1
|
+
import { getSqliteDatabase } from "../../../storage/sqlite/transaction.js";
|
|
2
2
|
import { getSessionMetadata } from "../../../storage/sqlite/session-repository.js";
|
|
3
3
|
import { loadTranscriptRowsForSession } from "../../../storage/sqlite/transcript-repository.js";
|
|
4
4
|
import { listMemoryRecords, upsertMemoryRecord } from "../../../storage/sqlite/memory-records-repository.js";
|
|
@@ -7,8 +7,7 @@ import { ActivityService } from "../../../activity/service.js";
|
|
|
7
7
|
import "../../../activity/index.js";
|
|
8
8
|
import { buildSessionKey, init_session_key } from "../../../routing/session-key.js";
|
|
9
9
|
import { resolveEffectiveAgentProfile } from "../../../config/agent-profile.js";
|
|
10
|
-
import { GoalService
|
|
11
|
-
import { draftGoalContract } from "../../../goals/goal-contract-draft.js";
|
|
10
|
+
import { GoalService } from "../../../goals/goal-service.js";
|
|
12
11
|
import "../../../goals/index.js";
|
|
13
12
|
import { ProjectWorkspaceConflictError, ProjectWorkspaceMissingError } from "../../../projects/workspace-project.js";
|
|
14
13
|
import { isValidProjectAgentId, normalizeProjectAgentId, resolveProjectAgentId } from "../../../projects/project-agent.js";
|
|
@@ -27,10 +26,6 @@ import { readFile, readdir, realpath, stat, writeFile } from "node:fs/promises";
|
|
|
27
26
|
//#region src/gateway/hono/routes/projects.ts
|
|
28
27
|
init_session_key();
|
|
29
28
|
const log = createGatewayRouteLogger("Projects");
|
|
30
|
-
const DELEGATED_OUTCOME_MAX_LENGTH = 12e3;
|
|
31
|
-
function inferDelegatedWorkName(outcome) {
|
|
32
|
-
return (outcome.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? outcome.trim()).replace(/^[#*\-\s]+/, "").replace(/[。.!!??]+$/, "").trim().slice(0, 72) || "Untitled work";
|
|
33
|
-
}
|
|
34
29
|
function parseProjectStatus(raw) {
|
|
35
30
|
return raw === "active" || raw === "paused" || raw === "archived" ? raw : void 0;
|
|
36
31
|
}
|
|
@@ -379,102 +374,6 @@ function registerProjectsRoutes(authenticated, deps) {
|
|
|
379
374
|
const activity = new ActivityService();
|
|
380
375
|
const goals = new GoalService();
|
|
381
376
|
const workItems = new WorkItemService();
|
|
382
|
-
authenticated.post("/api/projects/delegate", async (c) => {
|
|
383
|
-
const body = await c.req.json().catch(() => ({}));
|
|
384
|
-
const outcome = textField(body, "outcome")?.trim() ?? "";
|
|
385
|
-
if (!outcome) return c.json({
|
|
386
|
-
ok: false,
|
|
387
|
-
error: "Missing outcome"
|
|
388
|
-
}, 400);
|
|
389
|
-
if (outcome.length > DELEGATED_OUTCOME_MAX_LENGTH) return c.json({
|
|
390
|
-
ok: false,
|
|
391
|
-
error: `Outcome exceeds ${DELEGATED_OUTCOME_MAX_LENGTH} characters`
|
|
392
|
-
}, 400);
|
|
393
|
-
const name = textField(body, "name")?.trim().slice(0, 72) || inferDelegatedWorkName(outcome);
|
|
394
|
-
const uiLocale = normalizeGoalUiLocale(body.uiLocale);
|
|
395
|
-
const defaultAgentId = inferSuggestedProjectDefaultAgentId({
|
|
396
|
-
config: service.currentConfig,
|
|
397
|
-
name,
|
|
398
|
-
description: outcome,
|
|
399
|
-
projectKind: "auto"
|
|
400
|
-
});
|
|
401
|
-
if (!isValidProjectAgentId(service.currentConfig, defaultAgentId)) return c.json({
|
|
402
|
-
ok: false,
|
|
403
|
-
error: "Default agent not found"
|
|
404
|
-
}, 400);
|
|
405
|
-
const contractDraft = await draftGoalContract({
|
|
406
|
-
title: name,
|
|
407
|
-
context: outcome,
|
|
408
|
-
uiLocale,
|
|
409
|
-
modelRef: service.currentConfig.goals?.judgeModelRef
|
|
410
|
-
});
|
|
411
|
-
let created;
|
|
412
|
-
try {
|
|
413
|
-
created = runSqliteWriteTransaction(() => {
|
|
414
|
-
const project = service.projects.create({
|
|
415
|
-
name,
|
|
416
|
-
description: outcome,
|
|
417
|
-
defaultAgentId,
|
|
418
|
-
projectKind: "auto",
|
|
419
|
-
brief: outcome
|
|
420
|
-
});
|
|
421
|
-
const goal = goals.create({
|
|
422
|
-
title: name,
|
|
423
|
-
description: outcome,
|
|
424
|
-
agentId: defaultAgentId,
|
|
425
|
-
priority: "normal",
|
|
426
|
-
uiLocale,
|
|
427
|
-
source: "api",
|
|
428
|
-
projectId: project.id,
|
|
429
|
-
contract: contractDraft.contract,
|
|
430
|
-
config: service.currentConfig
|
|
431
|
-
});
|
|
432
|
-
const detailedGoal = goals.setContextMessage({
|
|
433
|
-
goalId: goal.id,
|
|
434
|
-
text: outcome
|
|
435
|
-
});
|
|
436
|
-
if (!detailedGoal) throw new Error("Goal context could not be saved");
|
|
437
|
-
return {
|
|
438
|
-
project,
|
|
439
|
-
goal: detailedGoal
|
|
440
|
-
};
|
|
441
|
-
});
|
|
442
|
-
} catch (error) {
|
|
443
|
-
log.warn({
|
|
444
|
-
err: error,
|
|
445
|
-
phase: "delegate_create"
|
|
446
|
-
}, `Delegated work could not be created: ${error instanceof Error ? error.message : String(error)}`);
|
|
447
|
-
return c.json({
|
|
448
|
-
ok: false,
|
|
449
|
-
error: error instanceof Error ? error.message : String(error)
|
|
450
|
-
}, 400);
|
|
451
|
-
}
|
|
452
|
-
let queued;
|
|
453
|
-
let executionWarning;
|
|
454
|
-
try {
|
|
455
|
-
queued = service.enqueueGoalRun(created.goal.id, { source: "api" });
|
|
456
|
-
} catch (error) {
|
|
457
|
-
executionWarning = error instanceof Error ? error.message : String(error);
|
|
458
|
-
log.warn({
|
|
459
|
-
err: error,
|
|
460
|
-
projectId: created.project.id,
|
|
461
|
-
goalId: created.goal.id,
|
|
462
|
-
phase: "delegate_enqueue"
|
|
463
|
-
}, `Delegated work was saved but could not be queued: ${executionWarning}`);
|
|
464
|
-
}
|
|
465
|
-
return c.json({
|
|
466
|
-
ok: true,
|
|
467
|
-
project: enrichProjectWorkspace(service, created.project),
|
|
468
|
-
goal: created.goal,
|
|
469
|
-
contractGenerated: contractDraft.generated,
|
|
470
|
-
contractWarning: contractDraft.warning,
|
|
471
|
-
execution: {
|
|
472
|
-
status: queued ? "queued" : "saved",
|
|
473
|
-
queueItem: queued,
|
|
474
|
-
warning: executionWarning
|
|
475
|
-
}
|
|
476
|
-
}, 201);
|
|
477
|
-
});
|
|
478
377
|
authenticated.post("/api/projects", async (c) => {
|
|
479
378
|
const body = await c.req.json().catch(() => ({}));
|
|
480
379
|
const name = textField(body, "name")?.trim();
|