@aitne/daemon 0.1.10 → 0.1.11
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/adapters/adapter-watchdog.d.ts +70 -0
- package/dist/adapters/adapter-watchdog.js +115 -0
- package/dist/adapters/discord.d.ts +17 -1
- package/dist/adapters/discord.js +33 -0
- package/dist/adapters/notification-manager.d.ts +27 -1
- package/dist/adapters/notification-manager.js +54 -39
- package/dist/adapters/slack-adapter.d.ts +26 -1
- package/dist/adapters/slack-adapter.js +41 -0
- package/dist/adapters/telegram-adapter.d.ts +18 -1
- package/dist/adapters/telegram-adapter.js +41 -2
- package/dist/adapters/types.d.ts +20 -0
- package/dist/adapters/whatsapp-adapter.d.ts +26 -7
- package/dist/adapters/whatsapp-adapter.js +74 -21
- package/dist/api/env-writer.js +8 -5
- package/dist/api/helpers/agent-errors-registry.d.ts +5 -5
- package/dist/api/helpers/agent-errors-registry.js +5 -5
- package/dist/api/routes/agent.js +33 -12
- package/dist/api/routes/agents/index.js +75 -16
- package/dist/api/routes/agents/views.d.ts +37 -2
- package/dist/api/routes/agents/views.js +64 -2
- package/dist/api/routes/background-task.d.ts +22 -0
- package/dist/api/routes/background-task.js +338 -0
- package/dist/api/routes/browser-history.js +9 -1
- package/dist/api/routes/context/permissions.js +3 -2
- package/dist/api/routes/context/snapshots.js +0 -3
- package/dist/api/routes/context/write.js +3 -17
- package/dist/api/routes/dashboard/config.js +48 -12
- package/dist/api/routes/dashboard/cost-approvals.js +66 -0
- package/dist/api/routes/dashboard/notifications.js +9 -9
- package/dist/api/routes/integrations/crud-patch.js +5 -1
- package/dist/api/routes/integrations-reconcile.js +2 -2
- package/dist/api/routes/notion.d.ts +1 -1
- package/dist/api/routes/observations.js +7 -7
- package/dist/api/routes/obsidian.d.ts +1 -1
- package/dist/api/routes/receipts.js +5 -1
- package/dist/api/routes/setup-migrate.js +1 -1
- package/dist/api/routes/setup.js +1 -1
- package/dist/api/routes/task-flows.d.ts +1 -1
- package/dist/api/routes/task-flows.js +1 -1
- package/dist/api/routes/tuning.d.ts +29 -0
- package/dist/api/routes/tuning.js +304 -0
- package/dist/api/server.d.ts +44 -16
- package/dist/api/server.js +9 -0
- package/dist/bootstrap/adapters.d.ts +19 -0
- package/dist/bootstrap/adapters.js +61 -0
- package/dist/bootstrap/api.d.ts +5 -3
- package/dist/bootstrap/api.js +45 -13
- package/dist/bootstrap/catchup.d.ts +1 -1
- package/dist/bootstrap/catchup.js +11 -11
- package/dist/bootstrap/event-pipeline.d.ts +11 -0
- package/dist/bootstrap/event-pipeline.js +245 -7
- package/dist/bootstrap/observers.js +9 -6
- package/dist/bootstrap/schedule-helpers.d.ts +104 -6
- package/dist/bootstrap/schedule-helpers.js +172 -19
- package/dist/config.js +26 -12
- package/dist/core/agent-core.d.ts +33 -1
- package/dist/core/agent-core.js +36 -1
- package/dist/core/agents/activity-scan-cadence.d.ts +103 -0
- package/dist/core/agents/activity-scan-cadence.js +127 -0
- package/dist/core/agents/agent-route-override.d.ts +53 -0
- package/dist/core/agents/agent-route-override.js +69 -0
- package/dist/core/agents/builtin-registry.d.ts +51 -14
- package/dist/core/agents/builtin-registry.js +92 -15
- package/dist/core/agents/config-gate-reconcile.d.ts +38 -0
- package/dist/core/agents/config-gate-reconcile.js +51 -0
- package/dist/core/agents/cron-substitute.d.ts +1 -1
- package/dist/core/agents/cron-substitute.js +1 -1
- package/dist/core/agents/custom-routine-migration.d.ts +60 -0
- package/dist/core/agents/custom-routine-migration.js +149 -0
- package/dist/core/agents/firing-blocked.d.ts +1 -1
- package/dist/core/agents/hourly-cadence.d.ts +102 -0
- package/dist/core/agents/hourly-cadence.js +126 -0
- package/dist/core/agents/loader-boot.js +23 -0
- package/dist/core/agents/loader.d.ts +19 -0
- package/dist/core/agents/loader.js +34 -2
- package/dist/core/agents/override-merge.d.ts +1 -1
- package/dist/core/agents/override-merge.js +9 -1
- package/dist/core/agents/recurrence-convert.d.ts +1 -1
- package/dist/core/agents/recurrence-convert.js +1 -1
- package/dist/core/agents/recurring-schedule-adapter.js +8 -0
- package/dist/core/alerts.js +6 -6
- package/dist/core/backends/auth-health-monitor.d.ts +2 -2
- package/dist/core/backends/auth-health-monitor.js +1 -1
- package/dist/core/backends/backend-router.d.ts +27 -1
- package/dist/core/backends/backend-router.js +165 -1
- package/dist/core/backends/claude-code-core.d.ts +71 -31
- package/dist/core/backends/claude-code-core.js +282 -54
- package/dist/core/backends/cli-quota-guards.d.ts +29 -1
- package/dist/core/backends/cli-quota-guards.js +40 -5
- package/dist/core/backends/codex-core.d.ts +6 -0
- package/dist/core/backends/codex-core.js +22 -6
- package/dist/core/backends/failure-spend.d.ts +58 -0
- package/dist/core/backends/failure-spend.js +137 -0
- package/dist/core/backends/gemini-cli-core.d.ts +6 -0
- package/dist/core/backends/gemini-cli-core.js +25 -6
- package/dist/core/backends/model-registry.d.ts +1 -1
- package/dist/core/backends/model-registry.js +4 -4
- package/dist/core/backends/opencode-core.d.ts +1 -1
- package/dist/core/backends/opencode-core.js +5 -5
- package/dist/core/backends/plan-presets.js +39 -15
- package/dist/core/bang-commands/commands-cost.js +3 -1
- package/dist/core/bang-commands/commands-report.js +4 -3
- package/dist/core/bang-commands/commands-research.js +4 -1
- package/dist/core/bang-commands/commands-revert-tuning.d.ts +18 -0
- package/dist/core/bang-commands/commands-revert-tuning.js +63 -0
- package/dist/core/bang-commands/commands-stop-start.js +3 -3
- package/dist/core/bang-commands/commands-task-control.d.ts +19 -0
- package/dist/core/bang-commands/commands-task-control.js +147 -0
- package/dist/core/bang-commands/commands-wiki.js +5 -5
- package/dist/core/bang-commands/index.d.ts +2 -0
- package/dist/core/bang-commands/index.js +12 -0
- package/dist/core/bang-commands/registry.d.ts +12 -0
- package/dist/core/browser-history/research-cluster-fanout.d.ts +28 -14
- package/dist/core/browser-history/research-cluster-fanout.js +39 -16
- package/dist/core/channel-timeline.d.ts +5 -1
- package/dist/core/channel-timeline.js +13 -0
- package/dist/core/context/index-reconciler.js +5 -2
- package/dist/core/context/policy-index-reconciler.d.ts +6 -4
- package/dist/core/context/policy-index-runner.js +25 -6
- package/dist/core/context-builder-calendar.js +10 -2
- package/dist/core/context-builder-conversation.d.ts +8 -1
- package/dist/core/context-builder-conversation.js +41 -7
- package/dist/core/context-builder-yesterday.js +4 -3
- package/dist/core/context-builder.d.ts +7 -2
- package/dist/core/context-builder.js +62 -20
- package/dist/core/context-file-serializer.d.ts +1 -1
- package/dist/core/context-file-serializer.js +1 -1
- package/dist/core/context-health.js +2 -2
- package/dist/core/context-paths.d.ts +1 -1
- package/dist/core/context-paths.js +1 -1
- package/dist/core/context-validation/prepare-write.js +1 -1
- package/dist/core/context-validation/routine-rulebook.d.ts +1 -1
- package/dist/core/context-vault-aliases.d.ts +0 -13
- package/dist/core/context-vault-aliases.js +37 -0
- package/dist/core/custom-routines.d.ts +99 -0
- package/dist/core/custom-routines.js +187 -0
- package/dist/core/daemon-api-cli.js +49 -0
- package/dist/core/day-boundary.d.ts +46 -0
- package/dist/core/day-boundary.js +40 -0
- package/dist/core/dispatcher-activity-scan.d.ts +221 -0
- package/dist/core/dispatcher-activity-scan.js +775 -0
- package/dist/core/dispatcher-error-handling.d.ts +6 -11
- package/dist/core/dispatcher-error-handling.js +38 -62
- package/dist/core/dispatcher-hourly-check.js +6 -1
- package/dist/core/dispatcher-message-handler.d.ts +10 -0
- package/dist/core/dispatcher-message-handler.js +17 -0
- package/dist/core/dispatcher-morning-routine.d.ts +6 -6
- package/dist/core/dispatcher-morning-routine.js +13 -13
- package/dist/core/dispatcher-result-processor.d.ts +33 -0
- package/dist/core/dispatcher-result-processor.js +167 -11
- package/dist/core/dispatcher-scheduled-background-task.d.ts +42 -0
- package/dist/core/dispatcher-scheduled-background-task.js +89 -0
- package/dist/core/dispatcher-scheduled-tasks.d.ts +63 -1
- package/dist/core/dispatcher-scheduled-tasks.js +213 -6
- package/dist/core/dispatcher-task-delivery.d.ts +105 -0
- package/dist/core/dispatcher-task-delivery.js +555 -0
- package/dist/core/dispatcher-types.d.ts +48 -9
- package/dist/core/dispatcher-types.js +3 -3
- package/dist/core/dispatcher.d.ts +112 -31
- package/dist/core/dispatcher.js +284 -59
- package/dist/core/dm-freshness-metrics.d.ts +1 -1
- package/dist/core/drift-effects.js +2 -2
- package/dist/core/feedback/consolidation-prep.js +17 -5
- package/dist/core/feedback/eviction-scorer.js +6 -2
- package/dist/core/feedback/lesson-format.js +9 -4
- package/dist/core/feedback/lesson-injection.d.ts +1 -1
- package/dist/core/feedback/lesson-injection.js +17 -2
- package/dist/core/feedback/lesson-store-overview.d.ts +8 -4
- package/dist/core/feedback/lesson-store-overview.js +8 -4
- package/dist/core/feedback/regeneralization-prep.js +29 -16
- package/dist/core/feedback/self-performance-prep.d.ts +186 -0
- package/dist/core/feedback/self-performance-prep.js +541 -0
- package/dist/core/feedback/tuning-actuator.d.ts +198 -0
- package/dist/core/feedback/tuning-actuator.js +432 -0
- package/dist/core/feedback/tuning-recommender.d.ts +247 -0
- package/dist/core/feedback/tuning-recommender.js +580 -0
- package/dist/core/feedback/tuning-revert-monitor.d.ts +90 -0
- package/dist/core/feedback/tuning-revert-monitor.js +213 -0
- package/dist/core/health-monitor.d.ts +6 -0
- package/dist/core/health-monitor.js +1 -1
- package/dist/core/injection-policy.d.ts +4 -4
- package/dist/core/injection-policy.js +4 -4
- package/dist/core/integration-main-backend.js +4 -0
- package/dist/core/management-md.d.ts +2 -2
- package/dist/core/management-md.js +51 -13
- package/dist/core/morning/orchestrator.d.ts +2 -2
- package/dist/core/morning/orchestrator.js +2 -2
- package/dist/core/notification-gate.d.ts +64 -0
- package/dist/core/notification-gate.js +51 -0
- package/dist/core/notification-rate-limit.d.ts +40 -0
- package/dist/core/notification-rate-limit.js +50 -0
- package/dist/core/policy-files.d.ts +1 -1
- package/dist/core/policy-files.js +2 -2
- package/dist/core/pre-pass-freshness.d.ts +4 -4
- package/dist/core/retention.d.ts +5 -0
- package/dist/core/retention.js +20 -4
- package/dist/core/review-context.d.ts +1 -1
- package/dist/core/review-context.js +10 -5
- package/dist/core/roadmap-write-lock.d.ts +2 -1
- package/dist/core/roadmap-write-lock.js +15 -10
- package/dist/core/routine-acquisition-plan.d.ts +47 -1
- package/dist/core/routine-acquisition-plan.js +78 -20
- package/dist/core/routine-fetch-window-retry.js +7 -4
- package/dist/core/routine-fetch-window-runner.d.ts +39 -3
- package/dist/core/routine-fetch-window-runner.js +264 -13
- package/dist/core/routine-windows.d.ts +2 -2
- package/dist/core/routine-windows.js +8 -5
- package/dist/core/scheduler.d.ts +175 -16
- package/dist/core/scheduler.js +559 -102
- package/dist/core/signal-detector.d.ts +12 -0
- package/dist/core/signal-detector.js +53 -9
- package/dist/core/skills-compiler-denied-tools.js +2 -2
- package/dist/core/skills-compiler-skill-index.d.ts +2 -2
- package/dist/core/skills-compiler-skill-index.js +2 -2
- package/dist/core/skills-compiler-variants.d.ts +1 -1
- package/dist/core/skills-compiler-variants.js +8 -0
- package/dist/core/skills-compiler.d.ts +29 -26
- package/dist/core/skills-compiler.js +117 -81
- package/dist/core/skills-manifest.d.ts +37 -0
- package/dist/core/skills-manifest.js +73 -2
- package/dist/core/sleep-inhibitor.d.ts +79 -0
- package/dist/core/sleep-inhibitor.js +132 -0
- package/dist/core/slim-system-prompt-loader.d.ts +77 -0
- package/dist/core/slim-system-prompt-loader.js +141 -0
- package/dist/core/spawn-gates.d.ts +126 -0
- package/dist/core/spawn-gates.js +180 -0
- package/dist/core/today-direct-writer.d.ts +2 -2
- package/dist/core/today-direct-writer.js +1 -1
- package/dist/core/today-write-lock.d.ts +4 -2
- package/dist/core/today-write-lock.js +30 -20
- package/dist/core/wake-detector.d.ts +55 -0
- package/dist/core/wake-detector.js +80 -0
- package/dist/core/wiki/compile-lock.d.ts +1 -1
- package/dist/core/wiki/compile-lock.js +1 -1
- package/dist/core/workdir.js +15 -6
- package/dist/db/activity-scan-signals.d.ts +77 -0
- package/dist/db/activity-scan-signals.js +378 -0
- package/dist/db/agents-store.d.ts +28 -0
- package/dist/db/agents-store.js +62 -0
- package/dist/db/background-task-clarifications-store.d.ts +81 -0
- package/dist/db/background-task-clarifications-store.js +152 -0
- package/dist/db/background-task-store.d.ts +207 -0
- package/dist/db/background-task-store.js +380 -0
- package/dist/db/browser-history-store.d.ts +39 -6
- package/dist/db/browser-history-store.js +51 -7
- package/dist/db/browser-task-clarifications-store.d.ts +12 -0
- package/dist/db/browser-task-clarifications-store.js +35 -5
- package/dist/db/browser-task-store.d.ts +3 -0
- package/dist/db/browser-task-store.js +29 -4
- package/dist/db/deferred-dm.d.ts +86 -0
- package/dist/db/deferred-dm.js +199 -0
- package/dist/db/migrations.js +330 -0
- package/dist/db/observations.d.ts +2 -2
- package/dist/db/observations.js +3 -3
- package/dist/db/schema.js +217 -16
- package/dist/db/voice-transcripts-store.d.ts +1 -1
- package/dist/index.js +86 -29
- package/dist/messaging/browser-task-mcp-notifier.d.ts +12 -70
- package/dist/messaging/browser-task-mcp-notifier.js +30 -151
- package/dist/messaging/browser-task-screenshot-attachment.d.ts +15 -0
- package/dist/messaging/browser-task-screenshot-attachment.js +63 -0
- package/dist/observers/delegated-sync-worker.d.ts +6 -6
- package/dist/observers/delegated-sync-worker.js +10 -10
- package/dist/observers/git-delegated-cron.d.ts +1 -1
- package/dist/observers/git-delegated-cron.js +2 -2
- package/dist/observers/github-poller-classifier.d.ts +3 -3
- package/dist/observers/github-poller-classifier.js +3 -3
- package/dist/observers/imminent-event-scheduler.d.ts +1 -1
- package/dist/observers/imminent-event-scheduler.js +1 -1
- package/dist/observers/mail-poller.d.ts +1 -0
- package/dist/observers/mail-poller.js +42 -3
- package/dist/observers/observation-summarizer/summarizer-client.d.ts +2 -2
- package/dist/observers/observation-summarizer/summarizer-client.js +2 -2
- package/dist/observers/observation-summarizer/worker.d.ts +2 -2
- package/dist/observers/observation-summarizer/worker.js +4 -4
- package/dist/observers/obsidian-watcher.d.ts +1 -1
- package/dist/observers/obsidian-watcher.js +1 -1
- package/dist/safety/agent-write-tracker.d.ts +4 -4
- package/dist/safety/agent-write-tracker.js +4 -4
- package/dist/safety/audit.d.ts +43 -5
- package/dist/safety/audit.js +86 -18
- package/dist/safety/risk-classifier.d.ts +6 -0
- package/dist/safety/risk-classifier.js +75 -11
- package/dist/scheduler/activity-scan-gate.d.ts +86 -0
- package/dist/scheduler/activity-scan-gate.js +132 -0
- package/dist/services/background-task/background-task-budget.d.ts +80 -0
- package/dist/services/background-task/background-task-budget.js +91 -0
- package/dist/services/background-task/background-task-driver.d.ts +105 -0
- package/dist/services/background-task/background-task-driver.js +416 -0
- package/dist/services/background-task/background-task-runner.d.ts +96 -0
- package/dist/services/background-task/background-task-runner.js +673 -0
- package/dist/services/background-task/background-task-tools.d.ts +84 -0
- package/dist/services/background-task/background-task-tools.js +247 -0
- package/dist/services/background-task/background-task-transition-events.d.ts +43 -0
- package/dist/services/background-task/background-task-transition-events.js +54 -0
- package/dist/services/browser-history/automation/egress-denylist.d.ts +1 -1
- package/dist/services/browser-history/automation/egress-denylist.js +16 -6
- package/dist/services/browser-history/managed-chromium/sandbox-launcher.js +0 -1
- package/dist/services/browser-task/browser-task-runner.js +53 -8
- package/dist/services/observations-batch.d.ts +1 -1
- package/dist/services/observations-batch.js +2 -2
- package/dist/settings/runtime-settings.d.ts +38 -11
- package/dist/settings/runtime-settings.js +203 -40
- package/dist/settings/settings-store.js +11 -3
- package/package.json +4 -4
|
@@ -1,77 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser-task MCP-side
|
|
2
|
+
* Browser-task MCP-side delivery bridge — BACKGROUND_TASK_RUNNER_DESIGN.md
|
|
3
|
+
* Phase 1.
|
|
3
4
|
*
|
|
4
|
-
* The browser-task sub-agent
|
|
5
|
-
* this
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* of screenshots (attached inline) the user should
|
|
11
|
-
* review.
|
|
12
|
-
*
|
|
13
|
-
* Distinct from the runner-side `BrowserTaskNotifier` (queued / terminal
|
|
14
|
-
* structural DMs):
|
|
15
|
-
*
|
|
16
|
-
* - The runner-side notifier covers events the sub-agent never sees
|
|
17
|
-
* (the slot manager queued the task, the SDK loop crashed before any
|
|
18
|
-
* tool fired, etc.). Plain templated bodies.
|
|
19
|
-
* - This MCP-side notifier carries agent-authored prose — the
|
|
20
|
-
* `question` / `report` strings come from the sub-agent.
|
|
21
|
-
*
|
|
22
|
-
* The two cannot collapse into one because:
|
|
23
|
-
* - The SDK tool body needs synchronous access to a notifier (it's
|
|
24
|
-
* invoked inside `mcp__aitne-browser__ask_user`'s handler); the
|
|
25
|
-
* runner-side notifier is invoked from the runner's lifecycle hooks.
|
|
26
|
-
* - The agent-authored vs. structural split keeps the redaction-
|
|
27
|
-
* coverage guard happy: structural bodies are templated text that
|
|
28
|
-
* the guard knows is safe; agent bodies pass the same redaction
|
|
29
|
-
* pipeline already applied to other LLM-authored outbound text.
|
|
30
|
-
*
|
|
31
|
-
* Best-effort delivery: DM failures log + continue. The DB row for the
|
|
32
|
-
* task / clarification has already been written by the tool handler, so
|
|
33
|
-
* a DM hiccup does NOT block the parent task — the dashboard surfaces
|
|
34
|
-
* the row regardless. (See §5 ask_user "Resume — Deadline enforcement"
|
|
35
|
-
* for the deadline-driven fallback when the user never sees the DM.)
|
|
36
|
-
*
|
|
37
|
-
* No capability-symbol gate here. The structural anti-spoofing surface
|
|
38
|
-
* (B-4 purchase confirms + lite-final-confirm tokens) protects DM bodies
|
|
39
|
-
* that the agent could otherwise mint to itself; `ask_user` / `finish`
|
|
40
|
-
* bodies are intentionally agent-authored — the user is reading the
|
|
41
|
-
* agent's question / report. The only header marker we attach is for the
|
|
42
|
-
* user's benefit, not for adapter-side trust gating.
|
|
5
|
+
* The browser-task sub-agent still writes clarifications/reports through
|
|
6
|
+
* its `ask_user` and `finish` tools, but this bridge no longer sends a
|
|
7
|
+
* templated DM directly. It enqueues a `task.delivery` event instead; the
|
|
8
|
+
* dispatcher acquires the owner-DM gates, chooses active vs idle delivery,
|
|
9
|
+
* records the sent assistant message into conversation history, and marks
|
|
10
|
+
* the row delivered for recovery.
|
|
43
11
|
*/
|
|
44
|
-
import {
|
|
45
|
-
import
|
|
12
|
+
import type { EventBus } from "../core/event-bus.js";
|
|
13
|
+
import type Database from "better-sqlite3";
|
|
46
14
|
import type { BrowserTaskMcpNotifier } from "../services/browser-history/automation/browser-task-tools/server.js";
|
|
47
|
-
/** Header line for ask_user DMs. Chosen so it does NOT collide with the
|
|
48
|
-
* B-4 / lite-final-confirm markers (which carry the literal substring
|
|
49
|
-
* "confirmation") nor with the runner's `🕒` / `🟦` queue / terminal
|
|
50
|
-
* emojis. */
|
|
51
|
-
export declare const ASK_USER_HEADER = "Browser task \u2014 needs your input";
|
|
52
|
-
/** Header line for finish DMs. */
|
|
53
|
-
export declare const FINISH_HEADER = "Browser task \u2014 report";
|
|
54
15
|
export interface CreateBrowserTaskMcpNotifierDeps {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* screenshotKey (`/api/browser-task/<id>/screenshots/<file>`) back to
|
|
58
|
-
* its on-disk location under
|
|
59
|
-
* `<paDataDir>/automation-traces/<id>/<file>` so the bytes can be
|
|
60
|
-
* uploaded through the messaging adapter / ingested for the dashboard.
|
|
61
|
-
* When omitted, every screenshot resolves to an "unavailable" note. */
|
|
62
|
-
paDataDir?: string;
|
|
63
|
-
/** Ingest a resolved trace-store screenshot into the chat
|
|
64
|
-
* `AttachmentStore` and return a store-backed `OutboundAttachmentRef`
|
|
65
|
-
* (or null on failure). Used for the `dashboard` platform ONLY: the
|
|
66
|
-
* dashboard fetches attachments by id through the authenticated
|
|
67
|
-
* same-origin `/api/chat/attachments/:id` proxy, so a loopback trace
|
|
68
|
-
* URL embedded as markdown would 401 (the bearer token is never
|
|
69
|
-
* attached to a raw `<img>` request). Minting a real store id lets the
|
|
70
|
-
* dashboard render the bytes inline like any other agent attachment —
|
|
71
|
-
* never a URL. Messaging adapters take the trace file directly via
|
|
72
|
-
* their native upload API, so they do NOT go through this. Optional:
|
|
73
|
-
* when omitted, dashboard screenshots resolve to an "unavailable"
|
|
74
|
-
* note. */
|
|
75
|
-
ingestOutboundImage?: IngestOutboundImage;
|
|
16
|
+
eventBus: EventBus;
|
|
17
|
+
db: Database.Database;
|
|
76
18
|
}
|
|
77
19
|
export declare function createBrowserTaskMcpNotifier(deps: CreateBrowserTaskMcpNotifierDeps): BrowserTaskMcpNotifier;
|
|
@@ -1,164 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser-task MCP-side
|
|
2
|
+
* Browser-task MCP-side delivery bridge — BACKGROUND_TASK_RUNNER_DESIGN.md
|
|
3
|
+
* Phase 1.
|
|
3
4
|
*
|
|
4
|
-
* The browser-task sub-agent
|
|
5
|
-
* this
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* of screenshots (attached inline) the user should
|
|
11
|
-
* review.
|
|
12
|
-
*
|
|
13
|
-
* Distinct from the runner-side `BrowserTaskNotifier` (queued / terminal
|
|
14
|
-
* structural DMs):
|
|
15
|
-
*
|
|
16
|
-
* - The runner-side notifier covers events the sub-agent never sees
|
|
17
|
-
* (the slot manager queued the task, the SDK loop crashed before any
|
|
18
|
-
* tool fired, etc.). Plain templated bodies.
|
|
19
|
-
* - This MCP-side notifier carries agent-authored prose — the
|
|
20
|
-
* `question` / `report` strings come from the sub-agent.
|
|
21
|
-
*
|
|
22
|
-
* The two cannot collapse into one because:
|
|
23
|
-
* - The SDK tool body needs synchronous access to a notifier (it's
|
|
24
|
-
* invoked inside `mcp__aitne-browser__ask_user`'s handler); the
|
|
25
|
-
* runner-side notifier is invoked from the runner's lifecycle hooks.
|
|
26
|
-
* - The agent-authored vs. structural split keeps the redaction-
|
|
27
|
-
* coverage guard happy: structural bodies are templated text that
|
|
28
|
-
* the guard knows is safe; agent bodies pass the same redaction
|
|
29
|
-
* pipeline already applied to other LLM-authored outbound text.
|
|
30
|
-
*
|
|
31
|
-
* Best-effort delivery: DM failures log + continue. The DB row for the
|
|
32
|
-
* task / clarification has already been written by the tool handler, so
|
|
33
|
-
* a DM hiccup does NOT block the parent task — the dashboard surfaces
|
|
34
|
-
* the row regardless. (See §5 ask_user "Resume — Deadline enforcement"
|
|
35
|
-
* for the deadline-driven fallback when the user never sees the DM.)
|
|
36
|
-
*
|
|
37
|
-
* No capability-symbol gate here. The structural anti-spoofing surface
|
|
38
|
-
* (B-4 purchase confirms + lite-final-confirm tokens) protects DM bodies
|
|
39
|
-
* that the agent could otherwise mint to itself; `ask_user` / `finish`
|
|
40
|
-
* bodies are intentionally agent-authored — the user is reading the
|
|
41
|
-
* agent's question / report. The only header marker we attach is for the
|
|
42
|
-
* user's benefit, not for adapter-side trust gating.
|
|
5
|
+
* The browser-task sub-agent still writes clarifications/reports through
|
|
6
|
+
* its `ask_user` and `finish` tools, but this bridge no longer sends a
|
|
7
|
+
* templated DM directly. It enqueues a `task.delivery` event instead; the
|
|
8
|
+
* dispatcher acquires the owner-DM gates, chooses active vs idle delivery,
|
|
9
|
+
* records the sent assistant message into conversation history, and marks
|
|
10
|
+
* the row delivered for recovery.
|
|
43
11
|
*/
|
|
12
|
+
import { createBrowserTaskClarificationDeliveryEvent, createBrowserTaskResultDeliveryEvent, } from "../core/dispatcher-task-delivery.js";
|
|
13
|
+
import { getBrowserTask } from "../db/browser-task-store.js";
|
|
44
14
|
import { createLogger } from "../logging.js";
|
|
45
|
-
import { MessageDeliveryError, } from "../adapters/message-hub.js";
|
|
46
|
-
import { parseChannelRef } from "../db/browser-automation-purchase-primary-channels-store.js";
|
|
47
|
-
import { resolveScreenshotAttachment, } from "./browser-task-screenshot-attachment.js";
|
|
48
15
|
const logger = createLogger("browser-task-mcp-notifier");
|
|
49
|
-
/** Header line for ask_user DMs. Chosen so it does NOT collide with the
|
|
50
|
-
* B-4 / lite-final-confirm markers (which carry the literal substring
|
|
51
|
-
* "confirmation") nor with the runner's `🕒` / `🟦` queue / terminal
|
|
52
|
-
* emojis. */
|
|
53
|
-
export const ASK_USER_HEADER = "Browser task — needs your input";
|
|
54
|
-
/** Header line for finish DMs. */
|
|
55
|
-
export const FINISH_HEADER = "Browser task — report";
|
|
56
|
-
/** Soft cap on the `finish` report body inside the DM. The agent's tool
|
|
57
|
-
* schema already caps `report` at 8 KB; some adapters (Telegram) cap
|
|
58
|
-
* individual messages at ~4 KB. We truncate at 3 800 chars to leave
|
|
59
|
-
* comfortable room for headers + screenshot links and append a "[…]"
|
|
60
|
-
* marker so the user can tell the report was cropped.
|
|
61
|
-
* The Aitne dashboard's per-task detail page renders the full report
|
|
62
|
-
* via `GET /api/browser-task/:id`, so truncation is purely a DM-side
|
|
63
|
-
* ergonomic. */
|
|
64
|
-
const FINISH_REPORT_DM_BODY_CAP = 3_800;
|
|
65
|
-
/** Max screenshots attached to a single finish DM. The full ordered list
|
|
66
|
-
* is preserved in the row's `report` field; this cap just keeps the DM
|
|
67
|
-
* from ballooning with attachments. */
|
|
68
|
-
const FINISH_DM_SCREENSHOT_LINK_CAP = 8;
|
|
69
16
|
export function createBrowserTaskMcpNotifier(deps) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
* image bytes — never a URL:
|
|
73
|
-
*
|
|
74
|
-
* - `dashboard`: each key is ingested into the chat `AttachmentStore`
|
|
75
|
-
* and delivered as an `OutboundAttachmentRef`; the dashboard renders
|
|
76
|
-
* it inline by fetching `/api/chat/attachments/:id` through its
|
|
77
|
-
* authenticated same-origin proxy.
|
|
78
|
-
* - messaging adapters (WhatsApp / Telegram / Slack / Discord): each
|
|
79
|
-
* key is handed to the adapter as a trace-file `OutboundAttachmentRef`
|
|
80
|
-
* so the adapter uploads the bytes via its native API.
|
|
81
|
-
*
|
|
82
|
-
* Any key that cannot be resolved (file dropped by §14.7 retention,
|
|
83
|
-
* ingest unavailable, unknown extension) is replaced by a single
|
|
84
|
-
* "unavailable" note rather than an unreachable link. The dashboard's
|
|
85
|
-
* `/browser-tasks/<id>` page remains the canonical full-trace view. */
|
|
86
|
-
async function dispatch(ref, head, tail, screenshotKeys) {
|
|
87
|
-
const parsed = parseChannelRef(ref);
|
|
88
|
-
if (!parsed) {
|
|
89
|
-
logger.warn({ ref }, "browser-task MCP notifier: unparseable channel ref — DM skipped");
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
const headLines = head.filter((s) => s !== null);
|
|
93
|
-
const tailLines = tail.filter((s) => s !== null);
|
|
94
|
-
const resolved = (await Promise.all(screenshotKeys.map((key) => resolveScreenshotAttachment({
|
|
95
|
-
platform: parsed.platform,
|
|
96
|
-
key,
|
|
97
|
-
paDataDir,
|
|
98
|
-
ingestOutboundImage: deps.ingestOutboundImage,
|
|
99
|
-
})))).filter((a) => a !== null);
|
|
100
|
-
const unresolved = screenshotKeys.length - resolved.length;
|
|
101
|
-
const noteBlock = unresolved > 0
|
|
102
|
-
? [
|
|
103
|
-
"",
|
|
104
|
-
`(${unresolved} screenshot${unresolved === 1 ? "" : "s"} could not be attached — open the browser-task detail page)`,
|
|
105
|
-
]
|
|
106
|
-
: [];
|
|
107
|
-
const body = [...headLines, ...noteBlock, ...tailLines].join("\n");
|
|
108
|
-
const attachments = resolved.length > 0 ? resolved : undefined;
|
|
109
|
-
try {
|
|
110
|
-
await deps.messageHub.sendToPlatform(parsed.platform, parsed.channelId, body, undefined, attachments);
|
|
111
|
-
}
|
|
112
|
-
catch (err) {
|
|
113
|
-
const reason = err instanceof MessageDeliveryError
|
|
114
|
-
? err.message
|
|
115
|
-
: err instanceof Error
|
|
116
|
-
? err.message
|
|
117
|
-
: String(err);
|
|
118
|
-
logger.warn({ ref, reason }, "browser-task MCP notifier: DM dispatch failed (continuing)");
|
|
119
|
-
}
|
|
17
|
+
function titleFor(taskId) {
|
|
18
|
+
return getBrowserTask(deps.db, taskId)?.description ?? `Browser task ${taskId}`;
|
|
120
19
|
}
|
|
121
20
|
async function notifyAskUser(input) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
`Task: ${input.taskId}`,
|
|
133
|
-
`Question: ${input.question}`,
|
|
134
|
-
`Context: ${input.contextSummary}`,
|
|
135
|
-
];
|
|
136
|
-
const tail = [
|
|
137
|
-
``,
|
|
138
|
-
`Reply in this DM to answer (clarification id: ${input.clarificationId}).`,
|
|
139
|
-
];
|
|
140
|
-
await dispatch(input.originatingChannel, head, tail, screenshotKeys);
|
|
21
|
+
await deps.eventBus.put(createBrowserTaskClarificationDeliveryEvent({
|
|
22
|
+
taskId: input.taskId,
|
|
23
|
+
originatingChannel: input.originatingChannel,
|
|
24
|
+
title: titleFor(input.taskId),
|
|
25
|
+
clarificationId: input.clarificationId,
|
|
26
|
+
question: input.question,
|
|
27
|
+
contextSummary: input.contextSummary,
|
|
28
|
+
screenshotKey: input.screenshotKey,
|
|
29
|
+
}));
|
|
30
|
+
logger.debug({ taskId: input.taskId, clarificationId: input.clarificationId }, "browser-task clarification queued for task.delivery");
|
|
141
31
|
}
|
|
142
32
|
async function notifyFinish(input) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const overflowCount = Math.max(0, input.screenshotKeys.length - keyBudget.length);
|
|
152
|
-
const head = [
|
|
153
|
-
`✅ ${FINISH_HEADER}`,
|
|
154
|
-
`Task: ${input.taskId}`,
|
|
155
|
-
``,
|
|
156
|
-
reportBody,
|
|
157
|
-
];
|
|
158
|
-
const tail = overflowCount > 0
|
|
159
|
-
? [``, `(+${overflowCount} more — see dashboard)`]
|
|
160
|
-
: [];
|
|
161
|
-
await dispatch(input.originatingChannel, head, tail, keyBudget);
|
|
33
|
+
await deps.eventBus.put(createBrowserTaskResultDeliveryEvent({
|
|
34
|
+
taskId: input.taskId,
|
|
35
|
+
originatingChannel: input.originatingChannel,
|
|
36
|
+
title: titleFor(input.taskId),
|
|
37
|
+
report: input.report,
|
|
38
|
+
screenshotKeys: input.screenshotKeys,
|
|
39
|
+
}));
|
|
40
|
+
logger.debug({ taskId: input.taskId }, "browser-task report queued for task.delivery");
|
|
162
41
|
}
|
|
163
42
|
return { notifyAskUser, notifyFinish };
|
|
164
43
|
}
|
|
@@ -60,3 +60,18 @@ export declare function resolveScreenshotAttachment(params: {
|
|
|
60
60
|
paDataDir: string | null;
|
|
61
61
|
ingestOutboundImage?: IngestOutboundImage;
|
|
62
62
|
}): Promise<OutboundAttachmentRef | null>;
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a worker-produced output FILE (absolute path) to a
|
|
65
|
+
* platform-appropriate outbound attachment — the generic-asset sibling of
|
|
66
|
+
* `resolveScreenshotAttachment` (BACKGROUND_TASK_RUNNER_DESIGN.md Phase 1 —
|
|
67
|
+
* delivery assets). Messaging adapters take the file path directly; the
|
|
68
|
+
* dashboard ingests it into the `AttachmentStore` so it renders inline.
|
|
69
|
+
* Returns null when the file is missing on disk or the dashboard ingest
|
|
70
|
+
* hook is unavailable — the caller omits it rather than sending a dead link.
|
|
71
|
+
*/
|
|
72
|
+
export declare function buildPathAttachment(params: {
|
|
73
|
+
platform: string;
|
|
74
|
+
absPath: string;
|
|
75
|
+
filename: string;
|
|
76
|
+
ingestOutboundImage?: IngestOutboundImage;
|
|
77
|
+
}): Promise<OutboundAttachmentRef | null>;
|
|
@@ -113,3 +113,66 @@ export async function resolveScreenshotAttachment(params) {
|
|
|
113
113
|
? buildStoreAttachment(params.paDataDir, params.ingestOutboundImage, params.key)
|
|
114
114
|
: buildTraceAttachment(params.paDataDir, params.key);
|
|
115
115
|
}
|
|
116
|
+
/** MIME by extension for generic worker-produced deliverables (PDF / slides
|
|
117
|
+
* / docs / images). Superset of the screenshot image map. Unknown
|
|
118
|
+
* extensions fall back to `application/octet-stream` so the adapter still
|
|
119
|
+
* uploads the bytes. */
|
|
120
|
+
const DELIVERABLE_MIME_BY_EXT = {
|
|
121
|
+
...IMAGE_MIME_BY_EXT,
|
|
122
|
+
gif: "image/gif",
|
|
123
|
+
pdf: "application/pdf",
|
|
124
|
+
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
125
|
+
ppt: "application/vnd.ms-powerpoint",
|
|
126
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
127
|
+
doc: "application/msword",
|
|
128
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
129
|
+
csv: "text/csv",
|
|
130
|
+
txt: "text/plain",
|
|
131
|
+
md: "text/markdown",
|
|
132
|
+
};
|
|
133
|
+
function mimeForFilename(filename) {
|
|
134
|
+
const ext = filename.slice(filename.lastIndexOf(".") + 1).toLowerCase();
|
|
135
|
+
return DELIVERABLE_MIME_BY_EXT[ext] ?? "application/octet-stream";
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolve a worker-produced output FILE (absolute path) to a
|
|
139
|
+
* platform-appropriate outbound attachment — the generic-asset sibling of
|
|
140
|
+
* `resolveScreenshotAttachment` (BACKGROUND_TASK_RUNNER_DESIGN.md Phase 1 —
|
|
141
|
+
* delivery assets). Messaging adapters take the file path directly; the
|
|
142
|
+
* dashboard ingests it into the `AttachmentStore` so it renders inline.
|
|
143
|
+
* Returns null when the file is missing on disk or the dashboard ingest
|
|
144
|
+
* hook is unavailable — the caller omits it rather than sending a dead link.
|
|
145
|
+
*/
|
|
146
|
+
export async function buildPathAttachment(params) {
|
|
147
|
+
const mimeType = mimeForFilename(params.filename);
|
|
148
|
+
if (params.platform === "dashboard") {
|
|
149
|
+
if (!params.ingestOutboundImage)
|
|
150
|
+
return null;
|
|
151
|
+
try {
|
|
152
|
+
return await params.ingestOutboundImage({
|
|
153
|
+
absPath: params.absPath,
|
|
154
|
+
mimeType,
|
|
155
|
+
originalFilename: params.filename,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
logger.warn({ absPath: params.absPath, err: toErrMsg(err) }, "deliverable asset: dashboard ingest failed");
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
let sizeBytes;
|
|
164
|
+
try {
|
|
165
|
+
sizeBytes = (await stat(params.absPath)).size;
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
logger.warn({ absPath: params.absPath, err: toErrMsg(err) }, "deliverable asset: file missing — omitted");
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
id: params.absPath,
|
|
173
|
+
path: params.absPath,
|
|
174
|
+
originalFilename: params.filename,
|
|
175
|
+
mimeType,
|
|
176
|
+
sizeBytes,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
@@ -43,7 +43,7 @@ interface DelegatedSyncRuntimeConfig {
|
|
|
43
43
|
/**
|
|
44
44
|
* Shared active-hours window applied to every cadence. Local-time hours
|
|
45
45
|
* in the daemon's `timezone`; `[startHour, endHour)`. When unset, defaults
|
|
46
|
-
* to `[4, 24)` to mirror the
|
|
46
|
+
* to `[4, 24)` to mirror the Activity Scan window.
|
|
47
47
|
*/
|
|
48
48
|
activeStartHour?: number;
|
|
49
49
|
activeEndHour?: number;
|
|
@@ -287,11 +287,11 @@ export declare class DelegatedSyncWorker implements Observer {
|
|
|
287
287
|
* Native rows are skipped by `backendForCadence` returning null — their
|
|
288
288
|
* observations come from the in-turn `routine.fetch_window` pre-pass
|
|
289
289
|
* instead, see `docs/design/appendices/native-integration-mode.md`
|
|
290
|
-
* §"Polling, observers, and the
|
|
290
|
+
* §"Polling, observers, and the activity-scan threshold".
|
|
291
291
|
*
|
|
292
292
|
* Why this exists: when every cadence is disabled (the post-Phase-9
|
|
293
293
|
* default), Gmail / Notion observations would otherwise dry up entirely
|
|
294
|
-
* — the delegated `routine.
|
|
294
|
+
* — the delegated `routine.activity_scan` task flow's Step 0a / 0c rely
|
|
295
295
|
* on `mail:lifecycle` / `notion:<db>` rows the worker writes server-
|
|
296
296
|
* side, and the agent prompt is explicitly told NOT to call the
|
|
297
297
|
* gmail / notion `/reconcile` route directly (would poison the worker's
|
|
@@ -300,7 +300,7 @@ export declare class DelegatedSyncWorker implements Observer {
|
|
|
300
300
|
* opted into a per-cadence schedule.
|
|
301
301
|
*
|
|
302
302
|
* Active-hours are NOT consulted: this method runs only because the
|
|
303
|
-
*
|
|
303
|
+
* activity scan itself fired, which already passed `activityScanActive*`
|
|
304
304
|
* gating. The cadence-side `activeStartHour` / `activeEndHour` window
|
|
305
305
|
* applies only to the worker's own 60 s tick.
|
|
306
306
|
*
|
|
@@ -313,7 +313,7 @@ export declare class DelegatedSyncWorker implements Observer {
|
|
|
313
313
|
* circuit-breaker) and surfaced through the next `getStatus()` snapshot;
|
|
314
314
|
* this method does not throw.
|
|
315
315
|
*/
|
|
316
|
-
|
|
316
|
+
runDisabledCadencesForActivityScan(): Promise<void>;
|
|
317
317
|
/**
|
|
318
318
|
* Run a single cadence on demand (dashboard "Run Now" button). Bypasses
|
|
319
319
|
* `cadenceEnabled`, `cadenceDue`, and active-hours gating — the user
|
|
@@ -410,7 +410,7 @@ export declare function resolveActiveHours(runtimeConfig: DelegatedSyncRuntimeCo
|
|
|
410
410
|
/**
|
|
411
411
|
* `true` when `now` falls inside `[startHour, endHour)` in the daemon's
|
|
412
412
|
* configured timezone. `endHour=24` is exclusive — i.e. covers up to
|
|
413
|
-
* 23:59:59. Mirrors the semantics of
|
|
413
|
+
* 23:59:59. Mirrors the semantics of Activity Scan's window so an operator
|
|
414
414
|
* who already understands one understands the other.
|
|
415
415
|
*/
|
|
416
416
|
export declare function isWithinActiveHours(now: Date, timezone: string | undefined, activeHours: DelegatedSyncActiveHours): boolean;
|
|
@@ -15,7 +15,7 @@ const CIRCUIT_FAILURE_THRESHOLD = 5;
|
|
|
15
15
|
const CIRCUIT_BACKOFF_MULTIPLIER = 4;
|
|
16
16
|
/**
|
|
17
17
|
* Default active-hours window for delegated-sync cadences. Mirrors Hourly
|
|
18
|
-
* Check defaults (`
|
|
18
|
+
* Check defaults (`activityScanActiveStartHour=4`, `activityScanActiveEndHour=24`)
|
|
19
19
|
* so the two schedules align unless an operator overrides one or the other.
|
|
20
20
|
* See `docs/design/appendices/delegated-sync-opt-in.md`.
|
|
21
21
|
*
|
|
@@ -126,7 +126,7 @@ const CALENDAR_24H_CADENCE = {
|
|
|
126
126
|
* - Window is the last 7 days. Reconcile keys by `(integration,
|
|
127
127
|
* window_key)` so the partition is wide enough that a recent thread
|
|
128
128
|
* with a fresh reply doesn't drop out and falsely emit `deleted`. The
|
|
129
|
-
* LLM
|
|
129
|
+
* LLM activity scan still post-filters to "last hour" inside its own
|
|
130
130
|
* decision flow; this cadence's job is structural diff, not selection.
|
|
131
131
|
* - `query="newer_than:7d"` Gmail search operator. `pageSize` /
|
|
132
132
|
* `max_results` / `maxResults` differs by backend (Claude / Codex /
|
|
@@ -136,7 +136,7 @@ const GMAIL_INBOX_7D_CADENCE = {
|
|
|
136
136
|
integration: "gmail",
|
|
137
137
|
windowKey: "inbox:7d",
|
|
138
138
|
displayName: "Gmail — inbox (last 7 days)",
|
|
139
|
-
description: "Polls thread-level changes in the last 7 days of inbox. Surfaces new threads and replies for the
|
|
139
|
+
description: "Polls thread-level changes in the last 7 days of inbox. Surfaces new threads and replies for the activity scan.",
|
|
140
140
|
defaultIntervalSeconds: 30 * 60,
|
|
141
141
|
softFloorSeconds: 15 * 60,
|
|
142
142
|
maxResults: 25,
|
|
@@ -159,7 +159,7 @@ const GMAIL_INBOX_7D_CADENCE = {
|
|
|
159
159
|
* and lets reconcile + the per-page `lastEditedTime` payload + the
|
|
160
160
|
* Notion normalizer's `inWindow` predicate sort out true churn.
|
|
161
161
|
* - The window's `created_date_range.start_date` arg is per the same
|
|
162
|
-
* date format the
|
|
162
|
+
* date format the activity_scan prompt uses (`YYYY-MM-DD`), to mirror
|
|
163
163
|
* what the LLM-driven path was already producing — connectors uniformly
|
|
164
164
|
* accept that.
|
|
165
165
|
*/
|
|
@@ -387,11 +387,11 @@ export class DelegatedSyncWorker {
|
|
|
387
387
|
* Native rows are skipped by `backendForCadence` returning null — their
|
|
388
388
|
* observations come from the in-turn `routine.fetch_window` pre-pass
|
|
389
389
|
* instead, see `docs/design/appendices/native-integration-mode.md`
|
|
390
|
-
* §"Polling, observers, and the
|
|
390
|
+
* §"Polling, observers, and the activity-scan threshold".
|
|
391
391
|
*
|
|
392
392
|
* Why this exists: when every cadence is disabled (the post-Phase-9
|
|
393
393
|
* default), Gmail / Notion observations would otherwise dry up entirely
|
|
394
|
-
* — the delegated `routine.
|
|
394
|
+
* — the delegated `routine.activity_scan` task flow's Step 0a / 0c rely
|
|
395
395
|
* on `mail:lifecycle` / `notion:<db>` rows the worker writes server-
|
|
396
396
|
* side, and the agent prompt is explicitly told NOT to call the
|
|
397
397
|
* gmail / notion `/reconcile` route directly (would poison the worker's
|
|
@@ -400,7 +400,7 @@ export class DelegatedSyncWorker {
|
|
|
400
400
|
* opted into a per-cadence schedule.
|
|
401
401
|
*
|
|
402
402
|
* Active-hours are NOT consulted: this method runs only because the
|
|
403
|
-
*
|
|
403
|
+
* activity scan itself fired, which already passed `activityScanActive*`
|
|
404
404
|
* gating. The cadence-side `activeStartHour` / `activeEndHour` window
|
|
405
405
|
* applies only to the worker's own 60 s tick.
|
|
406
406
|
*
|
|
@@ -413,9 +413,9 @@ export class DelegatedSyncWorker {
|
|
|
413
413
|
* circuit-breaker) and surfaced through the next `getStatus()` snapshot;
|
|
414
414
|
* this method does not throw.
|
|
415
415
|
*/
|
|
416
|
-
async
|
|
416
|
+
async runDisabledCadencesForActivityScan() {
|
|
417
417
|
if (this.tickRunning) {
|
|
418
|
-
logger.debug("Skipping
|
|
418
|
+
logger.debug("Skipping activity-scan delegated refresh — worker tick already in flight");
|
|
419
419
|
return;
|
|
420
420
|
}
|
|
421
421
|
this.tickRunning = true;
|
|
@@ -923,7 +923,7 @@ export function resolveActiveHours(runtimeConfig) {
|
|
|
923
923
|
/**
|
|
924
924
|
* `true` when `now` falls inside `[startHour, endHour)` in the daemon's
|
|
925
925
|
* configured timezone. `endHour=24` is exclusive — i.e. covers up to
|
|
926
|
-
* 23:59:59. Mirrors the semantics of
|
|
926
|
+
* 23:59:59. Mirrors the semantics of Activity Scan's window so an operator
|
|
927
927
|
* who already understands one understands the other.
|
|
928
928
|
*/
|
|
929
929
|
export function isWithinActiveHours(now, timezone, activeHours) {
|
|
@@ -11,7 +11,7 @@ interface GitDelegatedCronOptions {
|
|
|
11
11
|
githubRepos: readonly string[];
|
|
12
12
|
cadenceSeconds: number;
|
|
13
13
|
pushOverdueMinutes: number;
|
|
14
|
-
|
|
14
|
+
activityScanEnabled?: boolean;
|
|
15
15
|
now?: () => Date;
|
|
16
16
|
}
|
|
17
17
|
export declare function hasActiveDelegatedGitLifecycleIntegration(db: Database.Database, override?: {
|
|
@@ -81,10 +81,10 @@ export class GitDelegatedCronObserver {
|
|
|
81
81
|
this.timer.unref?.();
|
|
82
82
|
}
|
|
83
83
|
initialDelaySeconds() {
|
|
84
|
-
// Keep 1h delegated Git checks away from routine.
|
|
84
|
+
// Keep 1h delegated Git checks away from routine.activity_scan. This is
|
|
85
85
|
// the collision-avoidance rule from the Git lifecycle design: no session
|
|
86
86
|
// reuse, just a 30-minute offset to avoid light-tier concurrency spikes.
|
|
87
|
-
if (this.options.
|
|
87
|
+
if (this.options.activityScanEnabled && this.cadenceSeconds === 3600) {
|
|
88
88
|
return 30 * 60;
|
|
89
89
|
}
|
|
90
90
|
return this.cadenceSeconds;
|
|
@@ -48,7 +48,7 @@ export type Classification = {
|
|
|
48
48
|
/**
|
|
49
49
|
* When `true`, the orchestrator emits to EventBus in addition to
|
|
50
50
|
* recording the observation. Reserved for HIGH-priority signals that
|
|
51
|
-
* should DM the user without waiting for the
|
|
51
|
+
* should DM the user without waiting for the activity scan.
|
|
52
52
|
*/
|
|
53
53
|
emitEvent: boolean;
|
|
54
54
|
};
|
|
@@ -57,8 +57,8 @@ export type Classification = {
|
|
|
57
57
|
* emit-to-EventBus) per the agent's "patterns not events" philosophy.
|
|
58
58
|
*
|
|
59
59
|
* - `review_requested` / `assign` / `security_alert` are HIGH and bypass
|
|
60
|
-
*
|
|
61
|
-
* - `mention` / `team_mention` are NORMAL — coalesced in
|
|
60
|
+
* activity_scan via direct DM.
|
|
61
|
+
* - `mention` / `team_mention` are NORMAL — coalesced in activity_scan.
|
|
62
62
|
* - `subscribed` / `manual` / `comment` / `state_change` etc. are LOW
|
|
63
63
|
* noise; recorded as observations only so the agent can surface them
|
|
64
64
|
* if a pattern emerges.
|
|
@@ -4,8 +4,8 @@ import { EventPriority } from "@aitne/shared";
|
|
|
4
4
|
* emit-to-EventBus) per the agent's "patterns not events" philosophy.
|
|
5
5
|
*
|
|
6
6
|
* - `review_requested` / `assign` / `security_alert` are HIGH and bypass
|
|
7
|
-
*
|
|
8
|
-
* - `mention` / `team_mention` are NORMAL — coalesced in
|
|
7
|
+
* activity_scan via direct DM.
|
|
8
|
+
* - `mention` / `team_mention` are NORMAL — coalesced in activity_scan.
|
|
9
9
|
* - `subscribed` / `manual` / `comment` / `state_change` etc. are LOW
|
|
10
10
|
* noise; recorded as observations only so the agent can surface them
|
|
11
11
|
* if a pattern emerges.
|
|
@@ -145,7 +145,7 @@ export function classifyWorkflowRun(run, defaultBranch, repoFullName) {
|
|
|
145
145
|
ref,
|
|
146
146
|
payload,
|
|
147
147
|
// Only DM-grade for default-branch failures. Feature-branch failures
|
|
148
|
-
// are noise during normal development and only surface via
|
|
148
|
+
// are noise during normal development and only surface via activity_scan.
|
|
149
149
|
emitEvent: onDefaultBranch,
|
|
150
150
|
};
|
|
151
151
|
}
|
|
@@ -17,7 +17,7 @@ import type { Observer } from "./manager.js";
|
|
|
17
17
|
* by design (`INTEGRATION_SNAPSHOT_PARTITIONS_BY_MODE[google_calendar].native = []`);
|
|
18
18
|
* without this second source, native-mode users would silently lose
|
|
19
19
|
* every 15-minute reminder. Cadence note: native observations refresh
|
|
20
|
-
* on the
|
|
20
|
+
* on the activity_scan tick (60-min cadence) so events scheduled with
|
|
21
21
|
* less than ~60 min lead-time may miss their reminder. The 5-min
|
|
22
22
|
* direct-mode polling cadence does not have this limit.
|
|
23
23
|
*
|
|
@@ -38,7 +38,7 @@ function extractCalendarPayload(parsed) {
|
|
|
38
38
|
* by design (`INTEGRATION_SNAPSHOT_PARTITIONS_BY_MODE[google_calendar].native = []`);
|
|
39
39
|
* without this second source, native-mode users would silently lose
|
|
40
40
|
* every 15-minute reminder. Cadence note: native observations refresh
|
|
41
|
-
* on the
|
|
41
|
+
* on the activity_scan tick (60-min cadence) so events scheduled with
|
|
42
42
|
* less than ~60 min lead-time may miss their reminder. The 5-min
|
|
43
43
|
* direct-mode polling cadence does not have this limit.
|
|
44
44
|
*
|
|
@@ -98,6 +98,7 @@ export declare class MailPoller implements Observer {
|
|
|
98
98
|
private isAccountManagedExternally;
|
|
99
99
|
private stopIdleForInactiveAccounts;
|
|
100
100
|
private ensureIdle;
|
|
101
|
+
private startIdleForAccount;
|
|
101
102
|
private softDeleteByProviderMsgId;
|
|
102
103
|
/**
|
|
103
104
|
* Upsert poller-observed messages into `mail_messages_index`.
|