@xopcai/xopc 0.0.334 → 0.0.335
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/{agent-avatar-dicebear-B73q7mlz.js → agent-avatar-dicebear-DtmNsTNI.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-B9L2YIXz.js → agent-defaults-settings-panel-AvGo9fao.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-plugin-dialog-COOjsvea.js → agent-plugin-dialog-DZCh4_E1.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-CCj1JnLu.js → agents-Drt1vHf6.js} +3 -3
- package/dist/gateway/static/root/assets/{agents-admin-api-Cuqi5xZn.js → agents-admin-api-C82B1W9Z.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-CckioKud.js → app-management-settings-panel-IKZm5_s2.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DDiPIr_Q.js → appearance-settings-DKWGkrVW.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-Azqy8vfo.js → apps-page-DY6Q7TMZ.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-Dtyr0RhX.js → archive-plugin-DXGAt0G7.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-g3SrFkTC.js → automations-page-DzqfYcqe.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-B0nW2nZD.js → automations-workspace-qMpqvBz1.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-BwKQVxsU.js → binary-plugins-Cy2FLsPv.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DD9d5pCt.js → block-editor-BqSpSNnv.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automation-inputs-D2gNdS3e.js → browser-automation-inputs-CLOq1KtH.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-BKqqJR7P.js → browser-automations-page-BEeyiVEw.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-BZH9bZbk.js → browser-settings-page-D6SygxnY.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-CHk4RZl4.js → capabilities-BfHgt4uk.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-page-CfWaVH-6.js → capabilities-page-C9Od0WN-.js} +2 -2
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-C5FcWsSe.js → capabilities-settings-panel-6HAVkNE4.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-header-actions-Bd66yEOa.js → capability-header-actions-CwcT7mjE.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-DIU5Gq4o.js → channels-D5HNBMLS.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-B0nPDJyj.js → chat-terminal-dock-BsxTfU1T.js} +1 -1
- package/dist/gateway/static/root/assets/{computer-settings-page-D7PxxaoG.js → computer-settings-page-CH01h8yI.js} +1 -1
- package/dist/gateway/static/root/assets/{connector-service-page-BZH4SeQg.js → connector-service-page-CTi8iaOn.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-BC81R_fz.js → connectors-page-C3GhbPPg.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-CDEVYjXI.js → date-picker-DTEOeiC4.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-AInmpSwC.js → dependency-picker-DFA0RZ02.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Sjgnlq8M.js → desktop-pet-Txr49_Zi.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BWn0rrhr.js → desktop-pet-settings-Coi0DUai.js} +1 -1
- package/dist/gateway/static/root/assets/{device-pairing-wizard-BtW837_d.js → device-pairing-wizard-OPY8ujCN.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-2CpmDx_D.js → directory-picker-path-field-B1ckH4hn.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-WWJFj9Z5.js → extension-debug-page-6e8BCEb6.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DL00dFRr.js → extension-page-DgaFykYf.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CN-agjPk.js → extension-settings-page-B-TyR9GM.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-CgIjCxM8.js → gateway-config-swr-Hn1vj6uI.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-realtime-Ciq4c7KT.js → gateway-realtime-CGjSxzj6.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-DytaaEu8.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-settings-4oD6fhAm.js → gateway-settings-CtjGyqB2.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-i-1lTrwY.js → gateway-startup-retry-CtTVgB7_.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-nEpyJUBY.js → home-page-Cs5fPXcJ.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-gilc-u7M.js → image-generation-api-DBA-bdEM.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-BivdeiQ5.js → imports-page-C72wCY44.js} +1 -1
- package/dist/gateway/static/root/assets/{index-BioG1pRD.js → index-BkSp_1Il.js} +8 -8
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B_8AJTFr.js → keyboard-shortcuts-settings-D1nzw6zI.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-CRtZQrmz.js → local-app-workbench-page-DqB0hGrZ.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-DclxpoqR.js → local-apps-page-D4FX0Ptx.js} +1 -1
- package/dist/gateway/static/root/assets/{local-session-drafts-DkolHmyp.js → local-session-drafts-Byxxogdc.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-BY30D6tg.js → locale-store-7F4l6DRV.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-DX8TxkRl.js → logs-page-CcWD_-zy.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-5WFufZ4g.js → management-settings-L9YGzLaz.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-DYJnwlDr.js → markdown-view-bxpOryax.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DlJDvwLK.js → media-plugins-DqsiYyAz.js} +1 -1
- package/dist/gateway/static/root/assets/{messages-_6IXbP2u.js → messages-DsUnS7rn.js} +2 -2
- package/dist/gateway/static/root/assets/{note-detail-panel-GF5Q9Fqy.js → note-detail-panel-DwK9Ndw1.js} +3 -3
- package/dist/gateway/static/root/assets/{notes-page-E8o4_Ty9.js → notes-page-D2FvAV9x.js} +1 -1
- package/dist/gateway/static/root/assets/{page-context-capture-button-CiCmfRTw.js → page-context-capture-button-CeWnFomm.js} +1 -1
- package/dist/gateway/static/root/assets/{page-tabs-Cwp3fGVM.js → page-tabs-B90ywILw.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-DJ5xqGeu.js → preview-open-alternatives-CwuY-FIE.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-CcGwNePw.js → product-open-page-CUcJOCAz.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-6hhRBkmC.js → project-detail-page-Blo9-zcq.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-DUOzRaFI.js → projects-page-C9rh1U9Z.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-BvVx0G1o.js → registry-api-DU915Prn.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-BWpWUXiE.js → remote-access-hub-Cw2Beq7s.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-C6eDCNHz.js → runtime-tools-settings-panel-Cj8LnZRV.js} +1 -1
- package/dist/gateway/static/root/assets/{scenes-page-pF7Lmqnk.js → scenes-page-BZd4VZBP.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-D8W8q_ez.js → schema-form-CNbrdYAu.js} +1 -1
- package/dist/gateway/static/root/assets/session-api-C7i3UFhq.js +1 -0
- package/dist/gateway/static/root/assets/{session-manager-BAy2sR2Q.js → session-manager-DAck_U0C.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-BKt3Cd0a.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BToasX5M.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-B0cAj0nq.js → settings-form-section-u6ZXo3oJ.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-DZVVTFxs.js → settings-page-gXacaOIv.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-DZCPVx9c.js → setup-status-panel-qKaz5drv.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BkPNyV8c.js → share-preview-page-DdkQ-B5M.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-Bqlv5JBi.js → shares-settings-BwFn5CYE.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-api-C0dufzQC.js → skill-api-Cf3_ZQOb.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CdNp1N-Y.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-DB4lR4om.js → skills-page-fKPvwSpa.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-xjrlhdUz.js → system-settings-panel-CO3l1jdd.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-CB6M7wSs.js → task-detail-page-zClWGuT5.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api--68MQEWM.js → tunnel-api-Dw6DW1j5.js} +1 -1
- package/dist/gateway/static/root/assets/{usage-page-OLZ00eqD.js → usage-page-QP_8nuHU.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-DsnHYpTv.js → use-autosave-ZwnXUpG4.js} +1 -1
- package/dist/gateway/static/root/assets/{user-model-page-CoePFpHD.js → user-model-page-B72PRFAI.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CvIXutQp.js → voice-api-key-field-CbIxN5SC.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-Bwy3Al3J.js → voice-config-api-LKFent6f.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-By5_7MLR.js → work-discovery-overlay-WIGHfEL3.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-HSMDxDXV.js → workflow-run-setup-panel-Bk0Jhdeq.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-DElQ47Da.js → workflows-page-BC385JPr.js} +1 -1
- package/dist/gateway/static/root/index.html +14 -14
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/sessions.js +11 -0
- package/dist/src/agent/agent-instance-gateway.d.ts +0 -2
- package/dist/src/agent/agent-manager.d.ts +0 -2
- package/dist/src/agent/agent-manager.js +0 -31
- package/dist/src/agent/background-review/run-background-review.d.ts +0 -7
- package/dist/src/agent/background-review/run-background-review.js +1 -21
- package/dist/src/agent/orchestration/agent-orchestrator.js +0 -3
- package/dist/src/agent/service/direct-turn-helpers.js +0 -3
- package/dist/src/automations/events/event-dispatcher.d.ts +10 -3
- package/dist/src/automations/service/automation-service.js +0 -1
- package/dist/src/gateway/hono/routes/sessions.js +15 -1
- package/dist/src/gateway/service/session-preparation-worker.d.ts +9 -2
- package/dist/src/gateway/service.js +3 -3
- package/dist/src/home-intelligence/generator.d.ts +8 -1
- package/dist/src/home-intelligence/generator.js +25 -14
- package/dist/src/home-intelligence/host.d.ts +8 -1
- package/dist/src/home-intelligence/host.js +81 -7
- package/dist/src/home-intelligence/repository.d.ts +5 -1
- package/dist/src/home-intelligence/repository.js +16 -9
- package/dist/src/home-intelligence/snapshot.js +4 -4
- package/dist/src/storage/sqlite/ai-usage-repository.d.ts +3 -0
- package/dist/src/storage/sqlite/ai-usage-repository.js +25 -1
- package/package.json +4 -4
- package/dist/gateway/static/root/assets/gateway-realtime-store-BHeHN26R.js +0 -1
- package/dist/gateway/static/root/assets/session-api-BAyUr97V.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BDKDqqf9.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-C9cJWlAq.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-3JF2OTBz.js +0 -1
|
@@ -3,7 +3,6 @@ import { init_logger } from "../../utils/logger.js";
|
|
|
3
3
|
import { abortEmbeddedRun } from "../embedded/runs.js";
|
|
4
4
|
import { persistInboundAttachments } from "../../channels/attachments/inbound-persist.js";
|
|
5
5
|
import { buildTranscriptUserMessage, clearPendingTranscriptUserMessage, hydrateUserTurnForLlm, setPendingTranscriptUserMessage } from "../inbound/attachment-pipeline.js";
|
|
6
|
-
import { extractAgentUserPlainText } from "../memory/user-message-text.js";
|
|
7
6
|
import { resolveEffectiveThinkingLevel } from "../../session/thinking-resolve.js";
|
|
8
7
|
import { runEmbeddedTurnForSession } from "../embedded/run-for-session.js";
|
|
9
8
|
import { randomUUID } from "node:crypto";
|
|
@@ -68,7 +67,6 @@ var AgentOrchestrator = class {
|
|
|
68
67
|
agentManager: this.agentManager
|
|
69
68
|
});
|
|
70
69
|
setPendingTranscriptUserMessage(conversationId, userMessage);
|
|
71
|
-
const userPlainForMemory = extractAgentUserPlainText(userMessage);
|
|
72
70
|
const turnId = randomUUID();
|
|
73
71
|
const userContext = await this.agentManager.prepareUserTurnContext(userMessage, conversationId, turnId);
|
|
74
72
|
const userMessageForModel = userMessage;
|
|
@@ -96,7 +94,6 @@ var AgentOrchestrator = class {
|
|
|
96
94
|
clearPendingTranscriptUserMessage(conversationId, userMessage);
|
|
97
95
|
}
|
|
98
96
|
})();
|
|
99
|
-
this.agentManager.scheduleUserUnderstandingMaintenance(conversationId, userPlainForMemory, turnId);
|
|
100
97
|
this.agentManager.scheduleBackgroundReviewAfterUserTurn(conversationId);
|
|
101
98
|
if (turnResult.ok) {
|
|
102
99
|
this.onEmbeddedTurnComplete?.(conversationId, turnResult.lastAssistantText);
|
|
@@ -3,7 +3,6 @@ import { getConnectionResumeInput, init_connection_wait_repository } from "../..
|
|
|
3
3
|
import { resolveImageHandlingStrategy } from "../image/vision-detection.js";
|
|
4
4
|
import { hydrateUserTurnForLlm } from "../inbound/attachment-pipeline.js";
|
|
5
5
|
import { buildTaskExecutionDirective } from "../../tasks/task-context-assembler.js";
|
|
6
|
-
import { extractAgentUserPlainText } from "../memory/user-message-text.js";
|
|
7
6
|
import { shouldSkipResetOverlapCommand } from "../../session/reset-triggers.js";
|
|
8
7
|
import { parseSlashCommand } from "../../chat-commands/command-parse.js";
|
|
9
8
|
import { commandRegistry } from "../../chat-commands/registry.js";
|
|
@@ -99,7 +98,6 @@ async function runDirectAgentTurn(deps, input) {
|
|
|
99
98
|
const isConnectionResume = Boolean(getConnectionResumeInput(input.conversationId, turnId));
|
|
100
99
|
const isClarificationResume = Boolean(getClarificationResumeInput(input.conversationId, turnId));
|
|
101
100
|
const isResume = isConnectionResume || isClarificationResume;
|
|
102
|
-
const userPlain = extractAgentUserPlainText(input.userMessage);
|
|
103
101
|
const userContext = await deps.agentManager.prepareUserTurnContext(input.userMessage, input.conversationId, turnId);
|
|
104
102
|
const sourceContexts = input.sourceContexts ?? [];
|
|
105
103
|
const userMessageForModel = prependAgentContext(injectSourceContextsIntoUserMessage(input.userMessage, sourceContexts), buildTaskExecutionDirective(input.conversationId));
|
|
@@ -127,7 +125,6 @@ async function runDirectAgentTurn(deps, input) {
|
|
|
127
125
|
beforeTurn: isResume ? void 0 : () => deps.agentManager.beginBackgroundReviewUserTurn(input.conversationId),
|
|
128
126
|
onEvent: input.onEvent
|
|
129
127
|
});
|
|
130
|
-
if (!isResume) deps.agentManager.scheduleUserUnderstandingMaintenance(input.conversationId, userPlain, turnId);
|
|
131
128
|
if (!isResume && result.stopReason !== "connection_required" && result.stopReason !== "clarification_required") deps.agentManager.scheduleBackgroundReviewAfterUserTurn(input.conversationId);
|
|
132
129
|
return result;
|
|
133
130
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import type { AutomationEventEnvelope, AutomationRun } from '../domain/types.js';
|
|
2
|
-
|
|
1
|
+
import type { AutomationEvent, AutomationEventEnvelope, AutomationRun } from '../domain/types.js';
|
|
2
|
+
export interface AutomationEventDispatchService {
|
|
3
|
+
availableRunSlots(): number;
|
|
4
|
+
queueRunAtomically(id: string, opts: {
|
|
5
|
+
manual: boolean;
|
|
6
|
+
event?: AutomationEvent;
|
|
7
|
+
}): AutomationRun;
|
|
8
|
+
dispatchQueuedRun(runId: string): void;
|
|
9
|
+
}
|
|
3
10
|
export declare class AutomationEventDispatcher {
|
|
4
11
|
private readonly automationService;
|
|
5
12
|
private readonly options;
|
|
@@ -8,7 +15,7 @@ export declare class AutomationEventDispatcher {
|
|
|
8
15
|
private stopping;
|
|
9
16
|
private readonly owner;
|
|
10
17
|
private readonly abortController;
|
|
11
|
-
constructor(automationService:
|
|
18
|
+
constructor(automationService: AutomationEventDispatchService, options?: {
|
|
12
19
|
onEvent?: (event: AutomationEventEnvelope, signal?: AbortSignal) => void | Promise<void>;
|
|
13
20
|
onDeadLetter?: (input: {
|
|
14
21
|
phase: 'event_projection' | 'event_delivery';
|
|
@@ -9,7 +9,6 @@ import { getAutomationEventDeliveryRunId, getAutomationEventForRun, getAutomatio
|
|
|
9
9
|
import { computeNextAutomationRunAtMs, timerDelayUntil } from "../domain/schedule.js";
|
|
10
10
|
import { AutomationActionExecutor } from "./action-executor.js";
|
|
11
11
|
import { AutomationEventDispatcher } from "../events/event-dispatcher.js";
|
|
12
|
-
import "../events/index.js";
|
|
13
12
|
import { AutomationDeliveryRouter, getAutomationResultDeliveryMetrics, listAutomationResultDeliveries, retryAutomationResultDelivery } from "../delivery/delivery-router.js";
|
|
14
13
|
import "../delivery/index.js";
|
|
15
14
|
import { randomUUID } from "node:crypto";
|
|
@@ -3,6 +3,7 @@ import { SessionDiscoveryQuerySchema } from "../../../../packages/gateway-contra
|
|
|
3
3
|
import { init_src } from "../../../../packages/gateway-contract/src/index.js";
|
|
4
4
|
import "../../../session/types.js";
|
|
5
5
|
import { SidebarLayoutConflictError, getSidebarLayout, init_sidebar_layout_repository, replaceSidebarLayout, sortBySidebarLayout } from "../../../storage/sqlite/sidebar-layout-repository.js";
|
|
6
|
+
import { summarizeAiUsageByConversations } from "../../../storage/sqlite/ai-usage-repository.js";
|
|
6
7
|
import { messagesToClientHistory } from "../../../session/client-history.js";
|
|
7
8
|
import { evictEmbeddedSessionRunner } from "../../../agent/embedded/session-runner.js";
|
|
8
9
|
import { SessionEnvironmentService } from "../../../execution-environments/session-environment-service.js";
|
|
@@ -286,7 +287,20 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
286
287
|
limit: query.limit ? parseInt(query.limit) : void 0,
|
|
287
288
|
offset: query.offset ? parseInt(query.offset) : void 0
|
|
288
289
|
});
|
|
289
|
-
|
|
290
|
+
const usageByConversation = summarizeAiUsageByConversations(result.items.map((item) => item.key));
|
|
291
|
+
return c.json({
|
|
292
|
+
...result,
|
|
293
|
+
items: result.items.map((item) => ({
|
|
294
|
+
...item,
|
|
295
|
+
usage: usageByConversation.get(item.key) ?? {
|
|
296
|
+
calls: 0,
|
|
297
|
+
unknownCostCalls: 0,
|
|
298
|
+
totalTokens: 0,
|
|
299
|
+
knownCostUsd: "0",
|
|
300
|
+
costCompleteness: "unknown"
|
|
301
|
+
}
|
|
302
|
+
}))
|
|
303
|
+
});
|
|
290
304
|
});
|
|
291
305
|
authenticated.get("/api/sessions/stats", async (c) => {
|
|
292
306
|
const result = await service.sessions.stats();
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProjectService } from '../../projects/project-service.js';
|
|
2
|
+
import type { SessionInputState } from '../../storage/sqlite/session-input-repository.js';
|
|
3
|
+
export interface SessionPreparationWorkerService {
|
|
4
|
+
projects: Pick<ProjectService, 'get'>;
|
|
5
|
+
drainSessionInputs(conversationId: string): Promise<unknown>;
|
|
6
|
+
getSessionInputState(conversationId: string): SessionInputState;
|
|
7
|
+
emit(type: string, payload: unknown): void;
|
|
8
|
+
}
|
|
2
9
|
export declare class SessionPreparationWorker {
|
|
3
10
|
private readonly service;
|
|
4
11
|
private timer?;
|
|
@@ -6,7 +13,7 @@ export declare class SessionPreparationWorker {
|
|
|
6
13
|
private cleaning;
|
|
7
14
|
private cleanupTask?;
|
|
8
15
|
private readonly environments;
|
|
9
|
-
constructor(service:
|
|
16
|
+
constructor(service: SessionPreparationWorkerService);
|
|
10
17
|
start(): void;
|
|
11
18
|
stop(): Promise<void>;
|
|
12
19
|
wake(conversationId: string): void;
|
|
@@ -79,14 +79,14 @@ import "../knowledge/index.js";
|
|
|
79
79
|
import { ConnectionRecoveryService } from "../connectors/connection-recovery-service.js";
|
|
80
80
|
import { startConnectorLearningCoordinator } from "../connectors/learning-coordinator.js";
|
|
81
81
|
import { startConnectorSupervisor } from "../connectors/supervisor.js";
|
|
82
|
+
import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
|
|
83
|
+
import "../endpoint-tools/index.js";
|
|
82
84
|
import { DiscussionService } from "../discussions/service.js";
|
|
83
85
|
import { DiscussionOrganizer } from "../discussions/organizer.js";
|
|
84
86
|
import { DiscussionLiveWorker } from "../discussions/live-worker.js";
|
|
85
87
|
import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
|
|
86
88
|
import { DiscussionSealer } from "../discussions/sealer.js";
|
|
87
89
|
import "../discussions/index.js";
|
|
88
|
-
import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
|
|
89
|
-
import "../endpoint-tools/index.js";
|
|
90
90
|
import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
|
|
91
91
|
import { prepareAutomationAgentSession } from "./automation-agent-session.js";
|
|
92
92
|
import { stopTailscaleExposure } from "./tailscale-lifecycle.js";
|
|
@@ -143,8 +143,8 @@ import { createGatewayStartupTrace } from "./startup-trace.js";
|
|
|
143
143
|
import { GatewaySceneHost } from "./scenes/host.js";
|
|
144
144
|
import { checkAppContextAccess, prepareAppContext } from "./service/app-context-access.js";
|
|
145
145
|
import { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults } from "../voice/language-profile.js";
|
|
146
|
-
import { HomeIntelligenceHost } from "../home-intelligence/host.js";
|
|
147
146
|
import { HomeAdviceGenerator } from "../home-intelligence/generator.js";
|
|
147
|
+
import { HomeIntelligenceHost } from "../home-intelligence/host.js";
|
|
148
148
|
import { HomeSnapshotBuilder } from "../home-intelligence/snapshot.js";
|
|
149
149
|
import { HomeCapabilityPreflightService } from "../home-intelligence/capability-preflight.js";
|
|
150
150
|
import crypto from "node:crypto";
|
|
@@ -118,8 +118,15 @@ export interface HomeModelGeneration {
|
|
|
118
118
|
estimatedCostUsd?: number;
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
|
+
export interface HomeProviderCallBudget {
|
|
122
|
+
allowProviderCall(): boolean;
|
|
123
|
+
}
|
|
124
|
+
export declare class HomeAdviceBudgetExceededError extends Error {
|
|
125
|
+
readonly usage: HomeModelGeneration['usage'];
|
|
126
|
+
constructor(usage?: HomeModelGeneration['usage']);
|
|
127
|
+
}
|
|
121
128
|
export declare class HomeAdviceGenerator {
|
|
122
129
|
private readonly config;
|
|
123
130
|
constructor(config: () => Config);
|
|
124
|
-
generate(snapshot: HomeContextSnapshot, capabilities: HomeCapabilityInventory, signal?: AbortSignal): Promise<HomeModelGeneration>;
|
|
131
|
+
generate(snapshot: HomeContextSnapshot, capabilities: HomeCapabilityInventory, signal?: AbortSignal, budget?: HomeProviderCallBudget): Promise<HomeModelGeneration>;
|
|
125
132
|
}
|
|
@@ -146,11 +146,18 @@ function addUsage(left, right) {
|
|
|
146
146
|
estimatedCostUsd: add(left.estimatedCostUsd, right.estimatedCostUsd)
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
+
var HomeAdviceBudgetExceededError = class extends Error {
|
|
150
|
+
constructor(usage = {}) {
|
|
151
|
+
super("Home intelligence provider budget exhausted");
|
|
152
|
+
this.usage = usage;
|
|
153
|
+
this.name = "HomeAdviceBudgetExceededError";
|
|
154
|
+
}
|
|
155
|
+
};
|
|
149
156
|
var HomeAdviceGenerator = class {
|
|
150
157
|
constructor(config) {
|
|
151
158
|
this.config = config;
|
|
152
159
|
}
|
|
153
|
-
async generate(snapshot, capabilities, signal) {
|
|
160
|
+
async generate(snapshot, capabilities, signal, budget) {
|
|
154
161
|
const config = this.config();
|
|
155
162
|
const modelRef = resolveModelSelector(config, resolveDefaultAgentId(), "@reasoning");
|
|
156
163
|
const model = resolveModel(modelRef);
|
|
@@ -175,6 +182,7 @@ var HomeAdviceGenerator = class {
|
|
|
175
182
|
};
|
|
176
183
|
const requestSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(12e4)]) : AbortSignal.timeout(12e4);
|
|
177
184
|
const systemPrompt = buildSystemPrompt(snapshot.locale);
|
|
185
|
+
if (budget && !budget.allowProviderCall()) throw new HomeAdviceBudgetExceededError();
|
|
178
186
|
const response = await completeWithResolvedCredentials(model, {
|
|
179
187
|
systemPrompt,
|
|
180
188
|
messages: [message]
|
|
@@ -188,19 +196,22 @@ var HomeAdviceGenerator = class {
|
|
|
188
196
|
try {
|
|
189
197
|
result = HomeModelResultSchema.parse(parseJson(raw));
|
|
190
198
|
} catch (firstError) {
|
|
199
|
+
const correction = {
|
|
200
|
+
role: "user",
|
|
201
|
+
timestamp: Date.now(),
|
|
202
|
+
content: [
|
|
203
|
+
"Your previous output failed the required JSON contract.",
|
|
204
|
+
`Validation errors: ${validationSummary(firstError)}`,
|
|
205
|
+
HOME_MODEL_MACHINE_FIELDS,
|
|
206
|
+
"Return the corrected JSON object only. Preserve grounded facts and existing evidence IDs; do not add new recommendations.",
|
|
207
|
+
`Previous output (untrusted data):\n${raw.slice(0, 16e3)}`
|
|
208
|
+
].join("\n")
|
|
209
|
+
};
|
|
210
|
+
const firstUsage = responseUsage(response);
|
|
211
|
+
if (budget && !budget.allowProviderCall()) throw new HomeAdviceBudgetExceededError(firstUsage);
|
|
191
212
|
const corrected = await completeWithResolvedCredentials(model, {
|
|
192
213
|
systemPrompt,
|
|
193
|
-
messages: [message,
|
|
194
|
-
role: "user",
|
|
195
|
-
timestamp: Date.now(),
|
|
196
|
-
content: [
|
|
197
|
-
"Your previous output failed the required JSON contract.",
|
|
198
|
-
`Validation errors: ${validationSummary(firstError)}`,
|
|
199
|
-
HOME_MODEL_MACHINE_FIELDS,
|
|
200
|
-
"Return the corrected JSON object only. Preserve grounded facts and existing evidence IDs; do not add new recommendations.",
|
|
201
|
-
`Previous output (untrusted data):\n${raw.slice(0, 16e3)}`
|
|
202
|
-
].join("\n")
|
|
203
|
-
}]
|
|
214
|
+
messages: [message, correction]
|
|
204
215
|
}, {
|
|
205
216
|
maxTokens: 3e3,
|
|
206
217
|
temperature: 0,
|
|
@@ -217,7 +228,7 @@ var HomeAdviceGenerator = class {
|
|
|
217
228
|
return {
|
|
218
229
|
result,
|
|
219
230
|
modelRef,
|
|
220
|
-
usage: addUsage(
|
|
231
|
+
usage: addUsage(firstUsage, responseUsage(corrected))
|
|
221
232
|
};
|
|
222
233
|
}
|
|
223
234
|
return {
|
|
@@ -228,4 +239,4 @@ var HomeAdviceGenerator = class {
|
|
|
228
239
|
}
|
|
229
240
|
};
|
|
230
241
|
//#endregion
|
|
231
|
-
export { HomeAdviceGenerator, HomeModelCandidateSchema, HomeModelResultSchema };
|
|
242
|
+
export { HomeAdviceBudgetExceededError, HomeAdviceGenerator, HomeModelCandidateSchema, HomeModelResultSchema };
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { DatabaseSync } from 'node:sqlite';
|
|
2
2
|
import type { HomeAdviceMetrics, HomeAdvisor, HomeOpportunityHistoryItem } from '@xopcai/gateway-contract';
|
|
3
3
|
import type { HomeOpportunityActionRequest, HomeOpportunityActionResponse, HomeOpportunityFeedbackRequest } from '@xopcai/gateway-contract';
|
|
4
|
-
import type
|
|
4
|
+
import { type HomeAdviceGenerator } from './generator.js';
|
|
5
5
|
import { type HomeGenerationReason, type HomePrincipal } from './repository.js';
|
|
6
6
|
import { HomeSnapshotBuilder } from './snapshot.js';
|
|
7
7
|
import type { HomeCapabilityInventory } from './types.js';
|
|
8
8
|
import { type HomeOpportunityNotification } from './notification.js';
|
|
9
9
|
import type { HomeCapabilityRequirement, HomeCapabilityResolution } from './capability-preflight.js';
|
|
10
|
+
export declare const HOME_CONTEXT_REFRESH_COOLDOWN_MS: number;
|
|
11
|
+
export declare const DAILY_HOME_PROVIDER_CALL_BUDGET = 12;
|
|
12
|
+
export declare const DAILY_HOME_TOKEN_BUDGET = 120000;
|
|
10
13
|
export interface HomeIntelligenceHostDeps {
|
|
11
14
|
principal: HomePrincipal;
|
|
12
15
|
snapshot: HomeSnapshotBuilder;
|
|
@@ -32,6 +35,8 @@ export declare class HomeIntelligenceHost {
|
|
|
32
35
|
private stopped;
|
|
33
36
|
private abortController;
|
|
34
37
|
private localeHint;
|
|
38
|
+
private contextRefreshTimer?;
|
|
39
|
+
private readonly pendingContextReasons;
|
|
35
40
|
constructor(db: DatabaseSync, deps: HomeIntelligenceHostDeps);
|
|
36
41
|
start(): void;
|
|
37
42
|
stop(): void;
|
|
@@ -39,6 +44,8 @@ export declare class HomeIntelligenceHost {
|
|
|
39
44
|
getMetrics(since?: number): HomeAdviceMetrics;
|
|
40
45
|
getHistory(): HomeOpportunityHistoryItem[];
|
|
41
46
|
requestRefresh(reason: HomeGenerationReason, idempotencyKey?: string, locale?: string): string;
|
|
47
|
+
private currentFingerprint;
|
|
48
|
+
private scheduleContextRefresh;
|
|
42
49
|
sourceChanged(input: {
|
|
43
50
|
sourceInstanceId: string;
|
|
44
51
|
revision: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { HomeAdviceBudgetExceededError } from "./generator.js";
|
|
3
4
|
import { homePatternKey } from "./strategy.js";
|
|
4
5
|
import { HomeAdvicePolicy } from "./policy.js";
|
|
5
6
|
import { HomeIntelligenceRepository } from "./repository.js";
|
|
@@ -11,7 +12,16 @@ init_logger();
|
|
|
11
12
|
const log = createLogger("HomeIntelligence");
|
|
12
13
|
const POLL_INTERVAL_MS = 5e3;
|
|
13
14
|
const GENERATION_LEASE_MS = 5 * 6e4;
|
|
14
|
-
const
|
|
15
|
+
const HOME_CONTEXT_REFRESH_COOLDOWN_MS = 30 * 6e4;
|
|
16
|
+
const DAILY_HOME_PROVIDER_CALL_BUDGET = 12;
|
|
17
|
+
const DAILY_HOME_TOKEN_BUDGET = 12e4;
|
|
18
|
+
const HOME_USAGE_OPERATION = "home.generate_advice";
|
|
19
|
+
const CONTEXT_REFRESH_REASONS = new Set([
|
|
20
|
+
"project_changed",
|
|
21
|
+
"task_changed",
|
|
22
|
+
"connector_changed",
|
|
23
|
+
"conversation_changed"
|
|
24
|
+
]);
|
|
15
25
|
function generationFingerprint(snapshotHash, capabilities) {
|
|
16
26
|
return createHash("sha256").update(JSON.stringify({
|
|
17
27
|
snapshotHash,
|
|
@@ -29,6 +39,8 @@ var HomeIntelligenceHost = class {
|
|
|
29
39
|
stopped = false;
|
|
30
40
|
abortController = new AbortController();
|
|
31
41
|
localeHint;
|
|
42
|
+
contextRefreshTimer;
|
|
43
|
+
pendingContextReasons = /* @__PURE__ */ new Set();
|
|
32
44
|
constructor(db, deps) {
|
|
33
45
|
this.deps = deps;
|
|
34
46
|
this.repository = new HomeIntelligenceRepository(db);
|
|
@@ -49,6 +61,9 @@ var HomeIntelligenceHost = class {
|
|
|
49
61
|
this.abortController = new AbortController();
|
|
50
62
|
if (this.timer) clearInterval(this.timer);
|
|
51
63
|
this.timer = void 0;
|
|
64
|
+
if (this.contextRefreshTimer) clearTimeout(this.contextRefreshTimer);
|
|
65
|
+
this.contextRefreshTimer = void 0;
|
|
66
|
+
this.pendingContextReasons.clear();
|
|
52
67
|
}
|
|
53
68
|
getAdvisor() {
|
|
54
69
|
if (this.deps.enabled?.() === false) return { state: "disabled" };
|
|
@@ -65,6 +80,16 @@ var HomeIntelligenceHost = class {
|
|
|
65
80
|
if (this.deps.enabled?.() === false) return "disabled";
|
|
66
81
|
const now = this.now();
|
|
67
82
|
if (locale) this.localeHint = locale.toLowerCase().startsWith("zh") ? "zh" : "en";
|
|
83
|
+
if (CONTEXT_REFRESH_REASONS.has(reason)) {
|
|
84
|
+
const fingerprint = this.currentFingerprint(now);
|
|
85
|
+
if (this.repository.getLatestSnapshotHash(this.deps.principal) === fingerprint) return "unchanged";
|
|
86
|
+
const lastRequestedAt = this.repository.getLatestContextRefreshRequestedAt(this.deps.principal);
|
|
87
|
+
if (lastRequestedAt !== void 0 && now < lastRequestedAt + 18e5) {
|
|
88
|
+
this.pendingContextReasons.add(reason);
|
|
89
|
+
this.scheduleContextRefresh(lastRequestedAt + HOME_CONTEXT_REFRESH_COOLDOWN_MS - now);
|
|
90
|
+
return "cooldown";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
68
93
|
const bucket = Math.floor(now / (reason === "manual_refresh" ? 1 : 5 * 6e4));
|
|
69
94
|
const request = this.repository.enqueue(this.deps.principal, {
|
|
70
95
|
idempotencyKey: idempotencyKey ?? `${reason}:${bucket}`,
|
|
@@ -74,6 +99,32 @@ var HomeIntelligenceHost = class {
|
|
|
74
99
|
this.tick();
|
|
75
100
|
return request.generationId;
|
|
76
101
|
}
|
|
102
|
+
currentFingerprint(now) {
|
|
103
|
+
const successfulPatterns = this.repository.getSuccessfulPatterns(this.deps.principal);
|
|
104
|
+
return generationFingerprint(this.deps.snapshot.build({
|
|
105
|
+
now,
|
|
106
|
+
locale: this.localeHint,
|
|
107
|
+
successfulPatterns
|
|
108
|
+
}).hash, this.deps.capabilities());
|
|
109
|
+
}
|
|
110
|
+
scheduleContextRefresh(delayMs) {
|
|
111
|
+
if (this.contextRefreshTimer) return;
|
|
112
|
+
this.contextRefreshTimer = setTimeout(() => {
|
|
113
|
+
this.contextRefreshTimer = void 0;
|
|
114
|
+
if (this.stopped || this.pendingContextReasons.size === 0) return;
|
|
115
|
+
const reasons = [...this.pendingContextReasons];
|
|
116
|
+
this.pendingContextReasons.clear();
|
|
117
|
+
const now = this.now();
|
|
118
|
+
if (this.repository.getLatestSnapshotHash(this.deps.principal) === this.currentFingerprint(now)) return;
|
|
119
|
+
this.repository.enqueue(this.deps.principal, {
|
|
120
|
+
idempotencyKey: `context_refresh:${Math.floor(now / HOME_CONTEXT_REFRESH_COOLDOWN_MS)}`,
|
|
121
|
+
reasons,
|
|
122
|
+
requestedAt: now
|
|
123
|
+
});
|
|
124
|
+
this.tick();
|
|
125
|
+
}, Math.max(1, delayMs));
|
|
126
|
+
this.contextRefreshTimer.unref?.();
|
|
127
|
+
}
|
|
77
128
|
sourceChanged(input) {
|
|
78
129
|
const now = this.now();
|
|
79
130
|
const invalidated = this.repository.invalidateOpportunitiesByEvidenceSources(this.deps.principal, new Set([
|
|
@@ -174,16 +225,18 @@ var HomeIntelligenceHost = class {
|
|
|
174
225
|
let generation;
|
|
175
226
|
const startOfDay = new Date(startedAt);
|
|
176
227
|
startOfDay.setHours(0, 0, 0, 0);
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
228
|
+
const providerBudgetAvailable = () => {
|
|
229
|
+
const usage = this.repository.getProviderUsageSince(startOfDay.getTime(), HOME_USAGE_OPERATION);
|
|
230
|
+
return usage.calls < 12 && usage.totalTokens < 12e4;
|
|
231
|
+
};
|
|
232
|
+
const result = !providerBudgetAvailable() ? {
|
|
180
233
|
state: "quiet",
|
|
181
234
|
reason: "budget_exhausted"
|
|
182
|
-
} : previousHash === currentFingerprint && !
|
|
235
|
+
} : previousHash === currentFingerprint && !claim.reasons.includes("manual_refresh") ? {
|
|
183
236
|
state: "quiet",
|
|
184
237
|
reason: "no_change"
|
|
185
238
|
} : await (async () => {
|
|
186
|
-
generation = await this.deps.generator.generate(snapshot, capabilities, this.abortController.signal);
|
|
239
|
+
generation = await this.deps.generator.generate(snapshot, capabilities, this.abortController.signal, { allowProviderCall: providerBudgetAvailable });
|
|
187
240
|
return new HomeAdvicePolicy((requirements, options) => this.resolveCapabilityRequirements(requirements, Boolean(options?.degradedActionAvailable)), this.repository.listSuppressionKeys(this.deps.principal), new Map(successfulPatterns.map((item) => [homePatternKey(item.projectId, item.outcome), item.successCount])), this.repository.getPersonalization(this.deps.principal, this.now())).apply(snapshot, generation.result, this.now());
|
|
188
241
|
})();
|
|
189
242
|
const completedAt = this.now();
|
|
@@ -212,6 +265,27 @@ var HomeIntelligenceHost = class {
|
|
|
212
265
|
this.repository.fail(claim, this.now(), "cancelled", this.now());
|
|
213
266
|
return;
|
|
214
267
|
}
|
|
268
|
+
if (error instanceof HomeAdviceBudgetExceededError) {
|
|
269
|
+
const completedAt = this.now();
|
|
270
|
+
this.repository.complete(claim, {
|
|
271
|
+
result: {
|
|
272
|
+
state: "quiet",
|
|
273
|
+
reason: "budget_exhausted"
|
|
274
|
+
},
|
|
275
|
+
snapshotHash: currentFingerprint ?? this.repository.getLatestSnapshotHash(this.deps.principal) ?? "budget-exhausted",
|
|
276
|
+
evidenceIds: [],
|
|
277
|
+
inputTokens: error.usage.inputTokens,
|
|
278
|
+
outputTokens: error.usage.outputTokens,
|
|
279
|
+
estimatedCostUsd: error.usage.estimatedCostUsd,
|
|
280
|
+
outcomeReason: "budget_exhausted",
|
|
281
|
+
completedAt
|
|
282
|
+
});
|
|
283
|
+
this.deps.publish("home.advisor.updated", {
|
|
284
|
+
state: "quiet",
|
|
285
|
+
reason: "budget_exhausted"
|
|
286
|
+
});
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
215
289
|
const message = error instanceof Error ? error.message : String(error);
|
|
216
290
|
if (/no api key|no default model|credentials|unknown model|local model/i.test(message)) {
|
|
217
291
|
const completedAt = this.now();
|
|
@@ -246,4 +320,4 @@ var HomeIntelligenceHost = class {
|
|
|
246
320
|
}
|
|
247
321
|
};
|
|
248
322
|
//#endregion
|
|
249
|
-
export { HomeIntelligenceHost };
|
|
323
|
+
export { DAILY_HOME_PROVIDER_CALL_BUDGET, DAILY_HOME_TOKEN_BUDGET, HOME_CONTEXT_REFRESH_COOLDOWN_MS, HomeIntelligenceHost };
|
|
@@ -58,7 +58,11 @@ export declare class HomeIntelligenceRepository {
|
|
|
58
58
|
};
|
|
59
59
|
fail(claim: HomeGenerationClaim, now: number, errorCode: string, retryAt?: number): void;
|
|
60
60
|
getLatestSnapshotHash(principal: HomePrincipal): string | undefined;
|
|
61
|
-
|
|
61
|
+
getLatestContextRefreshRequestedAt(principal: HomePrincipal): number | undefined;
|
|
62
|
+
getProviderUsageSince(startedAt: number, operation: string): {
|
|
63
|
+
calls: number;
|
|
64
|
+
totalTokens: number;
|
|
65
|
+
};
|
|
62
66
|
listSuppressionKeys(principal: HomePrincipal): Set<string>;
|
|
63
67
|
getSuccessfulPatterns(principal: HomePrincipal): HomeSuccessfulPattern[];
|
|
64
68
|
getPersonalization(principal: HomePrincipal, now: number): HomeAdvicePersonalization;
|
|
@@ -151,16 +151,23 @@ var HomeIntelligenceRepository = class {
|
|
|
151
151
|
OR outcome_reason NOT IN ('no_change', 'budget_exhausted'))
|
|
152
152
|
ORDER BY completed_at DESC, rowid DESC LIMIT 1`).get(principal.ownerId, principal.workspaceId)?.snapshot_hash ?? void 0;
|
|
153
153
|
}
|
|
154
|
-
|
|
155
|
-
const row = this.db.prepare(`SELECT
|
|
156
|
-
WHEN generation_id = ? THEN MAX(attempt - 1, 0)
|
|
157
|
-
WHEN model_ref IS NOT NULL THEN 1
|
|
158
|
-
WHEN status IN ('failed', 'retry_wait') THEN attempt
|
|
159
|
-
ELSE 0
|
|
160
|
-
END), 0) AS count
|
|
154
|
+
getLatestContextRefreshRequestedAt(principal) {
|
|
155
|
+
const row = this.db.prepare(`SELECT MAX(requested_at) AS requested_at
|
|
161
156
|
FROM home_advice_generations
|
|
162
|
-
WHERE owner_id = ? AND workspace_id = ?
|
|
163
|
-
|
|
157
|
+
WHERE owner_id = ? AND workspace_id = ?
|
|
158
|
+
AND EXISTS (
|
|
159
|
+
SELECT 1 FROM json_each(reasons_json)
|
|
160
|
+
WHERE value IN ('project_changed', 'task_changed', 'connector_changed', 'conversation_changed')
|
|
161
|
+
)`).get(principal.ownerId, principal.workspaceId);
|
|
162
|
+
return row.requested_at === null ? void 0 : Number(row.requested_at);
|
|
163
|
+
}
|
|
164
|
+
getProviderUsageSince(startedAt, operation) {
|
|
165
|
+
const row = this.db.prepare(`SELECT COUNT(*) AS calls, COALESCE(SUM(total_tokens), 0) AS total_tokens
|
|
166
|
+
FROM ai_usage_events WHERE operation = ? AND started_at >= ?`).get(operation, startedAt);
|
|
167
|
+
return {
|
|
168
|
+
calls: Number(row.calls),
|
|
169
|
+
totalTokens: Number(row.total_tokens)
|
|
170
|
+
};
|
|
164
171
|
}
|
|
165
172
|
listSuppressionKeys(principal) {
|
|
166
173
|
const rows = this.db.prepare(`SELECT f.scope_json, p.kind, p.project_id
|
|
@@ -110,10 +110,10 @@ var HomeSnapshotBuilder = class {
|
|
|
110
110
|
const successfulPatterns = [...input.successfulPatterns ?? []].filter((item) => item.successCount > 0).sort((left, right) => right.successCount - left.successCount || left.outcome.localeCompare(right.outcome)).slice(0, 20);
|
|
111
111
|
const stableContent = {
|
|
112
112
|
locale: input.locale,
|
|
113
|
-
projects,
|
|
114
|
-
tasks,
|
|
115
|
-
knowledge,
|
|
116
|
-
recentSessions,
|
|
113
|
+
projects: projects.map(({ updatedAt: _updatedAt, ...project }) => project),
|
|
114
|
+
tasks: tasks.map(({ updatedAt: _updatedAt, ...task }) => task),
|
|
115
|
+
knowledge: knowledge.map(({ updatedAt: _updatedAt, ...item }) => item),
|
|
116
|
+
recentSessions: recentSessions.map(({ updatedAt: _updatedAt, ...session }) => session),
|
|
117
117
|
successfulPatterns
|
|
118
118
|
};
|
|
119
119
|
return {
|
|
@@ -29,6 +29,9 @@ export type AiUsageTotals = {
|
|
|
29
29
|
knownCostUsd: string;
|
|
30
30
|
costCompleteness: 'complete' | 'partial' | 'unknown';
|
|
31
31
|
};
|
|
32
|
+
export type ConversationAiUsageTotals = Pick<AiUsageTotals, 'calls' | 'unknownCostCalls' | 'totalTokens' | 'knownCostUsd' | 'costCompleteness'>;
|
|
33
|
+
/** Aggregate all retained AI usage records for the requested conversations. */
|
|
34
|
+
export declare function summarizeAiUsageByConversations(conversationIds: readonly string[]): Map<string, ConversationAiUsageTotals>;
|
|
32
35
|
export declare function summarizeAiUsage(query: AiUsageQuery): {
|
|
33
36
|
totals: AiUsageTotals;
|
|
34
37
|
byCategory: Array<{
|
|
@@ -94,6 +94,30 @@ const TOTALS_SQL = `COUNT(*) AS calls,
|
|
|
94
94
|
COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,
|
|
95
95
|
COALESCE(SUM(total_tokens), 0) AS total_tokens,
|
|
96
96
|
COALESCE(SUM(estimated_cost_microusd), 0) AS known_cost_microusd`;
|
|
97
|
+
/** Aggregate all retained AI usage records for the requested conversations. */
|
|
98
|
+
function summarizeAiUsageByConversations(conversationIds) {
|
|
99
|
+
const uniqueIds = [...new Set(conversationIds.filter(Boolean))];
|
|
100
|
+
const result = /* @__PURE__ */ new Map();
|
|
101
|
+
const db = getSqliteDatabase();
|
|
102
|
+
for (let offset = 0; offset < uniqueIds.length; offset += 500) {
|
|
103
|
+
const batch = uniqueIds.slice(offset, offset + 500);
|
|
104
|
+
const rows = db.prepare(`SELECT conversation_id, ${TOTALS_SQL}
|
|
105
|
+
FROM ai_usage_events
|
|
106
|
+
WHERE conversation_id IN (${batch.map(() => "?").join(", ")})
|
|
107
|
+
GROUP BY conversation_id`).all(...batch);
|
|
108
|
+
for (const row of rows) {
|
|
109
|
+
const totals = totalsFromRow(row);
|
|
110
|
+
result.set(String(row.conversation_id), {
|
|
111
|
+
calls: totals.calls,
|
|
112
|
+
unknownCostCalls: totals.unknownCostCalls,
|
|
113
|
+
totalTokens: totals.totalTokens,
|
|
114
|
+
knownCostUsd: totals.knownCostUsd,
|
|
115
|
+
costCompleteness: totals.costCompleteness
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
97
121
|
function summarizeAiUsage(query) {
|
|
98
122
|
const { sql, values } = queryWhere(query);
|
|
99
123
|
const db = getSqliteDatabase();
|
|
@@ -172,4 +196,4 @@ function listAiUsageTrace(traceId) {
|
|
|
172
196
|
ORDER BY started_at ASC, id ASC`).all(traceId).map(eventFromRow);
|
|
173
197
|
}
|
|
174
198
|
//#endregion
|
|
175
|
-
export { AI_USAGE_RETENTION_MS, finishAiUsageEvent, getAiUsageEvent, getAiUsageEventView, insertAiUsageEvent, listAiUsageEvents, listAiUsageTrace, markStaleAiUsageEventsUnknown, pruneAiUsageEvents, summarizeAiUsage };
|
|
199
|
+
export { AI_USAGE_RETENTION_MS, finishAiUsageEvent, getAiUsageEvent, getAiUsageEventView, insertAiUsageEvent, listAiUsageEvents, listAiUsageTrace, markStaleAiUsageEventsUnknown, pruneAiUsageEvents, summarizeAiUsage, summarizeAiUsageByConversations };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.335",
|
|
4
4
|
"description": "Local-first personal AI for the one-person company, with durable context, tasks, workflows, automations, and local or cloud models.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -159,12 +159,12 @@
|
|
|
159
159
|
"vitest": "4.1.5",
|
|
160
160
|
"vue": "^3.5.35",
|
|
161
161
|
"@xopcai/browser-control-contract": "0.1.0",
|
|
162
|
+
"@xopcai/endpoint-tools-client": "0.0.0",
|
|
162
163
|
"@xopcai/computer-control-contract": "0.1.0",
|
|
163
164
|
"@xopcai/endpoint-tools-protocol": "0.0.0",
|
|
164
165
|
"@xopcai/gateway-contract": "0.0.0",
|
|
165
|
-
"@xopcai/
|
|
166
|
-
"@xopcai/realtime-client": "0.0.0"
|
|
167
|
-
"@xopcai/realtime-protocol": "0.0.0"
|
|
166
|
+
"@xopcai/realtime-protocol": "0.0.0",
|
|
167
|
+
"@xopcai/realtime-client": "0.0.0"
|
|
168
168
|
},
|
|
169
169
|
"scripts": {
|
|
170
170
|
"assets:brand": "node scripts/generate-brand-assets.mjs",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{p as e}from"./locale-store-BY30D6tg.js";var t=e(()=>({connectionState:`idle`,error:null}));function n(e){t.setState(e)}export{t as n,n as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e,r as t}from"./locale-store-BY30D6tg.js";import{d as n,g as r,h as i,i as a,l as o,p as s,r as c,s as l,t as u,u as d,v as f}from"./schemas-CObaziC7.js";import{t as p}from"./gateway-startup-retry-i-1lTrwY.js";var m=f().transform(e=>e.toLowerCase()).brand(),h=s().trim().regex(/^[a-z0-9][a-z0-9._-]{0,127}$/i).brand(),g=u([`active`,`idle`,`archived`,`pinned`]),_=d({agentId:s().optional(),source:s().optional(),accountId:s().optional(),peerKind:s().optional(),peerId:s().optional(),threadId:s().optional(),scopeId:s().optional()}).passthrough();d({agentId:s().optional(),projectId:s().optional(),key:s(),transcriptId:h.optional(),name:s().optional(),title:s().optional(),displayName:s().optional(),messageCount:o(),updatedAt:s(),sourceChannel:s().optional(),status:g.optional(),routing:_.optional()}).passthrough();var v=d({items:c(r()),total:o(),limit:o(),offset:o(),hasMore:a()}),y=d({role:s(),content:r(),timestamp:i([s(),o()]).optional()}).passthrough(),b=d({key:s(),messages:c(y)}).passthrough(),ee=d({session:b}),x=d({session:d({key:s(),transcriptId:h.optional(),messages:c(y),name:s().optional(),status:g.optional(),sourceChannel:s().optional(),sourceChatId:s().optional(),projectId:s().optional(),customData:n(s(),r()).optional(),routing:_.optional()}).passthrough(),pagination:d({total:o(),limit:o(),offset:o(),hasMore:a(),before:s().optional(),nextBeforeCursor:s().optional(),revision:o().int().nonnegative().optional()}).passthrough()}).passthrough(),S=d({ok:l(!0),conversationId:f(),rowCount:o().int().nonnegative(),lastTurnId:s().min(1),session:b}).passthrough(),C=d({ok:a().optional(),payload:d({active:a(),runId:s().optional()}).passthrough().optional()}).passthrough(),w=d({ok:a().optional(),error:s().optional()}).passthrough(),T=w.extend({renamed:a().optional()}),E=w.extend({reset:a().optional(),transcriptId:h.optional(),previousTranscriptId:s().optional(),session:r().optional()}),D=d({totalSessions:o(),activeSessions:o(),archivedSessions:o(),pinnedSessions:o(),totalMessages:o(),totalTokens:o(),oldestSession:s().optional(),newestSession:s().optional(),byChannel:n(s(),o())}).passthrough();d({ok:a(),payload:d({conversationId:f(),transcriptId:h,session:r()}).passthrough().optional(),error:s().optional()}).passthrough();var O=d({ok:l(!0),projects:d({items:c(d({project:r(),sessions:c(r()),sessionTotal:o(),sessionHasMore:a()}).passthrough()),total:o(),limit:o(),offset:o(),hasMore:a()}),inbox:v,pinned:c(r()).default([]),layouts:n(s(),d({itemIds:c(s()),revision:o().int().nonnegative()})).default({})}).passthrough();function k(e){return ee.parse(e)}function A(e){return x.parse(e)}function j(e){return S.parse(e)}function M(e){return C.parse(e)}function N(e){return w.parse(e)}function P(e){return T.parse(e)}function F(e){return E.parse(e)}function I(e){return D.parse(e)}function L(e){return O.parse(e)}function R(e){let t=M(e).payload,n=typeof t?.runId==`string`?t.runId.trim():``;return!t?.active||!n?{active:!1}:{active:!0,runId:n}}function z(e){let t=new URLSearchParams;if(!e)return``;e.status&&t.set(`status`,e.status),e.search&&t.set(`search`,e.search),e.channel&&t.set(`channel`,e.channel),e.sources?.length&&t.set(`sources`,e.sources.join(`,`)),e.purposes?.length&&t.set(`purposes`,e.purposes.join(`,`)),e.activity&&t.set(`activity`,e.activity),e.agentId&&t.set(`agentId`,e.agentId),e.excludeArchived&&t.set(`excludeArchived`,`true`),e.projectId&&t.set(`projectId`,e.projectId),e.unassigned&&t.set(`unassigned`,`true`),e.updatedAfter!=null&&t.set(`updatedAfter`,String(e.updatedAfter)),e.includePinned&&t.set(`includePinned`,`true`),e.includeConversationId&&t.set(`includeConversationId`,e.includeConversationId),e.sessionTypes?.length&&t.set(`types`,e.sessionTypes.join(`,`)),e.sortBy&&t.set(`sortBy`,e.sortBy),e.sortOrder&&t.set(`sortOrder`,e.sortOrder),e.limit!=null&&t.set(`limit`,String(e.limit)),e.offset!=null&&t.set(`offset`,String(e.offset));let n=t.toString();return n?`?${n}`:``}function B(e,t){let n=[];t?.includeTranscript&&n.push(`transcript`),t?.includeTranscriptRows&&n.push(`transcriptRows`);let r=n.length?`?include=${n.join(`,`)}`:``;return`/api/sessions/${encodeURIComponent(e)}${r}`}function te(e){return`/api/sessions/${encodeURIComponent(e)}/fork-at-turn`}function V(e,t){let n=new URLSearchParams;n.set(`limit`,String(t?.limit??50));let r=t?.before?.trim();return r?n.set(`before`,r):t?.offset!=null&&n.set(`offset`,String(t.offset)),`/api/sessions/${encodeURIComponent(e)}/history?${n.toString()}`}function H(e){return`/api/sessions/${encodeURIComponent(e)}/run`}function U(){return`/api/sessions/stats`}function W(e){let t=new URLSearchParams;e?.projectLimit!=null&&t.set(`projectLimit`,String(e.projectLimit)),e?.projectOffset!=null&&t.set(`projectOffset`,String(e.projectOffset)),e?.sessionPreviewLimit!=null&&t.set(`sessionPreviewLimit`,String(e.sessionPreviewLimit)),e?.inboxLimit!=null&&t.set(`inboxLimit`,String(e.inboxLimit)),e?.inboxOffset!=null&&t.set(`inboxOffset`,String(e.inboxOffset)),e?.staleDays!=null&&t.set(`staleDays`,String(e.staleDays)),e?.includeConversationId&&t.set(`includeConversationId`,e.includeConversationId);let n=t.toString();return`/api/sidebar/chat-list${n?`?${n}`:``}`}function G(e){return`/api/sidebar/layouts/${encodeURIComponent(e)}`}function K(e,t){let n=encodeURIComponent(e);return t===`delete`?`/api/sessions/${n}`:`/api/sessions/${n}/${t}`}function q(e){return e?JSON.stringify({status:e.status,search:e.search,channel:e.channel,sources:e.sources,purposes:e.purposes,activity:e.activity,agentId:e.agentId,excludeArchived:e.excludeArchived,projectId:e.projectId,unassigned:e.unassigned,updatedAfter:e.updatedAfter,includePinned:e.includePinned,includeConversationId:e.includeConversationId,sessionTypes:e.sessionTypes,sortBy:e.sortBy,sortOrder:e.sortOrder,limit:e.limit,offset:e.offset}):`default`}var J=new Map;async function Y(e){let n=q(e),r=J.get(n);if(r)return r;let i=t(`/api/sessions${z(e)}`),a=(async()=>{let e=await p(i);if(!e.ok){let t=await e.json().catch(()=>({})),n=typeof t.error==`string`?t.error:t.error?.message;throw Error(n??`HTTP ${e.status}`)}return await e.json()})().finally(()=>{J.delete(n)});return J.set(n,a),a}async function X(n){return L(await e(t(W(n))))}async function Z(n){let r=await e(t(G(n.containerId)),{method:`PUT`,body:JSON.stringify({itemIds:n.itemIds,expectedRevision:n.expectedRevision})});if(!r.ok||!r.layout)throw Error(r.error??`Failed to save sidebar order`);return r.layout}async function Q(){return I(await e(t(U())))}async function ne(n,r){let i=k(await e(t(B(n,r))));if(!i.session)throw Error(`Session not found`);return i.session}async function re(n){let r=await e(t(`/api/sessions/resolve`),{method:`POST`,body:JSON.stringify(n)});if(!r.ok||!r.payload)throw Error(r.error??`Session not found`);return r.payload}async function ie(n){N(await e(t(K(n,`delete`)),{method:`DELETE`}))}async function ae(n,r){return{renamed:P(await e(t(K(n,`rename`)),{method:`POST`,body:JSON.stringify({name:r})})).renamed===!0}}async function oe(n){N(await e(t(K(n,`archive`)),{method:`POST`}))}async function $(n){N(await e(t(K(n,`unarchive`)),{method:`POST`}))}async function se(n){N(await e(t(K(n,`pin`)),{method:`POST`}))}async function ce(n){N(await e(t(K(n,`unpin`)),{method:`POST`}))}async function le(n){return(await e(t(`/api/sessions/${encodeURIComponent(n)}/export?format=json`))).content}export{R as _,ne as a,F as b,se as c,Z as d,$ as f,H as g,V as h,X as i,ae as l,te as m,ie as n,Q as o,ce as p,le as r,Y as s,oe as t,re as u,j as v,m as x,A as y};
|