@capybara-hq/kernel 0.1.0-rc.21 → 0.1.0-rc.23
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/admin/admin.controller.d.ts +3 -3
- package/dist/admin/admin.controller.js +6 -2
- package/dist/admin/admin.schemas.d.ts +13 -0
- package/dist/agents/admin-agents.d.ts +16 -3
- package/dist/agents/admin-agents.js +65 -7
- package/dist/agents/agents.schemas.d.ts +24 -6
- package/dist/agents/agents.service.d.ts +4 -3
- package/dist/agents/agents.service.js +39 -26
- package/dist/agents/definition.d.ts +44 -6
- package/dist/agents/definition.js +86 -18
- package/dist/agents/from-template.d.ts +6 -3
- package/dist/agents/from-template.js +57 -44
- package/dist/agents/org-templates.js +97 -41
- package/dist/agents/templates.d.ts +6 -0
- package/dist/agents/templates.js +15 -1
- package/dist/background/launch.d.ts +43 -5
- package/dist/background/launch.js +88 -8
- package/dist/background/session.d.ts +14 -2
- package/dist/background/session.js +26 -4
- package/dist/background/status.d.ts +1 -1
- package/dist/background/status.js +3 -3
- package/dist/background/stop.d.ts +0 -2
- package/dist/background/stop.js +1 -21
- package/dist/catalog/admin-catalog.controller.d.ts +2 -4
- package/dist/catalog/admin-catalog.controller.js +2 -6
- package/dist/catalog/catalog-content.d.ts +5 -0
- package/dist/catalog/catalog-content.js +1 -0
- package/dist/catalog/catalog.module.js +3 -0
- package/dist/catalog/claude/report.d.ts +9 -2
- package/dist/catalog/claude/report.js +1 -0
- package/dist/catalog/claude/translate.js +1 -1
- package/dist/catalog/component-promotion.js +1 -2
- package/dist/catalog/component-state.d.ts +13 -1
- package/dist/catalog/component-state.js +14 -5
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/marketplaces.service.js +2 -1
- package/dist/catalog/org-catalog.controller.d.ts +13 -3
- package/dist/catalog/org-catalog.controller.js +26 -4
- package/dist/catalog/org-catalog.schemas.d.ts +13 -0
- package/dist/catalog/org-catalog.schemas.js +34 -0
- package/dist/catalog/org-plugin-uploads.controller.js +0 -1
- package/dist/catalog/org-plugin-uploads.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.js +0 -3
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.schemas.js +0 -2
- package/dist/catalog/platform-components.d.ts +0 -1
- package/dist/catalog/platform-components.js +3 -8
- package/dist/catalog/plugin-import.d.ts +0 -8
- package/dist/catalog/plugin-import.js +4 -35
- package/dist/catalog/plugin-install.d.ts +2 -2
- package/dist/catalog/plugin-install.js +2 -2
- package/dist/catalog/plugin-package.d.ts +7 -0
- package/dist/catalog/plugin-package.js +27 -1
- package/dist/catalog/plugin-upgrade.d.ts +5 -6
- package/dist/catalog/plugin-upgrade.js +5 -23
- package/dist/catalog/requests.service.d.ts +66 -10
- package/dist/catalog/requests.service.js +196 -15
- package/dist/channels/actions.d.ts +2 -0
- package/dist/channels/actions.js +19 -4
- package/dist/channels/cards.d.ts +16 -2
- package/dist/channels/cards.js +40 -7
- package/dist/channels/channels.module.js +3 -0
- package/dist/channels/outbound.d.ts +22 -1
- package/dist/channels/outbound.js +116 -7
- package/dist/channels/phrases.d.ts +25 -0
- package/dist/channels/phrases.js +19 -0
- package/dist/channels/threads.d.ts +12 -0
- package/dist/channels/threads.js +34 -0
- package/dist/config/schema.d.ts +23 -1
- package/dist/config/schema.js +107 -5
- package/dist/conversations/conversations.service.d.ts +42 -9
- package/dist/conversations/conversations.service.js +57 -25
- package/dist/conversations/events.d.ts +106 -11
- package/dist/conversations/events.js +121 -18
- package/dist/conversations/message-context.d.ts +6 -3
- package/dist/conversations/message-context.js +14 -10
- package/dist/conversations/queue.d.ts +15 -2
- package/dist/conversations/queue.js +22 -3
- package/dist/conversations/queue.service.d.ts +12 -6
- package/dist/conversations/queue.service.js +36 -13
- package/dist/db/kernel-schema.d.ts +105 -3
- package/dist/devices/conversation-devices.d.ts +8 -1
- package/dist/devices/conversation-devices.js +8 -0
- package/dist/devices/devices.controller.d.ts +21 -4
- package/dist/devices/devices.controller.js +46 -8
- package/dist/devices/devices.schemas.d.ts +9 -1
- package/dist/devices/devices.schemas.js +11 -3
- package/dist/devices/devices.service.d.ts +176 -4
- package/dist/devices/devices.service.js +347 -6
- package/dist/devices/dto.d.ts +56 -3
- package/dist/devices/dto.js +51 -1
- package/dist/devices/public-suffix.d.ts +6 -0
- package/dist/devices/public-suffix.js +79 -0
- package/dist/errors.d.ts +50 -5
- package/dist/errors.js +50 -5
- package/dist/evals/reconstruct.d.ts +18 -13
- package/dist/evals/reconstruct.js +50 -36
- package/dist/evals/recorded-tools.d.ts +7 -7
- package/dist/evals/recorded-tools.js +4 -3
- package/dist/evals/trajectory.d.ts +6 -1
- package/dist/evals/trajectory.js +7 -0
- package/dist/extensions/package.js +2 -2
- package/dist/http/api.module.js +5 -0
- package/dist/identity/settings.d.ts +53 -3
- package/dist/identity/settings.js +92 -9
- package/dist/inbox/inbox.module.js +2 -1
- package/dist/inbox/inbox.service.d.ts +19 -4
- package/dist/inbox/inbox.service.js +14 -3
- package/dist/infra/config/kernel-config.service.d.ts +7 -0
- package/dist/infra/config/kernel-config.service.js +31 -0
- package/dist/infra/events/kernel-events.d.ts +2 -1
- package/dist/local-devices/device-policy.service.d.ts +65 -0
- package/dist/local-devices/device-policy.service.js +217 -0
- package/dist/local-devices/local-device-gateway.d.ts +4 -2
- package/dist/local-devices/local-device-gateway.js +39 -11
- package/dist/local-devices/local-device-provider.d.ts +40 -3
- package/dist/local-devices/local-device-provider.js +109 -7
- package/dist/local-devices/local-devices.module.d.ts +2 -1
- package/dist/local-devices/local-devices.module.js +19 -3
- package/dist/local-devices/machines.d.ts +30 -3
- package/dist/local-devices/machines.js +79 -3
- package/dist/local-devices/network-grants.d.ts +104 -0
- package/dist/local-devices/network-grants.js +288 -0
- package/dist/local-devices/policy-summary.d.ts +20 -0
- package/dist/local-devices/policy-summary.js +63 -0
- package/dist/orgs/orgs.module.js +4 -10
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +4 -0
- package/dist/orgs/settings.controller.js +4 -3
- package/dist/orgs/settings.service.d.ts +172 -14
- package/dist/orgs/settings.service.js +229 -27
- package/dist/platform/exclusions.js +11 -1
- package/dist/platform/operation.js +4 -0
- package/dist/platform/ops/admin-items.ops.js +1 -1
- package/dist/platform/ops/admin.ops.js +32 -7
- package/dist/platform/ops/agent-skills.ops.js +2 -2
- package/dist/platform/ops/agent-templates.ops.js +2 -2
- package/dist/platform/ops/agents.ops.js +11 -15
- package/dist/platform/ops/devices.ops.js +3 -1
- package/dist/platform/ops/inbox.ops.js +19 -0
- package/dist/platform/ops/org-settings.ops.js +15 -6
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/platform.ops.d.ts +9 -1
- package/dist/platform/ops/platform.ops.js +34 -12
- package/dist/platform/ops/requests.ops.js +3 -2
- package/dist/platform/ops/schedules.ops.d.ts +21 -0
- package/dist/platform/ops/schedules.ops.js +470 -0
- package/dist/platform/ops/skills.ops.js +3 -3
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +5 -0
- package/dist/platform/route-schemas.js +3 -0
- package/dist/roles/worker.module.js +3 -0
- package/dist/runtime/context/build.js +13 -4
- package/dist/runtime/context/compaction.js +6 -3
- package/dist/runtime/context/device-paths.d.ts +43 -21
- package/dist/runtime/context/device-paths.js +104 -21
- package/dist/runtime/context/run-context.d.ts +9 -0
- package/dist/runtime/context/run-context.js +8 -0
- package/dist/runtime/context/skills.d.ts +14 -1
- package/dist/runtime/context/skills.js +36 -5
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +16 -5
- package/dist/runtime/run-finish.d.ts +6 -1
- package/dist/runtime/run-finish.js +16 -2
- package/dist/runtime/run-queue.js +21 -2
- package/dist/runtime/run-worker.js +14 -33
- package/dist/runtime/runtime.module.js +3 -0
- package/dist/runtime/subagents/definition.d.ts +32 -14
- package/dist/runtime/subagents/definition.js +106 -109
- package/dist/runtime/subagents/dispatch.js +4 -3
- package/dist/runtime/subagents/preamble.d.ts +2 -1
- package/dist/runtime/subagents/preamble.js +2 -1
- package/dist/runtime/waits.js +14 -4
- package/dist/sandbox/platform-tiers.d.ts +86 -0
- package/dist/sandbox/platform-tiers.js +97 -0
- package/dist/sandbox/sandbox.service.d.ts +121 -11
- package/dist/sandbox/sandbox.service.js +351 -30
- package/dist/sandbox/tiers.d.ts +98 -0
- package/dist/sandbox/tiers.js +104 -0
- package/dist/schedules/effective-settings.d.ts +16 -0
- package/dist/schedules/effective-settings.js +17 -0
- package/dist/schedules/errors.d.ts +8 -0
- package/dist/schedules/errors.js +8 -0
- package/dist/schedules/fire.d.ts +118 -0
- package/dist/schedules/fire.js +625 -0
- package/dist/schedules/grant-rules.d.ts +94 -0
- package/dist/schedules/grant-rules.js +126 -0
- package/dist/schedules/job-ids.d.ts +32 -0
- package/dist/schedules/job-ids.js +27 -0
- package/dist/schedules/pause.d.ts +9 -0
- package/dist/schedules/pause.js +33 -0
- package/dist/schedules/run-tracker.d.ts +81 -0
- package/dist/schedules/run-tracker.js +333 -0
- package/dist/schedules/scan.job.d.ts +64 -0
- package/dist/schedules/scan.job.js +303 -0
- package/dist/schedules/schedule-math.d.ts +31 -0
- package/dist/schedules/schedule-math.js +223 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +351 -0
- package/dist/schedules/scheduled-tasks.service.js +1193 -0
- package/dist/schedules/schedules.controller.d.ts +68 -0
- package/dist/schedules/schedules.controller.js +242 -0
- package/dist/schedules/schedules.module.d.ts +16 -0
- package/dist/schedules/schedules.module.js +65 -0
- package/dist/schedules/schedules.schemas.d.ts +316 -0
- package/dist/schedules/schedules.schemas.js +186 -0
- package/dist/schedules/store.d.ts +81 -0
- package/dist/schedules/store.js +390 -0
- package/dist/schedules/store.module.d.ts +6 -0
- package/dist/schedules/store.module.js +21 -0
- package/dist/schedules/types.d.ts +108 -0
- package/dist/schedules/types.js +1 -0
- package/dist/schedules/unattended.d.ts +117 -0
- package/dist/schedules/unattended.js +228 -0
- package/dist/setup/oauth-token-probe.js +8 -4
- package/dist/skills/agent-skills.service.d.ts +4 -8
- package/dist/skills/agent-skills.service.js +18 -53
- package/dist/skills/catalog.d.ts +65 -62
- package/dist/skills/catalog.js +109 -206
- package/dist/skills/conversation-catalog.d.ts +3 -3
- package/dist/skills/conversation-catalog.js +5 -12
- package/dist/skills/invoke.d.ts +2 -2
- package/dist/skills/skills.controller.d.ts +3 -1
- package/dist/skills/skills.service.d.ts +38 -37
- package/dist/skills/skills.service.js +168 -107
- package/dist/skills/usable.d.ts +57 -8
- package/dist/skills/usable.js +172 -38
- package/dist/tools/approvals.controller.d.ts +4 -2
- package/dist/tools/approvals.controller.js +17 -2
- package/dist/tools/approvals.schemas.d.ts +1 -0
- package/dist/tools/approvals.schemas.js +3 -1
- package/dist/tools/approvals.service.d.ts +182 -7
- package/dist/tools/approvals.service.js +597 -13
- package/dist/tools/builtin-names.d.ts +25 -4
- package/dist/tools/builtin-names.js +45 -4
- package/dist/tools/builtins/builtin-tools.d.ts +8 -0
- package/dist/tools/builtins/builtin-tools.js +23 -2
- package/dist/tools/builtins/sandbox/bash.js +16 -7
- package/dist/tools/builtins/sandbox/common.d.ts +1 -1
- package/dist/tools/builtins/sandbox/common.js +33 -10
- package/dist/tools/builtins/sandbox/edit.js +7 -3
- package/dist/tools/builtins/sandbox/file-state.d.ts +31 -1
- package/dist/tools/builtins/sandbox/file-state.js +33 -3
- package/dist/tools/builtins/sandbox/write.js +8 -4
- package/dist/tools/builtins/schedules.d.ts +107 -0
- package/dist/tools/builtins/schedules.js +789 -0
- package/dist/tools/elicitation.d.ts +2 -0
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/fixed-ask.d.ts +7 -0
- package/dist/tools/fixed-ask.js +9 -0
- package/dist/tools/network-asks.d.ts +109 -0
- package/dist/tools/network-asks.js +221 -0
- package/dist/tools/pipeline.d.ts +53 -6
- package/dist/tools/pipeline.js +202 -13
- package/dist/tools/policy.d.ts +21 -8
- package/dist/tools/policy.js +63 -9
- package/dist/tools/registry.d.ts +10 -1
- package/dist/tools/tools.module.js +12 -0
- package/package.json +2 -2
- package/src/migrations/0113_scheduled_tasks.sql +108 -0
- package/src/migrations/0114_network_asks.sql +23 -0
- package/src/migrations/0115_network_requests.sql +28 -0
- package/src/migrations/0116_skills_default_on.sql +37 -0
- package/src/migrations/0117_sandbox_tiers.sql +11 -0
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { Inject, Injectable, Module } from "@nestjs/common";
|
|
11
|
+
import { AgentLookup, AgentLookupModule } from "../agents/agent-lookup.js";
|
|
12
|
+
import { ChannelsModule } from "../channels/channels.module.js";
|
|
13
|
+
import { ChannelConnections } from "../channels/connections.service.js";
|
|
14
|
+
import { findOrBindThread, findThread } from "../channels/threads.js";
|
|
15
|
+
import { ConversationAccess, ConversationAccessModule } from "../conversations/access.js";
|
|
16
|
+
import { ConversationsModule } from "../conversations/conversations.module.js";
|
|
17
|
+
import { ConversationsService } from "../conversations/conversations.service.js";
|
|
18
|
+
import { ConversationQueue } from "../conversations/queue.service.js";
|
|
19
|
+
import { ApiError } from "../errors.js";
|
|
20
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
21
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
22
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
23
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
24
|
+
import { LockService } from "../infra/lock/lock.service.js";
|
|
25
|
+
import { QueueModule } from "../infra/queue/queue.module.js";
|
|
26
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
27
|
+
import { deviceLeaseKey } from "../local-devices/keys.js";
|
|
28
|
+
import { OrgLock, OrgLockModule } from "../orgs/org-lock.js";
|
|
29
|
+
import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
|
|
30
|
+
import { RunControl } from "../runtime/run-control.js";
|
|
31
|
+
import { RuntimeModule } from "../runtime/runtime.module.js";
|
|
32
|
+
import { readScheduleSettings } from "./effective-settings.js";
|
|
33
|
+
import { pauseTaskIn } from "./pause.js";
|
|
34
|
+
import { lockTaskRow, ScheduledTaskRunTracker, ScheduledTaskTrackerModule } from "./run-tracker.js";
|
|
35
|
+
import { ScheduledTaskScanJob } from "./scan.job.js";
|
|
36
|
+
import { ScheduledTaskStore } from "./store.js";
|
|
37
|
+
import { ScheduledTaskStoreModule } from "./store.module.js";
|
|
38
|
+
/** A task run's message client id in a conversation's queue (never read back as "the task's"). */
|
|
39
|
+
export const scheduledClientMessageId = (taskRunId) => `sched-${taskRunId}`;
|
|
40
|
+
const HOUR_MS = 3_600_000;
|
|
41
|
+
/** How many stale previous runs the overlap check releases before it gives up. */
|
|
42
|
+
const OVERLAP_SETTLE_MAX = 5;
|
|
43
|
+
/** The skips that last: the task pauses with the same reason (spec §6). */
|
|
44
|
+
const LASTING = new Set([
|
|
45
|
+
"org_disabled",
|
|
46
|
+
"creator_inactive",
|
|
47
|
+
"agent_gone",
|
|
48
|
+
"conversation_gone",
|
|
49
|
+
"target_gone",
|
|
50
|
+
]);
|
|
51
|
+
/** The tick in the task's zone as the run's header shows it: `2026-11-11 09:00 (Asia/Shanghai)`. */
|
|
52
|
+
export function localTimeOf(at, timeZone) {
|
|
53
|
+
const p = Object.fromEntries(new Intl.DateTimeFormat("en-US", {
|
|
54
|
+
timeZone,
|
|
55
|
+
hourCycle: "h23",
|
|
56
|
+
year: "numeric",
|
|
57
|
+
month: "2-digit",
|
|
58
|
+
day: "2-digit",
|
|
59
|
+
hour: "2-digit",
|
|
60
|
+
minute: "2-digit",
|
|
61
|
+
})
|
|
62
|
+
.formatToParts(at)
|
|
63
|
+
.map((x) => [x.type, x.value]));
|
|
64
|
+
return `${p.year}-${p.month}-${p.day} ${p.hour}:${p.minute} (${timeZone})`;
|
|
65
|
+
}
|
|
66
|
+
const DEVICE_GONE = new Set(["device.not_found", "device.unavailable", "sandbox.unavailable"]);
|
|
67
|
+
/**
|
|
68
|
+
* Checks and starts one task run (scheduled tasks spec §6), the body of the `sched-fire-<id>` job.
|
|
69
|
+
* Idempotent on the task run: only a `pending` one is fired. Two steps:
|
|
70
|
+
*
|
|
71
|
+
* 1. The claim, one transaction under the org row lock (which serializes the org's rate limit
|
|
72
|
+
* count), then the task run and the task rows: the checks in order (task paused since the
|
|
73
|
+
* scan, unless a person's "run now"; org disabled, creator
|
|
74
|
+
* inactive or not a member, agent gone or not visible, conversation gone, connection inactive,
|
|
75
|
+
* overlap, rate limit, device offline, queue paused), each a `skipped` run with its reason, the
|
|
76
|
+
* lasting ones also pausing the task; then `fired_at` is written, after the rate limit count.
|
|
77
|
+
* A run whose claim committed before (a retried job) goes straight to the start.
|
|
78
|
+
* 2. The start, idempotent: `new` creates the conversation with its first message keyed by the
|
|
79
|
+
* task run id (`create_request_id`); `conversation` queues the prompt in the target
|
|
80
|
+
* conversation's queue (never absorbed into a run in progress); `chat` finds the DM's live
|
|
81
|
+
* thread or creates and binds a conversation (one transaction), then queues the prompt there;
|
|
82
|
+
* a group chat gets a new conversation per run whose thread outbound binds at the run's first
|
|
83
|
+
* post (`openGroup`). A start that finds the target gone takes `fired_at` back and skips the run.
|
|
84
|
+
*
|
|
85
|
+
* Every message carries the schedule marker and the task's zone; the kernel run its message
|
|
86
|
+
* triggers takes the task run (`linkStartedRunIn`), and the run tracker follows it to its end.
|
|
87
|
+
*/
|
|
88
|
+
let ScheduledTaskFirer = class ScheduledTaskFirer {
|
|
89
|
+
kdb;
|
|
90
|
+
txHost;
|
|
91
|
+
config;
|
|
92
|
+
store;
|
|
93
|
+
tracker;
|
|
94
|
+
orgLock;
|
|
95
|
+
agents;
|
|
96
|
+
access;
|
|
97
|
+
conversations;
|
|
98
|
+
queue;
|
|
99
|
+
connections;
|
|
100
|
+
runs;
|
|
101
|
+
locks;
|
|
102
|
+
log;
|
|
103
|
+
constructor(kdb, txHost, config, store, tracker, orgLock, agents, access, conversations, queue, connections, runs,
|
|
104
|
+
/** Reads a local device's connection lease (online or not). */
|
|
105
|
+
locks, log) {
|
|
106
|
+
this.kdb = kdb;
|
|
107
|
+
this.txHost = txHost;
|
|
108
|
+
this.config = config;
|
|
109
|
+
this.store = store;
|
|
110
|
+
this.tracker = tracker;
|
|
111
|
+
this.orgLock = orgLock;
|
|
112
|
+
this.agents = agents;
|
|
113
|
+
this.access = access;
|
|
114
|
+
this.conversations = conversations;
|
|
115
|
+
this.queue = queue;
|
|
116
|
+
this.connections = connections;
|
|
117
|
+
this.runs = runs;
|
|
118
|
+
this.locks = locks;
|
|
119
|
+
this.log = log;
|
|
120
|
+
}
|
|
121
|
+
get db() {
|
|
122
|
+
return this.kdb.db;
|
|
123
|
+
}
|
|
124
|
+
/** Fires task run `taskRunId` (see the class); a run not `pending` is left as it is. */
|
|
125
|
+
async fire(taskRunId) {
|
|
126
|
+
const pre = await this.db
|
|
127
|
+
.selectFrom("scheduled_task_runs as r")
|
|
128
|
+
.innerJoin("scheduled_tasks as t", "t.id", "r.task_id")
|
|
129
|
+
.select(["r.status", "r.org_id", "r.fired_at", "t.device_id", "t.mode"])
|
|
130
|
+
.where("r.id", "=", taskRunId)
|
|
131
|
+
.executeTakeFirst();
|
|
132
|
+
if (pre?.status !== "pending")
|
|
133
|
+
return;
|
|
134
|
+
// a Redis read: outside the claim's transaction
|
|
135
|
+
const offline = pre.fired_at === null && pre.device_id !== null && pre.mode === "new"
|
|
136
|
+
? await this.deviceOffline(pre.device_id)
|
|
137
|
+
: false;
|
|
138
|
+
const claimed = await this.claim(taskRunId, pre.org_id, offline);
|
|
139
|
+
if (claimed === null || "skip" in claimed)
|
|
140
|
+
return;
|
|
141
|
+
await this.start(claimed.plan);
|
|
142
|
+
}
|
|
143
|
+
/** Step 1 (see the class): a skip, the plan, or null when there is nothing to fire. */
|
|
144
|
+
async claim(taskRunId, orgId, deviceOffline) {
|
|
145
|
+
const t = this.db;
|
|
146
|
+
// the org row first, as every task write does (ScheduledTasksService): no lock cycle
|
|
147
|
+
if ((await this.orgLock.tryLock(orgId)) === undefined)
|
|
148
|
+
return null;
|
|
149
|
+
const owner = await t
|
|
150
|
+
.selectFrom("scheduled_task_runs")
|
|
151
|
+
.select("task_id")
|
|
152
|
+
.where("id", "=", taskRunId)
|
|
153
|
+
.executeTakeFirst();
|
|
154
|
+
if (!owner)
|
|
155
|
+
return null;
|
|
156
|
+
// lock order org → task row → task runs, as the run tracker and the service take them
|
|
157
|
+
await lockTaskRow(t, owner.task_id);
|
|
158
|
+
const row = await t
|
|
159
|
+
.selectFrom("scheduled_task_runs")
|
|
160
|
+
.select("id")
|
|
161
|
+
.where("id", "=", taskRunId)
|
|
162
|
+
.forUpdate()
|
|
163
|
+
.executeTakeFirst();
|
|
164
|
+
const run = row ? await this.store.updateRun(t, taskRunId, {}) : null;
|
|
165
|
+
if (run?.status !== "pending")
|
|
166
|
+
return null;
|
|
167
|
+
const task = await this.store.getTask(t, orgId, run.taskId);
|
|
168
|
+
if (!task) {
|
|
169
|
+
await this.store.updateRun(t, run.id, {
|
|
170
|
+
status: "skipped",
|
|
171
|
+
skipReason: "task_deleted",
|
|
172
|
+
firedAt: null,
|
|
173
|
+
});
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
const resumed = run.firedAt !== null;
|
|
177
|
+
const skip = async (reason) => {
|
|
178
|
+
await this.skipIn(t, run.id, task.id, reason);
|
|
179
|
+
return { skip: reason };
|
|
180
|
+
};
|
|
181
|
+
// paused after the scan recorded the tick: only a person's "run now" still runs
|
|
182
|
+
if (!resumed && !run.manual && task.status === "paused")
|
|
183
|
+
return skip("task_paused");
|
|
184
|
+
const settings = await readScheduleSettings(t, this.config, orgId);
|
|
185
|
+
if (!resumed && !settings.enabled)
|
|
186
|
+
return skip("org_disabled");
|
|
187
|
+
if (!resumed && !(await this.creatorActive(orgId, task.accountId))) {
|
|
188
|
+
return skip("creator_inactive");
|
|
189
|
+
}
|
|
190
|
+
if (!resumed) {
|
|
191
|
+
try {
|
|
192
|
+
await this.agents.get(orgId, task.agentId, task.accountId);
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
if (e instanceof ApiError && e.code === "agent.not_found")
|
|
196
|
+
return skip("agent_gone");
|
|
197
|
+
throw e;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
let plan;
|
|
201
|
+
let queuePausedOn;
|
|
202
|
+
if (task.mode === "conversation") {
|
|
203
|
+
const conv = await this.targetConversation(task);
|
|
204
|
+
if (conv === undefined)
|
|
205
|
+
return skip("conversation_gone");
|
|
206
|
+
plan = { mode: "conversation", task, run, conversationId: conv.id };
|
|
207
|
+
if (conv.queuePaused)
|
|
208
|
+
queuePausedOn = conv.id;
|
|
209
|
+
}
|
|
210
|
+
else if (task.mode === "chat") {
|
|
211
|
+
const chat = task.chat;
|
|
212
|
+
const conn = chat === null ? undefined : await this.connections.row(chat.connectionId);
|
|
213
|
+
if (chat === null ||
|
|
214
|
+
!conn ||
|
|
215
|
+
conn.orgId !== orgId ||
|
|
216
|
+
conn.status !== "active" ||
|
|
217
|
+
!conn.pluginEnabled ||
|
|
218
|
+
conn.agentId !== task.agentId) {
|
|
219
|
+
return skip("target_gone");
|
|
220
|
+
}
|
|
221
|
+
if (chat.chatType === "group") {
|
|
222
|
+
// a group has no current conversation: each run starts its own thread at its first post
|
|
223
|
+
// (spec §8), which needs a channel with threads; the creator must have written there
|
|
224
|
+
if (!this.connections.channel(conn.plugin).features.threads) {
|
|
225
|
+
return skip("unsupported_target");
|
|
226
|
+
}
|
|
227
|
+
if (!(await this.inGroup(chat.connectionId, chat.chatId, task.accountId))) {
|
|
228
|
+
return skip("target_gone");
|
|
229
|
+
}
|
|
230
|
+
plan = { mode: "group", task, run, connectionId: chat.connectionId, chatId: chat.chatId };
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const threadKey = await this.dmThreadKey(conn, chat.chatId, task.accountId);
|
|
234
|
+
if (threadKey === undefined)
|
|
235
|
+
return skip("target_gone");
|
|
236
|
+
const thread = {
|
|
237
|
+
connectionId: chat.connectionId,
|
|
238
|
+
chatId: chat.chatId,
|
|
239
|
+
threadKey,
|
|
240
|
+
accountId: task.accountId,
|
|
241
|
+
};
|
|
242
|
+
plan = { mode: "chat", task, run, thread, target: { chatId: chat.chatId, chatType: "dm" } };
|
|
243
|
+
const live = await findThread(t, thread);
|
|
244
|
+
if (live !== undefined && (await this.queuePaused(live)))
|
|
245
|
+
queuePausedOn = live;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
plan = { mode: "new", task, run };
|
|
250
|
+
}
|
|
251
|
+
if (resumed)
|
|
252
|
+
return { plan };
|
|
253
|
+
if (await this.overlaps(task.id, run.id))
|
|
254
|
+
return skip("overlap");
|
|
255
|
+
const fired = await this.store.countFiredSince(t, orgId, new Date(Date.now() - HOUR_MS));
|
|
256
|
+
if (fired >= settings.maxRunsPerHour)
|
|
257
|
+
return skip("rate_limited");
|
|
258
|
+
if (deviceOffline)
|
|
259
|
+
return skip("device_offline");
|
|
260
|
+
if (queuePausedOn !== undefined)
|
|
261
|
+
return skip("queue_paused");
|
|
262
|
+
const claimed = await this.store.updateRun(t, run.id, {
|
|
263
|
+
firedAt: new Date(),
|
|
264
|
+
...(plan.mode === "conversation" && { conversationId: plan.conversationId }),
|
|
265
|
+
});
|
|
266
|
+
return { plan: { ...plan, run: claimed ?? run } };
|
|
267
|
+
}
|
|
268
|
+
/** Step 2 (see the class). */
|
|
269
|
+
async start(plan) {
|
|
270
|
+
const { task, run } = plan;
|
|
271
|
+
const marker = {
|
|
272
|
+
taskId: task.id,
|
|
273
|
+
taskRunId: run.id,
|
|
274
|
+
scheduledFor: run.scheduledFor.toISOString(),
|
|
275
|
+
trial: run.trial,
|
|
276
|
+
taskName: task.name,
|
|
277
|
+
localTime: localTimeOf(run.scheduledFor, task.trigger.timeZone),
|
|
278
|
+
};
|
|
279
|
+
const internal = { schedule: marker, timeZoneOverride: task.trigger.timeZone };
|
|
280
|
+
try {
|
|
281
|
+
if (plan.mode === "new") {
|
|
282
|
+
// model and effort are a new-conversation task's only (spec §4): a conversation or chat
|
|
283
|
+
// task runs with that conversation's selection, never switching it for a person
|
|
284
|
+
const pick = {
|
|
285
|
+
...(task.model !== null && { model: task.model }),
|
|
286
|
+
...(task.effort !== null && { effort: task.effort }),
|
|
287
|
+
};
|
|
288
|
+
const out = await this.conversations.createWithMessage(task.orgId, task.accountId, task.agentId, { text: task.prompt, clientMessageId: run.id, ...pick }, task.deviceId === null ? {} : { deviceId: task.deviceId }, internal);
|
|
289
|
+
await this.setConversation(run.id, out.conversation.id);
|
|
290
|
+
// a retried start found the conversation made before: its run may be still to start
|
|
291
|
+
if (!out.created)
|
|
292
|
+
await this.runs.ensureRun(out.conversation.id);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
let conversationId;
|
|
296
|
+
if (plan.mode === "chat" || plan.mode === "group") {
|
|
297
|
+
const bound = plan.mode === "chat" ? await this.bindChat(plan) : await this.openGroup(plan);
|
|
298
|
+
if (bound === null)
|
|
299
|
+
return;
|
|
300
|
+
conversationId = bound;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
conversationId = plan.conversationId;
|
|
304
|
+
}
|
|
305
|
+
await this.queue.add(task.orgId, conversationId, task.accountId, { text: task.prompt, clientMessageId: scheduledClientMessageId(run.id) }, internal);
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
if (!(e instanceof ApiError))
|
|
309
|
+
throw e;
|
|
310
|
+
const reason = e.code === "agent.not_found"
|
|
311
|
+
? "agent_gone"
|
|
312
|
+
: e.code === "conversation.not_found"
|
|
313
|
+
? plan.mode === "chat" || plan.mode === "group"
|
|
314
|
+
? "target_gone"
|
|
315
|
+
: "conversation_gone"
|
|
316
|
+
: DEVICE_GONE.has(e.code)
|
|
317
|
+
? "device_offline"
|
|
318
|
+
: undefined;
|
|
319
|
+
if (reason !== undefined) {
|
|
320
|
+
await this.unstart(run.id, task.id, reason);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
this.log.warn("scheduled task run could not start", {
|
|
324
|
+
taskId: task.id,
|
|
325
|
+
taskRunId: run.id,
|
|
326
|
+
code: e.code,
|
|
327
|
+
});
|
|
328
|
+
await this.failStart(run.id, task.id, e.message);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The DM's live conversation, or a new one bound to it (`findOrBindThread`), in one transaction:
|
|
333
|
+
* a conversation it creates is the task's (`conversations.scheduled_task_id`). Null when the
|
|
334
|
+
* live conversation's queue is paused (the run is skipped, `queue_paused`).
|
|
335
|
+
*/
|
|
336
|
+
async bindChat(plan) {
|
|
337
|
+
const { task, run } = plan;
|
|
338
|
+
const t = this.db;
|
|
339
|
+
// the one lock order: task row, then the task run
|
|
340
|
+
await lockTaskRow(t, task.id);
|
|
341
|
+
const locked = await t
|
|
342
|
+
.selectFrom("scheduled_task_runs")
|
|
343
|
+
.select("status")
|
|
344
|
+
.where("id", "=", run.id)
|
|
345
|
+
.forUpdate()
|
|
346
|
+
.executeTakeFirst();
|
|
347
|
+
if (locked?.status !== "pending")
|
|
348
|
+
return null;
|
|
349
|
+
const { conversationId, created } = await findOrBindThread(t, plan.thread, plan.target, async () => {
|
|
350
|
+
const conv = await this.conversations.create(task.orgId, task.accountId, task.agentId,
|
|
351
|
+
// a chat task takes no device (new mode only): an IM conversation's default
|
|
352
|
+
{ im: true });
|
|
353
|
+
await t
|
|
354
|
+
.updateTable("conversations")
|
|
355
|
+
.set({ scheduled_task_id: task.id })
|
|
356
|
+
.where("id", "=", conv.id)
|
|
357
|
+
.execute();
|
|
358
|
+
return conv.id;
|
|
359
|
+
});
|
|
360
|
+
if (!created && (await this.queuePaused(conversationId))) {
|
|
361
|
+
await this.skipIn(t, run.id, task.id, "queue_paused");
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
await this.store.updateRun(t, run.id, { conversationId });
|
|
365
|
+
return conversationId;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* A group run's conversation (spec §8): a new one per run, the task's
|
|
369
|
+
* (`conversations.scheduled_task_id`), whose delivery goes to the group with its thread still to
|
|
370
|
+
* bind (`channel_deliveries.pending_thread_account_id` = the creator): outbound binds it at the
|
|
371
|
+
* run's first post, thread key = that message's id, so replies in that thread continue the
|
|
372
|
+
* conversation. One transaction; a retried start reuses the conversation it made before.
|
|
373
|
+
*/
|
|
374
|
+
async openGroup(plan) {
|
|
375
|
+
const { task, run } = plan;
|
|
376
|
+
const t = this.db;
|
|
377
|
+
// the one lock order: task row, then the task run
|
|
378
|
+
await lockTaskRow(t, task.id);
|
|
379
|
+
const locked = await t
|
|
380
|
+
.selectFrom("scheduled_task_runs")
|
|
381
|
+
.select(["status", "conversation_id"])
|
|
382
|
+
.where("id", "=", run.id)
|
|
383
|
+
.forUpdate()
|
|
384
|
+
.executeTakeFirst();
|
|
385
|
+
if (locked?.status !== "pending")
|
|
386
|
+
return null;
|
|
387
|
+
if (locked.conversation_id !== null)
|
|
388
|
+
return locked.conversation_id;
|
|
389
|
+
const conv = await this.conversations.create(task.orgId, task.accountId, task.agentId,
|
|
390
|
+
// a chat task takes no device (new mode only): an IM conversation's default
|
|
391
|
+
{ im: true });
|
|
392
|
+
await t
|
|
393
|
+
.updateTable("conversations")
|
|
394
|
+
.set({ scheduled_task_id: task.id })
|
|
395
|
+
.where("id", "=", conv.id)
|
|
396
|
+
.execute();
|
|
397
|
+
const target = { chatId: plan.chatId, chatType: "group" };
|
|
398
|
+
await t
|
|
399
|
+
.insertInto("channel_deliveries")
|
|
400
|
+
.values({
|
|
401
|
+
conversation_id: conv.id,
|
|
402
|
+
connection_id: plan.connectionId,
|
|
403
|
+
target: JSON.stringify(target),
|
|
404
|
+
last_seq: 0,
|
|
405
|
+
pending_thread_account_id: task.accountId,
|
|
406
|
+
})
|
|
407
|
+
.execute();
|
|
408
|
+
await this.store.updateRun(t, run.id, { conversationId: conv.id });
|
|
409
|
+
return conv.id;
|
|
410
|
+
}
|
|
411
|
+
/** The start found the target gone: `fired_at` back to null, skipped with `reason`. */
|
|
412
|
+
async unstart(runId, taskId, reason) {
|
|
413
|
+
// the one lock order: task row (paused for a lasting reason), then the task run
|
|
414
|
+
await lockTaskRow(this.db, taskId);
|
|
415
|
+
await this.skipIn(this.db, runId, taskId, reason);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* The start was refused for another reason (a full queue, a model gone since the task was
|
|
419
|
+
* saved, …): the run failed, and counts toward the task's failures as a failed run does.
|
|
420
|
+
*/
|
|
421
|
+
async failStart(runId, taskId, message) {
|
|
422
|
+
// the one lock order: task row (its failure count, maybe paused), then the task run
|
|
423
|
+
await lockTaskRow(this.db, taskId);
|
|
424
|
+
await this.tracker.failStartIn(runId, message);
|
|
425
|
+
}
|
|
426
|
+
async setConversation(runId, conversationId) {
|
|
427
|
+
await this.db
|
|
428
|
+
.updateTable("scheduled_task_runs")
|
|
429
|
+
.set({ conversation_id: conversationId })
|
|
430
|
+
.where("id", "=", runId)
|
|
431
|
+
.where("conversation_id", "is", null)
|
|
432
|
+
.execute();
|
|
433
|
+
}
|
|
434
|
+
/** Marks a pending run skipped (never fired) and pauses the task for a lasting reason. */
|
|
435
|
+
async skipIn(t, runId, taskId, reason) {
|
|
436
|
+
const r = await t
|
|
437
|
+
.updateTable("scheduled_task_runs")
|
|
438
|
+
.set({ status: "skipped", skip_reason: reason, fired_at: null })
|
|
439
|
+
.where("id", "=", runId)
|
|
440
|
+
.where("status", "=", "pending")
|
|
441
|
+
.executeTakeFirst();
|
|
442
|
+
if (Number(r.numUpdatedRows) === 0)
|
|
443
|
+
return;
|
|
444
|
+
if (LASTING.has(reason))
|
|
445
|
+
await pauseTaskIn(t, taskId, reason, null);
|
|
446
|
+
this.log.info("scheduled task run skipped", { taskId, taskRunId: runId, reason });
|
|
447
|
+
}
|
|
448
|
+
/** Another run of the task is still in flight (stale ones are settled on the way). */
|
|
449
|
+
async overlaps(taskId, runId) {
|
|
450
|
+
for (let i = 0; i < OVERLAP_SETTLE_MAX; i++) {
|
|
451
|
+
const prev = await this.store.latestNonTerminalRun(this.db, taskId, runId);
|
|
452
|
+
if (prev === null)
|
|
453
|
+
return false;
|
|
454
|
+
if (await this.tracker.inFlightIn(prev))
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
/** The creator is an active account and still a member of the org. */
|
|
460
|
+
async creatorActive(orgId, accountId) {
|
|
461
|
+
const row = await this.db
|
|
462
|
+
.selectFrom("memberships as m")
|
|
463
|
+
.innerJoin("accounts as a", "a.id", "m.account_id")
|
|
464
|
+
.select("a.status")
|
|
465
|
+
.where("m.org_id", "=", orgId)
|
|
466
|
+
.where("m.account_id", "=", accountId)
|
|
467
|
+
.executeTakeFirst();
|
|
468
|
+
return row?.status === "active";
|
|
469
|
+
}
|
|
470
|
+
/** The target conversation, live, the creator's chat with the task's agent and accessible. */
|
|
471
|
+
async targetConversation(task) {
|
|
472
|
+
if (task.conversationId === null)
|
|
473
|
+
return undefined;
|
|
474
|
+
const conv = await this.db
|
|
475
|
+
.selectFrom("conversations")
|
|
476
|
+
.select(["id", "queue_paused"])
|
|
477
|
+
.where("id", "=", task.conversationId)
|
|
478
|
+
.where("org_id", "=", task.orgId)
|
|
479
|
+
.where("account_id", "=", task.accountId)
|
|
480
|
+
.where("agent_id", "=", task.agentId)
|
|
481
|
+
.where("kind", "=", "chat")
|
|
482
|
+
.where("deleted_at", "is", null)
|
|
483
|
+
.executeTakeFirst();
|
|
484
|
+
if (!conv)
|
|
485
|
+
return undefined;
|
|
486
|
+
if (!(await this.access.isAccessible(task.orgId, conv.id, task.accountId)))
|
|
487
|
+
return undefined;
|
|
488
|
+
return { id: conv.id, queuePaused: conv.queue_paused };
|
|
489
|
+
}
|
|
490
|
+
async queuePaused(conversationId) {
|
|
491
|
+
const row = await this.db
|
|
492
|
+
.selectFrom("conversations")
|
|
493
|
+
.select("queue_paused")
|
|
494
|
+
.where("id", "=", conversationId)
|
|
495
|
+
.executeTakeFirst();
|
|
496
|
+
return row?.queue_paused === true;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* The DM thread key of the creator in `chatId` (the key inbound uses, `dm:<externalId>`), from
|
|
500
|
+
* their external ids on the connection's identity source (`<plugin>:<tenant>`): the id whose
|
|
501
|
+
* thread row in this chat is the newest (archived rows count); when none has a row there, the
|
|
502
|
+
* smallest id (deterministic). Without an identity (no tenant yet), the key of their newest DM
|
|
503
|
+
* thread row in the chat. Undefined when neither exists.
|
|
504
|
+
*/
|
|
505
|
+
async dmThreadKey(conn, chatId, accountId) {
|
|
506
|
+
const rows = await this.db
|
|
507
|
+
.selectFrom("channel_threads")
|
|
508
|
+
.select("thread_key")
|
|
509
|
+
.where("connection_id", "=", conn.id)
|
|
510
|
+
.where("chat_id", "=", chatId)
|
|
511
|
+
.where("account_id", "=", accountId)
|
|
512
|
+
.where("thread_key", "like", "dm:%")
|
|
513
|
+
.orderBy("created_at", "desc")
|
|
514
|
+
.orderBy("id", "desc")
|
|
515
|
+
.execute();
|
|
516
|
+
const used = rows.map((r) => r.thread_key);
|
|
517
|
+
if (conn.tenantId !== null) {
|
|
518
|
+
const ids = await this.db
|
|
519
|
+
.selectFrom("identities")
|
|
520
|
+
.select("external_id")
|
|
521
|
+
.where("source", "=", `${conn.plugin}:${conn.tenantId}`)
|
|
522
|
+
.where("account_id", "=", accountId)
|
|
523
|
+
.orderBy("external_id")
|
|
524
|
+
.execute();
|
|
525
|
+
const keys = ids.map((r) => `dm:${r.external_id}`);
|
|
526
|
+
// several ids on the source: the one with the newest thread row in this chat
|
|
527
|
+
const inChat = used.find((key) => keys.includes(key));
|
|
528
|
+
if (inChat !== undefined)
|
|
529
|
+
return inChat;
|
|
530
|
+
if (keys[0] !== undefined)
|
|
531
|
+
return keys[0];
|
|
532
|
+
}
|
|
533
|
+
return used[0];
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* The creator has written in the group (spec §8: a group thread row of theirs exists there,
|
|
537
|
+
* archived ones included), so a run may post there on their behalf.
|
|
538
|
+
*/
|
|
539
|
+
async inGroup(connectionId, chatId, accountId) {
|
|
540
|
+
const row = await this.db
|
|
541
|
+
.selectFrom("channel_threads")
|
|
542
|
+
.select("id")
|
|
543
|
+
.where("connection_id", "=", connectionId)
|
|
544
|
+
.where("chat_id", "=", chatId)
|
|
545
|
+
.where("account_id", "=", accountId)
|
|
546
|
+
.where("thread_key", "not like", "dm:%")
|
|
547
|
+
.limit(1)
|
|
548
|
+
.executeTakeFirst();
|
|
549
|
+
return row !== undefined;
|
|
550
|
+
}
|
|
551
|
+
/** The device is gone, or a local device whose machine is not connected now. */
|
|
552
|
+
async deviceOffline(deviceId) {
|
|
553
|
+
const row = await this.db
|
|
554
|
+
.selectFrom("devices")
|
|
555
|
+
.select(["source", "deleted_at"])
|
|
556
|
+
.where("id", "=", deviceId)
|
|
557
|
+
.executeTakeFirst();
|
|
558
|
+
if (!row || row.deleted_at !== null)
|
|
559
|
+
return true;
|
|
560
|
+
if (row.source !== "local")
|
|
561
|
+
return false;
|
|
562
|
+
return (await this.locks.holderOf(deviceLeaseKey(deviceId))) === null;
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
__decorate([
|
|
566
|
+
Transactional()
|
|
567
|
+
], ScheduledTaskFirer.prototype, "claim", null);
|
|
568
|
+
__decorate([
|
|
569
|
+
Transactional()
|
|
570
|
+
], ScheduledTaskFirer.prototype, "bindChat", null);
|
|
571
|
+
__decorate([
|
|
572
|
+
Transactional()
|
|
573
|
+
], ScheduledTaskFirer.prototype, "openGroup", null);
|
|
574
|
+
__decorate([
|
|
575
|
+
Transactional()
|
|
576
|
+
], ScheduledTaskFirer.prototype, "unstart", null);
|
|
577
|
+
__decorate([
|
|
578
|
+
Transactional()
|
|
579
|
+
], ScheduledTaskFirer.prototype, "failStart", null);
|
|
580
|
+
__decorate([
|
|
581
|
+
Transactional()
|
|
582
|
+
], ScheduledTaskFirer.prototype, "setConversation", null);
|
|
583
|
+
ScheduledTaskFirer = __decorate([
|
|
584
|
+
Injectable(),
|
|
585
|
+
__param(0, Inject(KernelDb)),
|
|
586
|
+
__param(1, Inject(TransactionHost)),
|
|
587
|
+
__param(2, Inject(KernelConfigService)),
|
|
588
|
+
__param(3, Inject(ScheduledTaskStore)),
|
|
589
|
+
__param(4, Inject(ScheduledTaskRunTracker)),
|
|
590
|
+
__param(5, Inject(OrgLock)),
|
|
591
|
+
__param(6, Inject(AgentLookup)),
|
|
592
|
+
__param(7, Inject(ConversationAccess)),
|
|
593
|
+
__param(8, Inject(ConversationsService)),
|
|
594
|
+
__param(9, Inject(ConversationQueue)),
|
|
595
|
+
__param(10, Inject(ChannelConnections)),
|
|
596
|
+
__param(11, Inject(RunControl)),
|
|
597
|
+
__param(12, Inject(LockService)),
|
|
598
|
+
__param(13, Inject(KERNEL_LOGGER))
|
|
599
|
+
], ScheduledTaskFirer);
|
|
600
|
+
export { ScheduledTaskFirer };
|
|
601
|
+
/**
|
|
602
|
+
* The fire job and the scanner, worker only: imported by `MaintenanceModule` (which dispatches
|
|
603
|
+
* `sched-fire`) and `WorkerModule` (the scan's `@LockedCron`), never by another role.
|
|
604
|
+
*/
|
|
605
|
+
let ScheduledTaskFireModule = class ScheduledTaskFireModule {
|
|
606
|
+
};
|
|
607
|
+
ScheduledTaskFireModule = __decorate([
|
|
608
|
+
Module({
|
|
609
|
+
imports: [
|
|
610
|
+
ConversationsModule,
|
|
611
|
+
ChannelsModule,
|
|
612
|
+
RuntimeModule,
|
|
613
|
+
AgentLookupModule,
|
|
614
|
+
ConversationAccessModule,
|
|
615
|
+
OrgLockModule,
|
|
616
|
+
ScheduledTaskStoreModule,
|
|
617
|
+
ScheduledTaskTrackerModule,
|
|
618
|
+
// the scanner enqueues the fire jobs
|
|
619
|
+
QueueModule.registerQueue(MAINTENANCE_QUEUE_NAME),
|
|
620
|
+
],
|
|
621
|
+
providers: [ScheduledTaskFirer, ScheduledTaskScanJob],
|
|
622
|
+
exports: [ScheduledTaskFirer],
|
|
623
|
+
})
|
|
624
|
+
], ScheduledTaskFireModule);
|
|
625
|
+
export { ScheduledTaskFireModule };
|