@xopcai/xopc 0.0.205 → 0.0.206
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-DJBadfSX.js → activity-store-URW-e_me.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Br6C32BX.js → agent-avatar-dicebear-BLK6kRCJ.js} +1 -1
- package/dist/gateway/static/root/assets/agents-D5HVmdNx.js +68 -0
- package/dist/gateway/static/root/assets/{api-B5O7fKXa.js → api-C_MS4arC.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-Le1vJ1OO.js → app-management-settings-panel-CnUN6BJk.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-CZlAU60t.js → appearance-settings-C8Nx8hZE.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-DKCA_LFY.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-CRzXRXPE.js → archive-plugin-C7FqeJZD.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-CYAAQ6Qi.js → attachment-load-DCYQgsYE.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-BEOE4ZKM.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-CVR5cUmS.js → binary-plugins-Bf1WROsh.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CFe74rWi.js → block-editor-BPK08Pjv.js} +46 -46
- package/dist/gateway/static/root/assets/browser-settings-page-CLRmMdU9.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-Bd68yluo.js → browser-workflow-inputs-cqVoDHyp.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-B0uiDLga.js → browser-workflows-page-Des1UTsS.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BNcVi4ar.js +7 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-BerPMp6f.js → capability-presets-api-D4MjqV2a.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-DJjVOCJY.js → capability-presets-settings-panel-uFwW2ah5.js} +2 -2
- package/dist/gateway/static/root/assets/{channel-recipient-api-D2d21_XA.js → channel-recipient-api-CcimZduy.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DSLP8OjS.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-D0OR6Ylw.js +1 -0
- package/dist/gateway/static/root/assets/chat-terminal-dock-B1njb2Cr.css +1 -0
- package/dist/gateway/static/root/assets/chat-terminal-dock-wpi7abPg.js +38 -0
- package/dist/gateway/static/root/assets/{connectors-api-Bq_vUzxP.js → connectors-api-CUvFu8jh.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-BJoHjWnu.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-DZBxmKGR.js → cron-expression-hFSZZpvM.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BNHd7HT7.js → date-picker-CKZ0gc-Y.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-D1kJBknt.js → dependency-picker-zv1oHtg4.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Di75oHkC.js → desktop-pet-DY9ykMtD.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-D6tD1uym.js → desktop-pet-settings-XiSmmt26.js} +1 -1
- package/dist/gateway/static/root/assets/directory-picker-path-field-CZkgk15r.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-D91_S7NQ.js → extension-debug-page-CTppsTEi.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DHzmmr_N.js → extension-page-CHRTUvAa.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BpJNtePi.js → extension-settings-page-z2UBx25A.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-BAzLYTKZ.js → gateway-config-api-DzFPJTnm.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-VVcfd3sG.js → gateway-config-swr-CGpoH1gU.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-C5-aKkTp.js → gateway-settings-DBa2I6VM.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-qAX_T2t2.js → gateway-startup-retry-Te-TREBt.js} +1 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-DyQGGdBu.js +1 -0
- package/dist/gateway/static/root/assets/home-page-EkT4eGeP.js +3 -0
- package/dist/gateway/static/root/assets/index-BpLqHdfz.css +2 -0
- package/dist/gateway/static/root/assets/index-CrwXzRpA.js +85 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-fpNjXnJK.js → keyboard-shortcuts-settings-fb0zS8pk.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CCC3Cvb8.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DBpQIfNd.js → local-apps-page-DFdheruU.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-CbPVxonP.js → locale-store-CieddUjx.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-BmXcJCKz.js → logs-page-B6jfkNDF.js} +2 -2
- package/dist/gateway/static/root/assets/{management-settings-CiK7Xkvi.js → management-settings-D3PsQ612.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-DVgpcOze.js → markdown-split-x5K52Thz.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-Dl-0_9JR.js → markdown-view-Cjjey5Y6.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DMj1lW-n.js → media-plugins-DNtEkRAh.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CySMn8WL.js +3 -0
- package/dist/gateway/static/root/assets/{notes-page-DvX1sTlf.js → notes-page-nWEqlwDw.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-QstkgWsW.js +4 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-DvsLigha.js → preview-open-alternatives-CXcIKVi9.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-DbCraAI3.js → product-open-page-CZLJudPk.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-Cf1v94LO.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BRMZkNht.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-D55FTXZw.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DzuUglQo.js → runtime-tools-settings-panel-RYjduQV6.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-plDnazVj.js → schema-form--1ZXg4qC.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-C5Yy6eIn.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BqO_8bUh.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-BwAxX_7e.js → settings-form-section-71-8j3zt.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-B3OiTnF9.js → settings-loading-skeleton-C5Jn1l0q.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-DvIWXBvp.js → settings-page-TYYGe6kZ.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-DThKKjLV.js → setup-status-panel-jA5I-17g.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-CFnoGHJb.js → share-preview-page-BMUQIGfk.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-Dru1a2rZ.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-C8iqS6kF.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-B38fY22S.js → skills-page-BzZT1SKg.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-vLIlk1c3.js → skills-page.utils-DnaBw5Ji.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DRV2wljT.js → system-settings-panel-DqiPQgVI.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-DQP5vDr-.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-Bc_eRUev.js → theme-store-BP3_RpaY.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-DTu23D9J.js → use-autosave-BJkQ-vpu.js} +1 -1
- package/dist/gateway/static/root/assets/{user-context-page-DCwqzN03.js → user-context-page-BP8-sOPi.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-CVDMesWc.js → voice-api-key-field-C6c8e7Mx.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-cyt93k0V.js → work-discovery-overlay-CCNjWKql.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-page-DL_Ie0s2.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DrdcfX_N.js → workflow-run-setup-panel-DLO-dMSN.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-B4-k2FHB.js +5 -0
- package/dist/gateway/static/root/assets/{working-directory-picker-modal-CYWdZUJ5.js → working-directory-picker-modal-vWi33CZJ.js} +1 -1
- package/dist/gateway/static/root/index.html +10 -10
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +11 -0
- package/dist/src/agent/agent-manager.js +36 -6
- package/dist/src/agent/service.d.ts +4 -1
- package/dist/src/agent/service.js +12 -0
- package/dist/src/agent/tools/xopc-use-tool.js +6 -2
- package/dist/src/automations/api/routes.js +8 -0
- package/dist/src/automations/domain/index.js +2 -2
- package/dist/src/automations/domain/types.d.ts +17 -12
- package/dist/src/automations/domain/validation.d.ts +30 -32
- package/dist/src/automations/domain/validation.js +8 -10
- package/dist/src/automations/draft/automation-draft-prompt.js +9 -5
- package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -8
- package/dist/src/automations/draft/automation-draft-validator.js +3 -3
- package/dist/src/automations/index.js +2 -2
- package/dist/src/automations/service/action-executor.js +13 -4
- package/dist/src/automations/service/automation-service.d.ts +5 -1
- package/dist/src/automations/service/automation-service.js +19 -12
- package/dist/src/automations/storage/automation-repository.js +8 -4
- package/dist/src/automations/storage/automation-run-repository.d.ts +5 -0
- package/dist/src/automations/storage/automation-run-repository.js +24 -8
- package/dist/src/automations/storage/index.js +2 -2
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/gateway/automation-agent-session.d.ts +4 -0
- package/dist/src/gateway/automation-agent-session.js +40 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js +3 -2
- package/dist/src/gateway/hono/routes/commands-skills.js +36 -2
- package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -0
- package/dist/src/gateway/service/marketplace-service.d.ts +4 -1
- package/dist/src/gateway/service/marketplace-service.js +9 -0
- package/dist/src/gateway/service.js +19 -2
- package/dist/src/mobile/notification-service.js +7 -4
- package/dist/src/storage/sqlite/migrations/121_automation_inbox.sql +24 -0
- package/dist/src/storage/sqlite/migrations/122_automation_session_projects.sql +18 -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/package.json +3 -2
- package/dist/gateway/static/root/assets/agents-DnFIy8Ye.js +0 -68
- package/dist/gateway/static/root/assets/apps-page-CONlVc-f.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-DuG69tIj.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-Cvt-8fqE.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-yk3QkGBP.js +0 -7
- package/dist/gateway/static/root/assets/channels-settings-CaNnYUQo.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-CZ5P9jbB.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DTpCnOsQ.js +0 -2
- package/dist/gateway/static/root/assets/directory-picker-path-field-Ly0TUflq.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CMZr1_Op.js +0 -1
- package/dist/gateway/static/root/assets/home-page-CBG9Bk-1.js +0 -3
- package/dist/gateway/static/root/assets/index-BBw9QL0p.js +0 -85
- package/dist/gateway/static/root/assets/index-Dm-cvIpl.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-Bi_0Sknt.js +0 -2
- package/dist/gateway/static/root/assets/messages-9zCa8KkW.js +0 -3
- package/dist/gateway/static/root/assets/notes-workbench-CMyosgjY.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-DkS-kbpj.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B3NxP6S4.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-DwhrMhjl.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BOfXXmBL.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-sPrZfZVR.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Dvl13Udt.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-D9elkZOz.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-Xd8PlB24.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page--DTi90d5.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DXyButkm.js +0 -5
|
@@ -157,19 +157,28 @@ var AutomationActionExecutor = class {
|
|
|
157
157
|
status: "failed",
|
|
158
158
|
error: "Agent service is not available"
|
|
159
159
|
};
|
|
160
|
+
const agentId = normalizeAgentId(action.agentId || this.deps.getDefaultAgentId?.() || "main");
|
|
161
|
+
const peerId = automation.conversationMode === "continuous" ? automation.id : `${automation.id}-${crypto.randomUUID().slice(0, 8)}`;
|
|
160
162
|
const sessionKey = buildSessionKey({
|
|
161
|
-
agentId
|
|
163
|
+
agentId,
|
|
162
164
|
source: "automation",
|
|
163
165
|
accountId: "default",
|
|
164
166
|
peerKind: "dm",
|
|
165
|
-
peerId
|
|
167
|
+
peerId
|
|
166
168
|
});
|
|
167
|
-
const effectiveWorkingDirectory = action.workingDirectory ?? (automation.projectId ? this.deps.getProjectWorkspaceRoot?.(automation.projectId) : void 0);
|
|
168
169
|
await hooks.onRunPatch?.({
|
|
169
170
|
sessionKey,
|
|
170
171
|
currentPhase: "action"
|
|
171
172
|
});
|
|
172
|
-
await
|
|
173
|
+
await this.deps.prepareAgentSession?.({
|
|
174
|
+
sessionKey,
|
|
175
|
+
projectId: automation.projectId,
|
|
176
|
+
agentId,
|
|
177
|
+
peerId,
|
|
178
|
+
automationId: automation.id,
|
|
179
|
+
runId: run.id
|
|
180
|
+
});
|
|
181
|
+
await agentService.sessionConfig?.applyAutomationWorkingDirectory?.(sessionKey, automation.projectId ? void 0 : action.workingDirectory);
|
|
173
182
|
if (agentService.sessionConfig?.applyAutomationModelOverride) {
|
|
174
183
|
if (!await agentService.sessionConfig.applyAutomationModelOverride(sessionKey, action.model) && action.model) log.warn({
|
|
175
184
|
automationId: automation.id,
|
|
@@ -49,6 +49,10 @@ export declare class AutomationService {
|
|
|
49
49
|
}): Promise<AutomationProductEventRun[]>;
|
|
50
50
|
getRun(runId: string): Promise<AutomationRun | null>;
|
|
51
51
|
listRunEvents(runId: string): Promise<AutomationRunEvent[]>;
|
|
52
|
+
markRunRead(runId: string): Promise<boolean>;
|
|
53
|
+
markAllRunsRead(options?: {
|
|
54
|
+
projectId?: string;
|
|
55
|
+
}): Promise<number>;
|
|
52
56
|
cancelRun(runId: string): Promise<boolean>;
|
|
53
57
|
getMetrics(): Promise<AutomationMetrics>;
|
|
54
58
|
private recomputeNextRuns;
|
|
@@ -60,5 +64,5 @@ export declare class AutomationService {
|
|
|
60
64
|
private waitForRetry;
|
|
61
65
|
private appendRunEvent;
|
|
62
66
|
private finishAutomationRun;
|
|
63
|
-
private
|
|
67
|
+
private postCompletionWebhook;
|
|
64
68
|
}
|
|
@@ -5,7 +5,7 @@ import { computeNextAutomationRunAtMs, timerDelayUntil } from "../domain/schedul
|
|
|
5
5
|
import { AutomationSchema, CreateAutomationSchema, UpdateAutomationSchema } from "../domain/validation.js";
|
|
6
6
|
import { AutomationActionExecutor } from "./action-executor.js";
|
|
7
7
|
import { deleteAutomation, getAutomation, listAutomations, saveAutomation, saveAutomations } from "../storage/automation-repository.js";
|
|
8
|
-
import { appendAutomationRunEvent, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, saveAutomationRun, touchAutomationRunLease } from "../storage/automation-run-repository.js";
|
|
8
|
+
import { appendAutomationRunEvent, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, markAllAutomationRunsRead, markAutomationRunRead, saveAutomationRun, touchAutomationRunLease } from "../storage/automation-run-repository.js";
|
|
9
9
|
import "../storage/index.js";
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
11
|
//#region src/automations/service/automation-service.ts
|
|
@@ -71,7 +71,8 @@ var AutomationService = class {
|
|
|
71
71
|
id: parsed.id?.trim() || randomUUID().slice(0, 12),
|
|
72
72
|
enabled: parsed.enabled ?? true,
|
|
73
73
|
safety: parsed.safety ?? { mode: "auto_apply" },
|
|
74
|
-
|
|
74
|
+
conversationMode: parsed.conversationMode ?? "new_session",
|
|
75
|
+
notificationPolicy: parsed.notificationPolicy ?? "attention",
|
|
75
76
|
state: parsed.state ?? {},
|
|
76
77
|
createdAtMs: now,
|
|
77
78
|
updatedAtMs: now
|
|
@@ -165,6 +166,12 @@ var AutomationService = class {
|
|
|
165
166
|
async listRunEvents(runId) {
|
|
166
167
|
return listAutomationRunEvents(runId);
|
|
167
168
|
}
|
|
169
|
+
async markRunRead(runId) {
|
|
170
|
+
return markAutomationRunRead(runId);
|
|
171
|
+
}
|
|
172
|
+
async markAllRunsRead(options) {
|
|
173
|
+
return markAllAutomationRunsRead(options);
|
|
174
|
+
}
|
|
168
175
|
async cancelRun(runId) {
|
|
169
176
|
const controller = this.activeRuns.get(runId);
|
|
170
177
|
if (!controller) return false;
|
|
@@ -389,30 +396,30 @@ var AutomationService = class {
|
|
|
389
396
|
};
|
|
390
397
|
this.appendRunEvent(run, task.termination.cancellationConfirmed ? "run.cancel_confirmed" : "run.cancellation_unconfirmed", task.termination.cancellationConfirmed ? "Automation cancellation confirmed" : "Automation cancellation was not confirmed within the cleanup grace period", { termination: task.termination });
|
|
391
398
|
}
|
|
392
|
-
if (status === "timeout" || status === "cancelled") {} else if ((automation.safety?.mode ?? "auto_apply") !== "auto_apply" && automation.
|
|
393
|
-
else if (automation.
|
|
394
|
-
activePhase = "
|
|
399
|
+
if (status === "timeout" || status === "cancelled") {} else if ((automation.safety?.mode ?? "auto_apply") !== "auto_apply" && automation.completionWebhookUrl) this.appendRunEvent(run, "completion_hook.completed", "Completion webhook skipped by safety mode", { safety: automation.safety ?? { mode: "auto_apply" } });
|
|
400
|
+
else if (automation.completionWebhookUrl) {
|
|
401
|
+
activePhase = "completion_hook";
|
|
395
402
|
run = {
|
|
396
403
|
...run,
|
|
397
|
-
currentPhase: "
|
|
404
|
+
currentPhase: "completion_hook"
|
|
398
405
|
};
|
|
399
406
|
saveAutomationRun(run);
|
|
400
|
-
this.appendRunEvent(run, "
|
|
401
|
-
await this.
|
|
402
|
-
this.appendRunEvent(run, "
|
|
407
|
+
this.appendRunEvent(run, "completion_hook.started", "Calling completion webhook", { url: automation.completionWebhookUrl });
|
|
408
|
+
await this.postCompletionWebhook(automation.completionWebhookUrl, run, controller.signal);
|
|
409
|
+
this.appendRunEvent(run, "completion_hook.completed", "Completion webhook completed");
|
|
403
410
|
}
|
|
404
411
|
} catch (err) {
|
|
405
412
|
error = err instanceof Error ? err.message : String(err);
|
|
406
413
|
const deadlineExceeded = run.deadlineAtMs !== void 0 && Date.now() >= run.deadlineAtMs;
|
|
407
414
|
status = controller.signal.aborted ? "cancelled" : deadlineExceeded ? "timeout" : "failed";
|
|
408
|
-
this.appendRunEvent(run, activePhase === "
|
|
415
|
+
this.appendRunEvent(run, activePhase === "completion_hook" ? "completion_hook.failed" : "action.failed", `Automation run ${status}`, { error });
|
|
409
416
|
run = {
|
|
410
417
|
...run,
|
|
411
418
|
status,
|
|
412
419
|
error,
|
|
413
420
|
termination: {
|
|
414
421
|
reason: status === "cancelled" ? "user_cancelled" : status === "timeout" ? "deadline_exceeded" : "failed",
|
|
415
|
-
component: activePhase === "
|
|
422
|
+
component: activePhase === "completion_hook" ? "automation" : run.termination?.component,
|
|
416
423
|
cancellationConfirmed: status !== "cancelled" || controller.signal.aborted
|
|
417
424
|
}
|
|
418
425
|
};
|
|
@@ -580,7 +587,7 @@ var AutomationService = class {
|
|
|
580
587
|
saveAutomation(next);
|
|
581
588
|
this.armTimer();
|
|
582
589
|
}
|
|
583
|
-
async
|
|
590
|
+
async postCompletionWebhook(url, run, signal) {
|
|
584
591
|
const remainingMs = run.deadlineAtMs === void 0 ? 3e4 : Math.max(1, run.deadlineAtMs - Date.now());
|
|
585
592
|
const requestSignal = AbortSignal.any([signal, AbortSignal.timeout(remainingMs)]);
|
|
586
593
|
const response = await fetch(url, {
|
|
@@ -18,7 +18,9 @@ function rowToAutomation(row) {
|
|
|
18
18
|
trigger: parseJson(row.trigger_json),
|
|
19
19
|
action: parseJson(row.action_json),
|
|
20
20
|
safety: parseJson(row.safety_json) ?? { mode: "auto_apply" },
|
|
21
|
-
|
|
21
|
+
conversationMode: row.conversation_mode,
|
|
22
|
+
notificationPolicy: row.notification_policy,
|
|
23
|
+
completionWebhookUrl: row.completion_webhook_url ?? void 0,
|
|
22
24
|
reliability: parseJson(row.reliability_json),
|
|
23
25
|
state: parseJson(row.state_json) ?? {},
|
|
24
26
|
createdAtMs: row.created_at_ms,
|
|
@@ -28,12 +30,14 @@ function rowToAutomation(row) {
|
|
|
28
30
|
function upsertAutomation(db, automation) {
|
|
29
31
|
db.prepare(`INSERT OR REPLACE INTO automations (
|
|
30
32
|
automation_id, name, description, project_id, enabled, trigger_json, action_json,
|
|
31
|
-
safety_json,
|
|
32
|
-
|
|
33
|
+
safety_json, conversation_mode, notification_policy, completion_webhook_url,
|
|
34
|
+
reliability_json, state_json, created_at_ms, updated_at_ms
|
|
35
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(automation.id, automation.name, automation.description ?? null, automation.projectId ?? null, automation.enabled ? 1 : 0, JSON.stringify(automation.trigger), JSON.stringify(automation.action), bindJson(automation.safety ?? { mode: "auto_apply" }), automation.conversationMode, automation.notificationPolicy, automation.completionWebhookUrl ?? null, bindJson(automation.reliability), JSON.stringify(automation.state ?? {}), automation.createdAtMs, automation.updatedAtMs);
|
|
33
36
|
}
|
|
34
37
|
const AUTOMATION_SELECT = `
|
|
35
38
|
SELECT automation_id, name, description, project_id, enabled, trigger_json, action_json,
|
|
36
|
-
safety_json,
|
|
39
|
+
safety_json, conversation_mode, notification_policy, completion_webhook_url,
|
|
40
|
+
reliability_json, state_json, created_at_ms, updated_at_ms
|
|
37
41
|
FROM automations
|
|
38
42
|
`;
|
|
39
43
|
function listAutomations(options) {
|
|
@@ -17,3 +17,8 @@ export declare function listAutomationRunsForProductEvent(options: {
|
|
|
17
17
|
limit?: number;
|
|
18
18
|
}): AutomationProductEventRun[];
|
|
19
19
|
export declare function deleteAutomationRunsForAutomation(automationId: string): void;
|
|
20
|
+
export declare function markAutomationRunRead(runId: string, readAtMs?: number): boolean;
|
|
21
|
+
export declare function markAllAutomationRunsRead(options?: {
|
|
22
|
+
projectId?: string;
|
|
23
|
+
readAtMs?: number;
|
|
24
|
+
}): number;
|
|
@@ -29,7 +29,8 @@ function rowToRun(row) {
|
|
|
29
29
|
leaseOwner: row.lease_owner ?? void 0,
|
|
30
30
|
leaseExpiresAtMs: row.lease_expires_at_ms ?? void 0,
|
|
31
31
|
attemptNumber: row.attempt_number,
|
|
32
|
-
rootRunId: row.root_run_id ?? void 0
|
|
32
|
+
rootRunId: row.root_run_id ?? void 0,
|
|
33
|
+
readAtMs: row.read_at_ms ?? void 0
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
function rowToEvent(row) {
|
|
@@ -68,8 +69,8 @@ function saveAutomationRun(run) {
|
|
|
68
69
|
duration_ms, summary, error, session_key, workflow_run_id, model,
|
|
69
70
|
deadline_at_ms, current_phase, cancel_requested_at_ms, cancel_confirmed_at_ms,
|
|
70
71
|
termination_json, heartbeat_at_ms, lease_owner, lease_expires_at_ms,
|
|
71
|
-
attempt_number, root_run_id
|
|
72
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(run.id, run.automationId, run.automationName, run.status, JSON.stringify(run.triggerSnapshot), JSON.stringify(run.actionSnapshot), run.manual ? 1 : 0, run.createdAtMs, run.startedAtMs ?? null, run.endedAtMs ?? null, run.durationMs ?? null, run.summary ?? null, run.error ?? null, run.sessionKey ?? null, run.workflowRunId ?? null, run.model ?? null, run.deadlineAtMs ?? null, run.currentPhase ?? null, run.cancelRequestedAtMs ?? null, run.cancelConfirmedAtMs ?? null, run.termination ? JSON.stringify(run.termination) : null, run.heartbeatAtMs ?? null, run.leaseOwner ?? null, run.leaseExpiresAtMs ?? null, run.attemptNumber ?? 1, run.rootRunId ?? run.id);
|
|
72
|
+
attempt_number, root_run_id, read_at_ms
|
|
73
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(run.id, run.automationId, run.automationName, run.status, JSON.stringify(run.triggerSnapshot), JSON.stringify(run.actionSnapshot), run.manual ? 1 : 0, run.createdAtMs, run.startedAtMs ?? null, run.endedAtMs ?? null, run.durationMs ?? null, run.summary ?? null, run.error ?? null, run.sessionKey ?? null, run.workflowRunId ?? null, run.model ?? null, run.deadlineAtMs ?? null, run.currentPhase ?? null, run.cancelRequestedAtMs ?? null, run.cancelConfirmedAtMs ?? null, run.termination ? JSON.stringify(run.termination) : null, run.heartbeatAtMs ?? null, run.leaseOwner ?? null, run.leaseExpiresAtMs ?? null, run.attemptNumber ?? 1, run.rootRunId ?? run.id, run.readAtMs ?? null);
|
|
73
74
|
trimRuns(db, run.automationId);
|
|
74
75
|
});
|
|
75
76
|
}
|
|
@@ -90,7 +91,7 @@ function getAutomationRun(runId) {
|
|
|
90
91
|
duration_ms, summary, error, session_key, workflow_run_id, model,
|
|
91
92
|
deadline_at_ms, current_phase, cancel_requested_at_ms, cancel_confirmed_at_ms,
|
|
92
93
|
termination_json, heartbeat_at_ms, lease_owner, lease_expires_at_ms,
|
|
93
|
-
attempt_number, root_run_id
|
|
94
|
+
attempt_number, root_run_id, read_at_ms
|
|
94
95
|
FROM automation_runs
|
|
95
96
|
WHERE run_id = ?`).get(runId);
|
|
96
97
|
return row ? rowToRun(row) : null;
|
|
@@ -103,7 +104,7 @@ function listAutomationRuns(options) {
|
|
|
103
104
|
duration_ms, summary, error, session_key, workflow_run_id, model,
|
|
104
105
|
deadline_at_ms, current_phase, cancel_requested_at_ms, cancel_confirmed_at_ms,
|
|
105
106
|
termination_json, heartbeat_at_ms, lease_owner, lease_expires_at_ms,
|
|
106
|
-
attempt_number, root_run_id
|
|
107
|
+
attempt_number, root_run_id, read_at_ms
|
|
107
108
|
FROM automation_runs`;
|
|
108
109
|
let rows;
|
|
109
110
|
if (options?.automationId) rows = db.prepare(`${base} WHERE automation_id = ? ORDER BY created_at_ms DESC LIMIT ?`).all(options.automationId, limit);
|
|
@@ -112,7 +113,7 @@ function listAutomationRuns(options) {
|
|
|
112
113
|
r.duration_ms, r.summary, r.error, r.session_key, r.workflow_run_id, r.model,
|
|
113
114
|
r.deadline_at_ms, r.current_phase, r.cancel_requested_at_ms, r.cancel_confirmed_at_ms,
|
|
114
115
|
r.termination_json, r.heartbeat_at_ms, r.lease_owner, r.lease_expires_at_ms,
|
|
115
|
-
r.attempt_number, r.root_run_id
|
|
116
|
+
r.attempt_number, r.root_run_id, r.read_at_ms
|
|
116
117
|
FROM automation_runs r
|
|
117
118
|
JOIN automations a ON a.automation_id = r.automation_id
|
|
118
119
|
WHERE a.project_id = ?
|
|
@@ -138,7 +139,7 @@ function listAutomationRunsForProductEvent(options) {
|
|
|
138
139
|
r.duration_ms, r.summary, r.error, r.session_key, r.workflow_run_id, r.model,
|
|
139
140
|
r.deadline_at_ms, r.current_phase, r.cancel_requested_at_ms, r.cancel_confirmed_at_ms,
|
|
140
141
|
r.termination_json, r.heartbeat_at_ms, r.lease_owner, r.lease_expires_at_ms,
|
|
141
|
-
r.attempt_number, r.root_run_id,
|
|
142
|
+
r.attempt_number, r.root_run_id, r.read_at_ms,
|
|
142
143
|
e.event_id, e.run_id AS event_run_id, e.automation_id AS event_automation_id,
|
|
143
144
|
e.type AS event_type, e.message AS event_message, e.data_json AS event_data_json,
|
|
144
145
|
e.created_at_ms AS event_created_at_ms
|
|
@@ -165,5 +166,20 @@ function deleteAutomationRunsForAutomation(automationId) {
|
|
|
165
166
|
db.prepare(`DELETE FROM automation_runs WHERE automation_id = ?`).run(automationId);
|
|
166
167
|
});
|
|
167
168
|
}
|
|
169
|
+
function markAutomationRunRead(runId, readAtMs = Date.now()) {
|
|
170
|
+
return getSqliteDatabase().prepare(`UPDATE automation_runs SET read_at_ms = ? WHERE run_id = ? AND ended_at_ms IS NOT NULL`).run(readAtMs, runId).changes > 0;
|
|
171
|
+
}
|
|
172
|
+
function markAllAutomationRunsRead(options) {
|
|
173
|
+
const projectId = options?.projectId?.trim();
|
|
174
|
+
const result = getSqliteDatabase().prepare(projectId ? `UPDATE automation_runs
|
|
175
|
+
SET read_at_ms = ?
|
|
176
|
+
WHERE read_at_ms IS NULL
|
|
177
|
+
AND ended_at_ms IS NOT NULL
|
|
178
|
+
AND EXISTS (
|
|
179
|
+
SELECT 1 FROM automations a
|
|
180
|
+
WHERE a.automation_id = automation_runs.automation_id AND a.project_id = ?
|
|
181
|
+
)` : `UPDATE automation_runs SET read_at_ms = ? WHERE read_at_ms IS NULL AND ended_at_ms IS NOT NULL`).run(options?.readAtMs ?? Date.now(), ...projectId ? [projectId] : []);
|
|
182
|
+
return Number(result.changes);
|
|
183
|
+
}
|
|
168
184
|
//#endregion
|
|
169
|
-
export { appendAutomationRunEvent, deleteAutomationRunsForAutomation, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, saveAutomationRun, touchAutomationRunLease };
|
|
185
|
+
export { appendAutomationRunEvent, deleteAutomationRunsForAutomation, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, markAllAutomationRunsRead, markAutomationRunRead, saveAutomationRun, touchAutomationRunLease };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { deleteAutomation, getAutomation, listAutomations, saveAutomation, saveAutomations } from "./automation-repository.js";
|
|
2
|
-
import { appendAutomationRunEvent, deleteAutomationRunsForAutomation, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, saveAutomationRun, touchAutomationRunLease } from "./automation-run-repository.js";
|
|
3
|
-
export { appendAutomationRunEvent, deleteAutomation, deleteAutomationRunsForAutomation, getAutomation, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, listAutomations, saveAutomation, saveAutomationRun, saveAutomations, touchAutomationRunLease };
|
|
2
|
+
import { appendAutomationRunEvent, deleteAutomationRunsForAutomation, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, markAllAutomationRunsRead, markAutomationRunRead, saveAutomationRun, touchAutomationRunLease } from "./automation-run-repository.js";
|
|
3
|
+
export { appendAutomationRunEvent, deleteAutomation, deleteAutomationRunsForAutomation, getAutomation, getAutomationRun, listAutomationRunEvents, listAutomationRuns, listAutomationRunsForProductEvent, listAutomations, markAllAutomationRunsRead, markAutomationRunRead, saveAutomation, saveAutomationRun, saveAutomations, touchAutomationRunLease };
|
|
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
|
|
|
52
52
|
id: "database-schema",
|
|
53
53
|
label: "Database schema",
|
|
54
54
|
status: "pass",
|
|
55
|
-
message: `SQLite schema v${status.dbVersion} (current release
|
|
55
|
+
message: `SQLite schema v${status.dbVersion} (current release v122).`,
|
|
56
56
|
hints: []
|
|
57
57
|
};
|
|
58
58
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PrepareAutomationAgentSessionInput } from '../automations/index.js';
|
|
2
|
+
import type { ProjectService } from '../projects/index.js';
|
|
3
|
+
import type { SessionStore } from '../session/index.js';
|
|
4
|
+
export declare function prepareAutomationAgentSession(store: SessionStore, projects: ProjectService, input: PrepareAutomationAgentSessionInput): Promise<void>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//#region src/gateway/automation-agent-session.ts
|
|
2
|
+
async function prepareAutomationAgentSession(store, projects, input) {
|
|
3
|
+
await store.resolveTranscriptPath(input.sessionKey, { metadata: {
|
|
4
|
+
projectId: input.projectId,
|
|
5
|
+
sourceChannel: "automation",
|
|
6
|
+
sourceChatId: `default:dm:${input.peerId}`,
|
|
7
|
+
sessionType: "chat",
|
|
8
|
+
routing: {
|
|
9
|
+
agentId: input.agentId,
|
|
10
|
+
source: "automation",
|
|
11
|
+
accountId: "default",
|
|
12
|
+
peerKind: "dm",
|
|
13
|
+
peerId: input.peerId
|
|
14
|
+
}
|
|
15
|
+
} });
|
|
16
|
+
const current = await store.getMetadata(input.sessionKey);
|
|
17
|
+
await store.updateMetadata(input.sessionKey, {
|
|
18
|
+
sourceChannel: "automation",
|
|
19
|
+
sourceChatId: `default:dm:${input.peerId}`,
|
|
20
|
+
sessionType: "chat",
|
|
21
|
+
routing: {
|
|
22
|
+
agentId: input.agentId,
|
|
23
|
+
source: "automation",
|
|
24
|
+
accountId: "default",
|
|
25
|
+
peerKind: "dm",
|
|
26
|
+
peerId: input.peerId
|
|
27
|
+
},
|
|
28
|
+
tags: [...new Set([...current?.tags ?? [], "automation"])],
|
|
29
|
+
customData: {
|
|
30
|
+
...current?.customData ?? {},
|
|
31
|
+
origin: "automation",
|
|
32
|
+
automationId: input.automationId,
|
|
33
|
+
latestAutomationRunId: input.runId
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (input.projectId) projects.attachSession(input.sessionKey, input.projectId);
|
|
37
|
+
else if (current?.projectId) projects.detachSession(input.sessionKey);
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { prepareAutomationAgentSession };
|
|
@@ -41,7 +41,8 @@ async function reconcileDreamingAutomations(params) {
|
|
|
41
41
|
trigger,
|
|
42
42
|
action,
|
|
43
43
|
safety: { mode: "auto_apply" },
|
|
44
|
-
|
|
44
|
+
conversationMode: "continuous",
|
|
45
|
+
notificationPolicy: "none",
|
|
45
46
|
reliability: { disableAfterConsecutiveFailures: 3 }
|
|
46
47
|
};
|
|
47
48
|
if (!current) {
|
|
@@ -52,7 +53,7 @@ async function reconcileDreamingAutomations(params) {
|
|
|
52
53
|
result.created = true;
|
|
53
54
|
return result;
|
|
54
55
|
}
|
|
55
|
-
if (current.name !== next.name || current.description !== next.description || !current.enabled || JSON.stringify(current.trigger) !== JSON.stringify(trigger) || JSON.stringify(current.action) !== JSON.stringify(action) || current.safety?.mode !== "auto_apply" || current.
|
|
56
|
+
if (current.name !== next.name || current.description !== next.description || !current.enabled || JSON.stringify(current.trigger) !== JSON.stringify(trigger) || JSON.stringify(current.action) !== JSON.stringify(action) || current.safety?.mode !== "auto_apply" || current.conversationMode !== "continuous" || current.notificationPolicy !== "none" || current.reliability?.disableAfterConsecutiveFailures !== 3) {
|
|
56
57
|
await params.automationService.update(USER_CONTEXT_CONSOLIDATION_AUTOMATION_ID, next);
|
|
57
58
|
result.updated = true;
|
|
58
59
|
}
|
|
@@ -74,9 +74,43 @@ function registerCommandsSkillsRoutes(authenticated, deps) {
|
|
|
74
74
|
}, 400);
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
|
-
authenticated.get("/api/chat/skills", (c) => {
|
|
77
|
+
authenticated.get("/api/chat/skills", async (c) => {
|
|
78
|
+
const sessionKey = c.req.query("sessionKey")?.trim();
|
|
78
79
|
const agentId = c.req.query("agentId")?.trim() || service.getConfig().agents?.default || "main";
|
|
79
|
-
const payload = service.marketplace.getAgentSkillsApi(agentId);
|
|
80
|
+
const payload = sessionKey ? await service.marketplace.getSessionSkillsApi(sessionKey) : service.marketplace.getAgentSkillsApi(agentId);
|
|
81
|
+
return c.json({
|
|
82
|
+
ok: true,
|
|
83
|
+
payload
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
authenticated.get("/api/chat/workspace-trust", async (c) => {
|
|
87
|
+
const sessionKey = c.req.query("sessionKey")?.trim();
|
|
88
|
+
if (!sessionKey) return c.json({
|
|
89
|
+
ok: false,
|
|
90
|
+
error: "Missing sessionKey"
|
|
91
|
+
}, 400);
|
|
92
|
+
const payload = await service.marketplace.getSessionWorkspaceTrustApi(sessionKey);
|
|
93
|
+
return c.json({
|
|
94
|
+
ok: true,
|
|
95
|
+
payload
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
authenticated.patch("/api/chat/workspace-trust", async (c) => {
|
|
99
|
+
let body;
|
|
100
|
+
try {
|
|
101
|
+
body = await c.req.json();
|
|
102
|
+
} catch {
|
|
103
|
+
return c.json({
|
|
104
|
+
ok: false,
|
|
105
|
+
error: "Invalid JSON"
|
|
106
|
+
}, 400);
|
|
107
|
+
}
|
|
108
|
+
const sessionKey = typeof body.sessionKey === "string" ? body.sessionKey.trim() : "";
|
|
109
|
+
if (!sessionKey || typeof body.trusted !== "boolean") return c.json({
|
|
110
|
+
ok: false,
|
|
111
|
+
error: "Expected { sessionKey: string, trusted: boolean }"
|
|
112
|
+
}, 400);
|
|
113
|
+
const payload = await service.marketplace.setSessionWorkspaceTrustApi(sessionKey, body.trusted);
|
|
80
114
|
return c.json({
|
|
81
115
|
ok: true,
|
|
82
116
|
payload
|
|
@@ -2,7 +2,7 @@ import type { Config } from '../../config/schema.js';
|
|
|
2
2
|
import type { AgentService } from '../../agent/service.js';
|
|
3
3
|
import type { ChannelManager } from '../../channels/manager.js';
|
|
4
4
|
import type { ExtensionLoader } from '../../extensions/loader.js';
|
|
5
|
-
import type { AgentSkillAvailabilityEntry, AgentSkillAvailabilityPayload, SkillCatalogEntry, SkillCatalogRuntimeMeta } from '../../agent/agent-manager.js';
|
|
5
|
+
import type { AgentSkillAvailabilityEntry, AgentSkillAvailabilityPayload, SkillCatalogEntry, SkillCatalogRuntimeMeta, WorkspaceTrustState } from '../../agent/agent-manager.js';
|
|
6
6
|
import type { ManagedSkillListItem } from '../../agent/skills/managed-store.js';
|
|
7
7
|
import type { SkillMarkdownPreviewPayload } from '../../agent/skills/types.js';
|
|
8
8
|
import type { MarketplaceCategoryOption, SkillsStoreListParams, UnifiedMarketplaceListResponse, UnifiedMarketplacePackageDetail } from '../../agent/skills/skills-marketplace.js';
|
|
@@ -73,6 +73,9 @@ export declare class GatewayMarketplaceService {
|
|
|
73
73
|
} & SkillCatalogRuntimeMeta;
|
|
74
74
|
getSkillsStatusApi(): SkillCatalogRuntimeMeta;
|
|
75
75
|
getAgentSkillsApi(agentId: string): AgentSkillAvailabilityPayload;
|
|
76
|
+
getSessionSkillsApi(sessionKey: string): Promise<AgentSkillAvailabilityPayload>;
|
|
77
|
+
getSessionWorkspaceTrustApi(sessionKey: string): Promise<WorkspaceTrustState>;
|
|
78
|
+
setSessionWorkspaceTrustApi(sessionKey: string, trusted: boolean): Promise<WorkspaceTrustState>;
|
|
76
79
|
getSkillMarkdownSource(skillName: string): SkillMarkdownPreviewPayload | null;
|
|
77
80
|
deleteSkill(skillId: string, target?: SkillInstallTarget): void;
|
|
78
81
|
installSkillZip(buffer: Buffer, opts: {
|
|
@@ -68,6 +68,15 @@ var GatewayMarketplaceService = class {
|
|
|
68
68
|
getAgentSkillsApi(agentId) {
|
|
69
69
|
return this.opts.getAgentService().getAgentSkillAvailability(agentId);
|
|
70
70
|
}
|
|
71
|
+
getSessionSkillsApi(sessionKey) {
|
|
72
|
+
return this.opts.getAgentService().getSessionSkillAvailability(sessionKey);
|
|
73
|
+
}
|
|
74
|
+
getSessionWorkspaceTrustApi(sessionKey) {
|
|
75
|
+
return this.opts.getAgentService().getSessionWorkspaceTrust(sessionKey);
|
|
76
|
+
}
|
|
77
|
+
setSessionWorkspaceTrustApi(sessionKey, trusted) {
|
|
78
|
+
return this.opts.getAgentService().setSessionWorkspaceTrust(sessionKey, trusted);
|
|
79
|
+
}
|
|
71
80
|
getSkillMarkdownSource(skillName) {
|
|
72
81
|
return this.opts.getAgentService().getSkillMarkdownSource(skillName);
|
|
73
82
|
}
|
|
@@ -69,6 +69,7 @@ import "../discussions/index.js";
|
|
|
69
69
|
import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
|
|
70
70
|
import "../endpoint-tools/index.js";
|
|
71
71
|
import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
|
|
72
|
+
import { prepareAutomationAgentSession } from "./automation-agent-session.js";
|
|
72
73
|
import { reconcileDreamingAutomations } from "./dreaming-automation-reconciler.js";
|
|
73
74
|
import { NotesStore } from "../notes/store.js";
|
|
74
75
|
import { buildNoteAgentContext } from "../notes/agent-context.js";
|
|
@@ -495,7 +496,7 @@ var GatewayService = class {
|
|
|
495
496
|
this.automationService.setDeps({
|
|
496
497
|
agentService: this._agentService,
|
|
497
498
|
getDefaultAgentId: () => getDefaultAgentId(this.config),
|
|
498
|
-
|
|
499
|
+
prepareAgentSession: (input) => prepareAutomationAgentSession(this.sessionIndex.getStore(), this.projects, input),
|
|
499
500
|
workflowRunService: this.createWorkflowRunService(),
|
|
500
501
|
browserRecipeService: this.browserRecipes,
|
|
501
502
|
executeTaskCommand: ({ taskId, idempotencyKey, command }) => {
|
|
@@ -865,6 +866,7 @@ var GatewayService = class {
|
|
|
865
866
|
this.automationService.setDeps({
|
|
866
867
|
agentService: this.agentService,
|
|
867
868
|
getDefaultAgentId: () => getDefaultAgentId(this.config),
|
|
869
|
+
prepareAgentSession: (input) => prepareAutomationAgentSession(this.sessionIndex.getStore(), this.projects, input),
|
|
868
870
|
workflowRunService: this.createWorkflowRunService(),
|
|
869
871
|
browserRecipeService: this.browserRecipes,
|
|
870
872
|
executeTaskCommand: ({ taskId, idempotencyKey, command }) => {
|
|
@@ -1502,7 +1504,22 @@ var GatewayService = class {
|
|
|
1502
1504
|
this.createMobileNotificationService().handleGatewayEvent(type, payload);
|
|
1503
1505
|
}
|
|
1504
1506
|
handleAutomationRunCompleted(run) {
|
|
1505
|
-
this.
|
|
1507
|
+
this.automationService.get(run.automationId).then((automation) => {
|
|
1508
|
+
if (!automation) return;
|
|
1509
|
+
const requiresAttention = run.status !== "succeeded" || (automation.safety?.mode ?? "auto_apply") !== "auto_apply";
|
|
1510
|
+
this.emit("automation.run.completed", {
|
|
1511
|
+
run,
|
|
1512
|
+
notificationPolicy: automation.notificationPolicy,
|
|
1513
|
+
requiresAttention,
|
|
1514
|
+
projectId: automation.projectId
|
|
1515
|
+
});
|
|
1516
|
+
}).catch((err) => {
|
|
1517
|
+
log.warn({
|
|
1518
|
+
err,
|
|
1519
|
+
automationId: run.automationId,
|
|
1520
|
+
runId: run.id
|
|
1521
|
+
}, "Automation completion event failed");
|
|
1522
|
+
});
|
|
1506
1523
|
}
|
|
1507
1524
|
startAutomationProductEventBridge() {
|
|
1508
1525
|
this.stopAutomationProductEventBridge?.();
|
|
@@ -40,10 +40,13 @@ function taskEvent(payload) {
|
|
|
40
40
|
}
|
|
41
41
|
function automationEvent(payload) {
|
|
42
42
|
if (!payload || typeof payload !== "object") return null;
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
const event = payload;
|
|
44
|
+
if (event.notificationPolicy === "none") return null;
|
|
45
|
+
if (event.notificationPolicy === "attention" && event.requiresAttention !== true) return null;
|
|
46
|
+
const run = event.run;
|
|
45
47
|
if (!run || run.status !== "failed" && run.status !== "timeout" && run.status !== "succeeded") return null;
|
|
46
48
|
const type = run.status === "succeeded" ? "automation.completed" : "automation.failed";
|
|
49
|
+
const route = `/automations?automation=${encodeURIComponent(run.automationId)}&run=${encodeURIComponent(run.id)}`;
|
|
47
50
|
return {
|
|
48
51
|
type,
|
|
49
52
|
entity: {
|
|
@@ -53,9 +56,9 @@ function automationEvent(payload) {
|
|
|
53
56
|
priority: type === "automation.failed" ? "high" : "normal",
|
|
54
57
|
title: type === "automation.failed" ? "Automation failed" : "Automation completed",
|
|
55
58
|
body: run.automationName.slice(0, 120),
|
|
56
|
-
deepLink:
|
|
59
|
+
deepLink: route,
|
|
57
60
|
payload: {
|
|
58
|
-
route
|
|
61
|
+
route,
|
|
59
62
|
automationId: run.automationId,
|
|
60
63
|
runId: run.id,
|
|
61
64
|
eventType: type
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
ALTER TABLE automations ADD COLUMN conversation_mode TEXT NOT NULL DEFAULT 'new_session'
|
|
2
|
+
CHECK (conversation_mode IN ('new_session', 'continuous'));
|
|
3
|
+
ALTER TABLE automations ADD COLUMN notification_policy TEXT NOT NULL DEFAULT 'attention'
|
|
4
|
+
CHECK (notification_policy IN ('attention', 'all', 'none'));
|
|
5
|
+
ALTER TABLE automations ADD COLUMN completion_webhook_url TEXT;
|
|
6
|
+
|
|
7
|
+
UPDATE automations
|
|
8
|
+
SET completion_webhook_url = json_extract(after_run_json, '$.url')
|
|
9
|
+
WHERE json_extract(after_run_json, '$.kind') = 'webhook';
|
|
10
|
+
|
|
11
|
+
ALTER TABLE automations DROP COLUMN after_run_json;
|
|
12
|
+
|
|
13
|
+
UPDATE automation_runs
|
|
14
|
+
SET current_phase = 'completion_hook'
|
|
15
|
+
WHERE current_phase = 'after_run';
|
|
16
|
+
|
|
17
|
+
UPDATE automation_run_events
|
|
18
|
+
SET type = replace(type, 'after_run.', 'completion_hook.'),
|
|
19
|
+
message = replace(message, 'After-run webhook', 'Completion webhook')
|
|
20
|
+
WHERE type LIKE 'after_run.%';
|
|
21
|
+
|
|
22
|
+
ALTER TABLE automation_runs ADD COLUMN read_at_ms INTEGER;
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_automation_runs_unread_created
|
|
24
|
+
ON automation_runs(read_at_ms, created_at_ms DESC);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
UPDATE sessions
|
|
2
|
+
SET project_id = (
|
|
3
|
+
SELECT a.project_id
|
|
4
|
+
FROM automation_runs r
|
|
5
|
+
JOIN automations a ON a.automation_id = r.automation_id
|
|
6
|
+
WHERE r.session_key = sessions.session_key
|
|
7
|
+
AND a.project_id IS NOT NULL
|
|
8
|
+
ORDER BY r.created_at_ms DESC
|
|
9
|
+
LIMIT 1
|
|
10
|
+
)
|
|
11
|
+
WHERE project_id IS NULL
|
|
12
|
+
AND EXISTS (
|
|
13
|
+
SELECT 1
|
|
14
|
+
FROM automation_runs r
|
|
15
|
+
JOIN automations a ON a.automation_id = r.automation_id
|
|
16
|
+
WHERE r.session_key = sessions.session_key
|
|
17
|
+
AND a.project_id IS NOT NULL
|
|
18
|
+
);
|
|
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
|
|
|
3
3
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
4
4
|
export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
5
5
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
6
|
-
export declare const XOPC_DB_SCHEMA_VERSION =
|
|
6
|
+
export declare const XOPC_DB_SCHEMA_VERSION = 122;
|
|
7
7
|
export declare function resolveMigrationsDir(override?: string): string;
|
|
8
8
|
/**
|
|
9
9
|
* Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
|
|
@@ -12,7 +12,7 @@ const log = createLogger("Sqlite:Migrations");
|
|
|
12
12
|
/** Baseline schema version applied from schema.sql on first open. */
|
|
13
13
|
const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
14
14
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
15
|
-
const XOPC_DB_SCHEMA_VERSION =
|
|
15
|
+
const XOPC_DB_SCHEMA_VERSION = 122;
|
|
16
16
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
17
17
|
function backupBeforeTaskCutover(db, databasePath) {
|
|
18
18
|
db.exec("PRAGMA wal_checkpoint(FULL)");
|
|
@@ -57,7 +57,7 @@ function applySingleMigration(db, migration) {
|
|
|
57
57
|
* Each step runs in its own transaction and updates schema_meta on success.
|
|
58
58
|
*/
|
|
59
59
|
function applyPendingMigrations(db, options = {}) {
|
|
60
|
-
const targetVersion = options.targetVersion ??
|
|
60
|
+
const targetVersion = options.targetVersion ?? 122;
|
|
61
61
|
let currentVersion = readSchemaVersion(db);
|
|
62
62
|
if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
|
|
63
63
|
if (currentVersion >= targetVersion) return currentVersion;
|
|
@@ -94,7 +94,7 @@ function applyPendingMigrations(db, options = {}) {
|
|
|
94
94
|
}
|
|
95
95
|
/** Inspect schema version without mutating the database. */
|
|
96
96
|
function inspectSchemaMigrationStatus(db, options = {}) {
|
|
97
|
-
const appVersion = options.targetVersion ??
|
|
97
|
+
const appVersion = options.targetVersion ?? 122;
|
|
98
98
|
const dbVersion = readSchemaVersion(db);
|
|
99
99
|
if (dbVersion > appVersion) return {
|
|
100
100
|
dbVersion,
|
|
@@ -19,7 +19,7 @@ const log = createLogger('Sqlite:Migrations');
|
|
|
19
19
|
export const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
|
|
20
20
|
|
|
21
21
|
/** Latest schema version this release supports (increment when adding migrations). */
|
|
22
|
-
export const XOPC_DB_SCHEMA_VERSION =
|
|
22
|
+
export const XOPC_DB_SCHEMA_VERSION = 122;
|
|
23
23
|
|
|
24
24
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.206",
|
|
4
4
|
"description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -150,6 +150,7 @@
|
|
|
150
150
|
"eslint": "^10.4.0",
|
|
151
151
|
"jsdom": "^29.1.1",
|
|
152
152
|
"onnxruntime-common": "1.21.0",
|
|
153
|
+
"node-pty": "1.1.0",
|
|
153
154
|
"playwright-core": "^1.60.0",
|
|
154
155
|
"sherpa-onnx-node": "1.13.4",
|
|
155
156
|
"svgo": "4.0.2",
|
|
@@ -162,9 +163,9 @@
|
|
|
162
163
|
"vitepress": "^1.6.4",
|
|
163
164
|
"vitest": "4.1.5",
|
|
164
165
|
"vue": "^3.5.35",
|
|
165
|
-
"@xopcai/gateway-contract": "0.0.0",
|
|
166
166
|
"@xopcai/endpoint-tools-protocol": "0.0.0",
|
|
167
167
|
"@xopcai/realtime-protocol": "0.0.0",
|
|
168
|
+
"@xopcai/gateway-contract": "0.0.0",
|
|
168
169
|
"@xopcai/realtime-client": "0.0.0"
|
|
169
170
|
},
|
|
170
171
|
"scripts": {
|