aiden-runtime 4.1.5 → 4.5.0
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/README.md +250 -847
- package/dist/api/server.js +32 -5
- package/dist/cli/v4/aidenCLI.js +351 -53
- package/dist/cli/v4/callbacks.js +170 -0
- package/dist/cli/v4/chatSession.js +138 -3
- package/dist/cli/v4/commands/_runtimeToggleHelpers.js +92 -0
- package/dist/cli/v4/commands/browserDepth.js +45 -0
- package/dist/cli/v4/commands/cron.js +264 -0
- package/dist/cli/v4/commands/daemon.js +541 -0
- package/dist/cli/v4/commands/daemonStatus.js +253 -0
- package/dist/cli/v4/commands/help.js +7 -0
- package/dist/cli/v4/commands/index.js +20 -1
- package/dist/cli/v4/commands/runs.js +203 -0
- package/dist/cli/v4/commands/sandbox.js +48 -0
- package/dist/cli/v4/commands/suggestions.js +68 -0
- package/dist/cli/v4/commands/tce.js +41 -0
- package/dist/cli/v4/commands/trigger.js +378 -0
- package/dist/cli/v4/commands/update.js +95 -3
- package/dist/cli/v4/daemonAgentBuilder.js +142 -0
- package/dist/cli/v4/defaultSoul.js +1 -1
- package/dist/cli/v4/display/capabilityCard.js +26 -0
- package/dist/cli/v4/display.js +18 -8
- package/dist/cli/v4/replyRenderer.js +31 -23
- package/dist/cli/v4/updateBootPrompt.js +170 -0
- package/dist/core/playwrightBridge.js +129 -0
- package/dist/core/v4/aidenAgent.js +308 -4
- package/dist/core/v4/browserState.js +436 -0
- package/dist/core/v4/checkpoint.js +79 -0
- package/dist/core/v4/daemon/bootstrap.js +604 -0
- package/dist/core/v4/daemon/cleanShutdown.js +154 -0
- package/dist/core/v4/daemon/cron/cronBridge.js +126 -0
- package/dist/core/v4/daemon/cron/cronEmitter.js +173 -0
- package/dist/core/v4/daemon/cron/migration.js +199 -0
- package/dist/core/v4/daemon/cron/misfirePolicy.js +115 -0
- package/dist/core/v4/daemon/daemonConfig.js +90 -0
- package/dist/core/v4/daemon/db/connection.js +106 -0
- package/dist/core/v4/daemon/db/migrations.js +296 -0
- package/dist/core/v4/daemon/db/schema/v1.spec.js +18 -0
- package/dist/core/v4/daemon/dispatcher/agentRunner.js +98 -0
- package/dist/core/v4/daemon/dispatcher/budgetGate.js +127 -0
- package/dist/core/v4/daemon/dispatcher/daemonApproval.js +113 -0
- package/dist/core/v4/daemon/dispatcher/dailyBudgetTracker.js +120 -0
- package/dist/core/v4/daemon/dispatcher/dispatcher.js +389 -0
- package/dist/core/v4/daemon/dispatcher/fireRateLimiter.js +113 -0
- package/dist/core/v4/daemon/dispatcher/index.js +53 -0
- package/dist/core/v4/daemon/dispatcher/promptTemplate.js +95 -0
- package/dist/core/v4/daemon/dispatcher/realAgentRunner.js +356 -0
- package/dist/core/v4/daemon/dispatcher/resolveModel.js +93 -0
- package/dist/core/v4/daemon/dispatcher/sessionId.js +93 -0
- package/dist/core/v4/daemon/drain.js +156 -0
- package/dist/core/v4/daemon/eventLoopLag.js +73 -0
- package/dist/core/v4/daemon/health.js +159 -0
- package/dist/core/v4/daemon/idempotencyStore.js +204 -0
- package/dist/core/v4/daemon/index.js +179 -0
- package/dist/core/v4/daemon/instanceTracker.js +99 -0
- package/dist/core/v4/daemon/resourceRegistry.js +150 -0
- package/dist/core/v4/daemon/restartCode.js +32 -0
- package/dist/core/v4/daemon/restartFailureCounter.js +77 -0
- package/dist/core/v4/daemon/runStore.js +114 -0
- package/dist/core/v4/daemon/runtimeLock.js +167 -0
- package/dist/core/v4/daemon/signals.js +50 -0
- package/dist/core/v4/daemon/supervisor.js +272 -0
- package/dist/core/v4/daemon/triggerBus.js +279 -0
- package/dist/core/v4/daemon/triggers/email/allowlist.js +70 -0
- package/dist/core/v4/daemon/triggers/email/automatedSender.js +78 -0
- package/dist/core/v4/daemon/triggers/email/bodyExtractor.js +0 -0
- package/dist/core/v4/daemon/triggers/email/emailSeenStore.js +99 -0
- package/dist/core/v4/daemon/triggers/email/emailSpec.js +107 -0
- package/dist/core/v4/daemon/triggers/email/imapConnection.js +211 -0
- package/dist/core/v4/daemon/triggers/email/index.js +332 -0
- package/dist/core/v4/daemon/triggers/email/seenUids.js +60 -0
- package/dist/core/v4/daemon/triggers/fileObservationsStore.js +93 -0
- package/dist/core/v4/daemon/triggers/fileWatcher.js +253 -0
- package/dist/core/v4/daemon/triggers/fileWatcherSpec.js +88 -0
- package/dist/core/v4/daemon/triggers/fsIdentity.js +42 -0
- package/dist/core/v4/daemon/triggers/globMatcher.js +100 -0
- package/dist/core/v4/daemon/triggers/reconcile.js +206 -0
- package/dist/core/v4/daemon/triggers/settleStat.js +81 -0
- package/dist/core/v4/daemon/triggers/webhook.js +376 -0
- package/dist/core/v4/daemon/triggers/webhookDeliveriesStore.js +109 -0
- package/dist/core/v4/daemon/triggers/webhookIdempotency.js +72 -0
- package/dist/core/v4/daemon/triggers/webhookRateLimit.js +56 -0
- package/dist/core/v4/daemon/triggers/webhookSpec.js +76 -0
- package/dist/core/v4/daemon/triggers/webhookVerifier.js +128 -0
- package/dist/core/v4/daemon/types.js +15 -0
- package/dist/core/v4/dockerSession.js +461 -0
- package/dist/core/v4/dryRun.js +117 -0
- package/dist/core/v4/failureClassifier.js +779 -0
- package/dist/core/v4/recoveryReport.js +449 -0
- package/dist/core/v4/runtimeToggles.js +187 -0
- package/dist/core/v4/sandboxConfig.js +285 -0
- package/dist/core/v4/sandboxFs.js +316 -0
- package/dist/core/v4/suggestionCatalog.js +41 -0
- package/dist/core/v4/suggestionEngine.js +210 -0
- package/dist/core/v4/toolRegistry.js +18 -0
- package/dist/core/v4/turnState.js +587 -0
- package/dist/core/v4/update/checkUpdate.js +63 -3
- package/dist/core/v4/update/installMethodDetect.js +115 -0
- package/dist/core/v4/update/registryClient.js +121 -0
- package/dist/core/v4/update/skipState.js +75 -0
- package/dist/core/v4/verifier.js +448 -0
- package/dist/core/version.js +1 -1
- package/dist/tools/v4/browser/_observer.js +224 -0
- package/dist/tools/v4/browser/browserBlocker.js +396 -0
- package/dist/tools/v4/browser/browserClick.js +18 -1
- package/dist/tools/v4/browser/browserClose.js +18 -1
- package/dist/tools/v4/browser/browserExtract.js +5 -1
- package/dist/tools/v4/browser/browserFill.js +17 -1
- package/dist/tools/v4/browser/browserGetUrl.js +5 -1
- package/dist/tools/v4/browser/browserNavigate.js +16 -1
- package/dist/tools/v4/browser/browserScreenshot.js +5 -1
- package/dist/tools/v4/browser/browserScroll.js +18 -1
- package/dist/tools/v4/browser/browserType.js +17 -1
- package/dist/tools/v4/browser/captchaCheck.js +5 -1
- package/dist/tools/v4/executeCode.js +1 -0
- package/dist/tools/v4/files/fileCopy.js +56 -2
- package/dist/tools/v4/files/fileDelete.js +38 -1
- package/dist/tools/v4/files/fileList.js +12 -1
- package/dist/tools/v4/files/fileMove.js +59 -2
- package/dist/tools/v4/files/filePatch.js +43 -1
- package/dist/tools/v4/files/fileRead.js +12 -1
- package/dist/tools/v4/files/fileWrite.js +41 -1
- package/dist/tools/v4/index.js +71 -58
- package/dist/tools/v4/memory/memoryAdd.js +14 -0
- package/dist/tools/v4/memory/memoryRemove.js +14 -0
- package/dist/tools/v4/memory/memoryReplace.js +15 -0
- package/dist/tools/v4/memory/sessionSummary.js +12 -0
- package/dist/tools/v4/process/processKill.js +19 -0
- package/dist/tools/v4/process/processList.js +1 -0
- package/dist/tools/v4/process/processLogRead.js +1 -0
- package/dist/tools/v4/process/processSpawn.js +13 -0
- package/dist/tools/v4/process/processWait.js +1 -0
- package/dist/tools/v4/sessions/recallSession.js +1 -0
- package/dist/tools/v4/sessions/sessionList.js +1 -0
- package/dist/tools/v4/sessions/sessionSearch.js +1 -0
- package/dist/tools/v4/skills/lookupToolSchema.js +2 -0
- package/dist/tools/v4/skills/skillManage.js +13 -0
- package/dist/tools/v4/skills/skillView.js +1 -0
- package/dist/tools/v4/skills/skillsList.js +1 -0
- package/dist/tools/v4/subagent/subagentFanout.js +1 -0
- package/dist/tools/v4/system/aidenSelfUpdate.js +16 -0
- package/dist/tools/v4/system/appClose.js +13 -0
- package/dist/tools/v4/system/appInput.js +13 -0
- package/dist/tools/v4/system/appLaunch.js +13 -0
- package/dist/tools/v4/system/clipboardRead.js +1 -0
- package/dist/tools/v4/system/clipboardWrite.js +14 -0
- package/dist/tools/v4/system/mediaKey.js +12 -0
- package/dist/tools/v4/system/mediaSessions.js +1 -0
- package/dist/tools/v4/system/mediaTransport.js +13 -0
- package/dist/tools/v4/system/naturalEvents.js +1 -0
- package/dist/tools/v4/system/nowPlaying.js +1 -0
- package/dist/tools/v4/system/osProcessList.js +1 -0
- package/dist/tools/v4/system/screenshot.js +1 -0
- package/dist/tools/v4/system/systemInfo.js +1 -0
- package/dist/tools/v4/system/volumeSet.js +17 -0
- package/dist/tools/v4/terminal/shellExec.js +81 -9
- package/dist/tools/v4/web/deepResearch.js +1 -0
- package/dist/tools/v4/web/openUrl.js +1 -0
- package/dist/tools/v4/web/webFetch.js +1 -0
- package/dist/tools/v4/web/webPage.js +1 -0
- package/dist/tools/v4/web/webSearch.js +1 -0
- package/dist/tools/v4/web/youtubeSearch.js +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* core/v4/daemon/index.ts — v4.5 Phase 1: barrel exports for the
|
|
10
|
+
* daemon foundation.
|
|
11
|
+
*
|
|
12
|
+
* Phase 1 ships the foundation; Phases 2-6 add file watcher,
|
|
13
|
+
* webhook, email, scheduler-migration, integration, default-on.
|
|
14
|
+
*
|
|
15
|
+
* Public surface (re-exported here so callers do
|
|
16
|
+
* `import { ... } from '@/core/v4/daemon'` instead of subpath
|
|
17
|
+
* imports for the common operations):
|
|
18
|
+
*
|
|
19
|
+
* - configuration + paths
|
|
20
|
+
* - SQLite handle + migrations
|
|
21
|
+
* - runtime lock + instance tracker
|
|
22
|
+
* - clean-shutdown marker + restart-failure counter
|
|
23
|
+
* - trigger bus + idempotency store + run store
|
|
24
|
+
* - resource registry
|
|
25
|
+
* - supervisor + service template generators
|
|
26
|
+
* - drain + signal handlers
|
|
27
|
+
* - health + metrics endpoint mounter
|
|
28
|
+
* - event loop lag sampler
|
|
29
|
+
*
|
|
30
|
+
* Side-effect imports (modules that install global state) are NOT
|
|
31
|
+
* re-exported here — those must be invoked explicitly during
|
|
32
|
+
* daemon boot.
|
|
33
|
+
*/
|
|
34
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
35
|
+
if (k2 === undefined) k2 = k;
|
|
36
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
37
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
38
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
39
|
+
}
|
|
40
|
+
Object.defineProperty(o, k2, desc);
|
|
41
|
+
}) : (function(o, m, k, k2) {
|
|
42
|
+
if (k2 === undefined) k2 = k;
|
|
43
|
+
o[k2] = m[k];
|
|
44
|
+
}));
|
|
45
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
46
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.reconcileFileWatcher = exports.createFileObservationsStore = exports.DEFAULT_FILE_WATCHER_SPEC = exports.parseFileWatcherSpec = exports.createFileWatcher = exports._resetDaemonBootstrapForTests = exports.getDaemonHandle = exports.bootstrapDaemon = exports._resetDaemonSignalHandlersForTests = exports.installDaemonSignalHandlers = exports._resetDrainStateForTests = exports.isDraining = exports.signalToReason = exports.performDrain = exports.windowsServiceGuidance = exports.generateLaunchdPlist = exports.generateSystemdUnit = exports.startSupervisor = exports._resetResourceRegistryForTests = exports.createResourceRegistry = exports.getResourceRegistry = exports.createRunStore = exports.IDEMPOTENCY_DEFAULT_TTL_MS = exports.createIdempotencyStore = exports.DEFAULT_MAX_ATTEMPTS = exports.DEFAULT_CLAIM_LEASE_MS = exports.createTriggerBus = exports.DEFAULT_STUCK_LOOP_THRESHOLD = exports.createRestartFailureCounter = exports.evaluateBootState = exports.consumeCleanShutdownMarker = exports.isCleanShutdown = exports.touchCleanShutdownMarker = exports.createInstanceTracker = exports.DaemonAlreadyRunningError = exports.acquireRuntimeLock = exports.LATEST_SCHEMA_VERSION = exports.runMigrations = exports._closeAllDaemonDbsForTests = exports.closeDaemonDb = exports.openDaemonDb = exports._resetDaemonConfigForTests = exports.getHostname = exports.daemonCleanShutdownMarkerPath = exports.daemonRuntimeLockPath = exports.daemonDbPath = exports.daemonDir = exports.readDaemonConfig = exports.getDaemonConfig = exports.DAEMON_RESTART_EXIT_CODE = void 0;
|
|
50
|
+
exports.evaluateDegraded = exports.mountHealthEndpoints = exports.isEventLoopResponsive = exports.getLastTickAt = exports.getEventLoopLagMs = exports.stopEventLoopLagSampler = exports.startEventLoopLagSampler = exports.BACKOFF_CONSTANTS = exports.nextBackoffMs = exports.createImapConnection = exports.extractEmailBody = exports.createEmailSeenStore = exports.DEFAULT_MAX_SEEN_UIDS = exports.createSeenUids = exports.compileSenderAllowlist = exports.AUTOMATED_HEADERS = exports.NOREPLY_PATTERNS = exports.isAutomatedSender = exports.DEFAULT_IMAP = exports.DEFAULT_EMAIL_SPEC = exports.parseEmailSpec = exports.createEmailTrigger = exports.createWebhookDeliveriesStore = exports.deriveIdempotencyKey = exports.createRateLimiter = exports.deriveEventName = exports.verifyWebhookSignature = exports.INSECURE_NO_AUTH = exports.DEFAULT_WEBHOOK_SPEC = exports.parseWebhookSpec = exports.assertSafeBind = exports.mountWebhookRoutes = exports.computeFileKey = exports.settleStat = exports.DEFAULT_IGNORE_PATTERNS = exports.compileGlobMatcher = void 0;
|
|
51
|
+
var restartCode_1 = require("./restartCode");
|
|
52
|
+
Object.defineProperty(exports, "DAEMON_RESTART_EXIT_CODE", { enumerable: true, get: function () { return restartCode_1.DAEMON_RESTART_EXIT_CODE; } });
|
|
53
|
+
var daemonConfig_1 = require("./daemonConfig");
|
|
54
|
+
Object.defineProperty(exports, "getDaemonConfig", { enumerable: true, get: function () { return daemonConfig_1.getDaemonConfig; } });
|
|
55
|
+
Object.defineProperty(exports, "readDaemonConfig", { enumerable: true, get: function () { return daemonConfig_1.readDaemonConfig; } });
|
|
56
|
+
Object.defineProperty(exports, "daemonDir", { enumerable: true, get: function () { return daemonConfig_1.daemonDir; } });
|
|
57
|
+
Object.defineProperty(exports, "daemonDbPath", { enumerable: true, get: function () { return daemonConfig_1.daemonDbPath; } });
|
|
58
|
+
Object.defineProperty(exports, "daemonRuntimeLockPath", { enumerable: true, get: function () { return daemonConfig_1.daemonRuntimeLockPath; } });
|
|
59
|
+
Object.defineProperty(exports, "daemonCleanShutdownMarkerPath", { enumerable: true, get: function () { return daemonConfig_1.daemonCleanShutdownMarkerPath; } });
|
|
60
|
+
Object.defineProperty(exports, "getHostname", { enumerable: true, get: function () { return daemonConfig_1.getHostname; } });
|
|
61
|
+
Object.defineProperty(exports, "_resetDaemonConfigForTests", { enumerable: true, get: function () { return daemonConfig_1._resetDaemonConfigForTests; } });
|
|
62
|
+
__exportStar(require("./types"), exports);
|
|
63
|
+
var connection_1 = require("./db/connection");
|
|
64
|
+
Object.defineProperty(exports, "openDaemonDb", { enumerable: true, get: function () { return connection_1.openDaemonDb; } });
|
|
65
|
+
Object.defineProperty(exports, "closeDaemonDb", { enumerable: true, get: function () { return connection_1.closeDaemonDb; } });
|
|
66
|
+
Object.defineProperty(exports, "_closeAllDaemonDbsForTests", { enumerable: true, get: function () { return connection_1._closeAllDaemonDbsForTests; } });
|
|
67
|
+
var migrations_1 = require("./db/migrations");
|
|
68
|
+
Object.defineProperty(exports, "runMigrations", { enumerable: true, get: function () { return migrations_1.runMigrations; } });
|
|
69
|
+
Object.defineProperty(exports, "LATEST_SCHEMA_VERSION", { enumerable: true, get: function () { return migrations_1.LATEST_SCHEMA_VERSION; } });
|
|
70
|
+
var runtimeLock_1 = require("./runtimeLock");
|
|
71
|
+
Object.defineProperty(exports, "acquireRuntimeLock", { enumerable: true, get: function () { return runtimeLock_1.acquireRuntimeLock; } });
|
|
72
|
+
Object.defineProperty(exports, "DaemonAlreadyRunningError", { enumerable: true, get: function () { return runtimeLock_1.DaemonAlreadyRunningError; } });
|
|
73
|
+
var instanceTracker_1 = require("./instanceTracker");
|
|
74
|
+
Object.defineProperty(exports, "createInstanceTracker", { enumerable: true, get: function () { return instanceTracker_1.createInstanceTracker; } });
|
|
75
|
+
var cleanShutdown_1 = require("./cleanShutdown");
|
|
76
|
+
Object.defineProperty(exports, "touchCleanShutdownMarker", { enumerable: true, get: function () { return cleanShutdown_1.touchCleanShutdownMarker; } });
|
|
77
|
+
Object.defineProperty(exports, "isCleanShutdown", { enumerable: true, get: function () { return cleanShutdown_1.isCleanShutdown; } });
|
|
78
|
+
Object.defineProperty(exports, "consumeCleanShutdownMarker", { enumerable: true, get: function () { return cleanShutdown_1.consumeCleanShutdownMarker; } });
|
|
79
|
+
Object.defineProperty(exports, "evaluateBootState", { enumerable: true, get: function () { return cleanShutdown_1.evaluateBootState; } });
|
|
80
|
+
var restartFailureCounter_1 = require("./restartFailureCounter");
|
|
81
|
+
Object.defineProperty(exports, "createRestartFailureCounter", { enumerable: true, get: function () { return restartFailureCounter_1.createRestartFailureCounter; } });
|
|
82
|
+
Object.defineProperty(exports, "DEFAULT_STUCK_LOOP_THRESHOLD", { enumerable: true, get: function () { return restartFailureCounter_1.DEFAULT_STUCK_LOOP_THRESHOLD; } });
|
|
83
|
+
var triggerBus_1 = require("./triggerBus");
|
|
84
|
+
Object.defineProperty(exports, "createTriggerBus", { enumerable: true, get: function () { return triggerBus_1.createTriggerBus; } });
|
|
85
|
+
Object.defineProperty(exports, "DEFAULT_CLAIM_LEASE_MS", { enumerable: true, get: function () { return triggerBus_1.DEFAULT_CLAIM_LEASE_MS; } });
|
|
86
|
+
Object.defineProperty(exports, "DEFAULT_MAX_ATTEMPTS", { enumerable: true, get: function () { return triggerBus_1.DEFAULT_MAX_ATTEMPTS; } });
|
|
87
|
+
var idempotencyStore_1 = require("./idempotencyStore");
|
|
88
|
+
Object.defineProperty(exports, "createIdempotencyStore", { enumerable: true, get: function () { return idempotencyStore_1.createIdempotencyStore; } });
|
|
89
|
+
Object.defineProperty(exports, "IDEMPOTENCY_DEFAULT_TTL_MS", { enumerable: true, get: function () { return idempotencyStore_1.DEFAULT_TTL_MS; } });
|
|
90
|
+
var runStore_1 = require("./runStore");
|
|
91
|
+
Object.defineProperty(exports, "createRunStore", { enumerable: true, get: function () { return runStore_1.createRunStore; } });
|
|
92
|
+
var resourceRegistry_1 = require("./resourceRegistry");
|
|
93
|
+
Object.defineProperty(exports, "getResourceRegistry", { enumerable: true, get: function () { return resourceRegistry_1.getResourceRegistry; } });
|
|
94
|
+
Object.defineProperty(exports, "createResourceRegistry", { enumerable: true, get: function () { return resourceRegistry_1.createResourceRegistry; } });
|
|
95
|
+
Object.defineProperty(exports, "_resetResourceRegistryForTests", { enumerable: true, get: function () { return resourceRegistry_1._resetResourceRegistryForTests; } });
|
|
96
|
+
var supervisor_1 = require("./supervisor");
|
|
97
|
+
Object.defineProperty(exports, "startSupervisor", { enumerable: true, get: function () { return supervisor_1.startSupervisor; } });
|
|
98
|
+
Object.defineProperty(exports, "generateSystemdUnit", { enumerable: true, get: function () { return supervisor_1.generateSystemdUnit; } });
|
|
99
|
+
Object.defineProperty(exports, "generateLaunchdPlist", { enumerable: true, get: function () { return supervisor_1.generateLaunchdPlist; } });
|
|
100
|
+
Object.defineProperty(exports, "windowsServiceGuidance", { enumerable: true, get: function () { return supervisor_1.windowsServiceGuidance; } });
|
|
101
|
+
var drain_1 = require("./drain");
|
|
102
|
+
Object.defineProperty(exports, "performDrain", { enumerable: true, get: function () { return drain_1.performDrain; } });
|
|
103
|
+
Object.defineProperty(exports, "signalToReason", { enumerable: true, get: function () { return drain_1.signalToReason; } });
|
|
104
|
+
Object.defineProperty(exports, "isDraining", { enumerable: true, get: function () { return drain_1.isDraining; } });
|
|
105
|
+
Object.defineProperty(exports, "_resetDrainStateForTests", { enumerable: true, get: function () { return drain_1._resetDrainStateForTests; } });
|
|
106
|
+
var signals_1 = require("./signals");
|
|
107
|
+
Object.defineProperty(exports, "installDaemonSignalHandlers", { enumerable: true, get: function () { return signals_1.installDaemonSignalHandlers; } });
|
|
108
|
+
Object.defineProperty(exports, "_resetDaemonSignalHandlersForTests", { enumerable: true, get: function () { return signals_1._resetDaemonSignalHandlersForTests; } });
|
|
109
|
+
var bootstrap_1 = require("./bootstrap");
|
|
110
|
+
Object.defineProperty(exports, "bootstrapDaemon", { enumerable: true, get: function () { return bootstrap_1.bootstrapDaemon; } });
|
|
111
|
+
Object.defineProperty(exports, "getDaemonHandle", { enumerable: true, get: function () { return bootstrap_1.getDaemonHandle; } });
|
|
112
|
+
Object.defineProperty(exports, "_resetDaemonBootstrapForTests", { enumerable: true, get: function () { return bootstrap_1._resetDaemonBootstrapForTests; } });
|
|
113
|
+
// ── v4.5 Phase 2 — file-watcher trigger ──────────────────────────────────
|
|
114
|
+
var fileWatcher_1 = require("./triggers/fileWatcher");
|
|
115
|
+
Object.defineProperty(exports, "createFileWatcher", { enumerable: true, get: function () { return fileWatcher_1.createFileWatcher; } });
|
|
116
|
+
var fileWatcherSpec_1 = require("./triggers/fileWatcherSpec");
|
|
117
|
+
Object.defineProperty(exports, "parseFileWatcherSpec", { enumerable: true, get: function () { return fileWatcherSpec_1.parseFileWatcherSpec; } });
|
|
118
|
+
Object.defineProperty(exports, "DEFAULT_FILE_WATCHER_SPEC", { enumerable: true, get: function () { return fileWatcherSpec_1.DEFAULT_FILE_WATCHER_SPEC; } });
|
|
119
|
+
var fileObservationsStore_1 = require("./triggers/fileObservationsStore");
|
|
120
|
+
Object.defineProperty(exports, "createFileObservationsStore", { enumerable: true, get: function () { return fileObservationsStore_1.createFileObservationsStore; } });
|
|
121
|
+
var reconcile_1 = require("./triggers/reconcile");
|
|
122
|
+
Object.defineProperty(exports, "reconcileFileWatcher", { enumerable: true, get: function () { return reconcile_1.reconcileFileWatcher; } });
|
|
123
|
+
var globMatcher_1 = require("./triggers/globMatcher");
|
|
124
|
+
Object.defineProperty(exports, "compileGlobMatcher", { enumerable: true, get: function () { return globMatcher_1.compileGlobMatcher; } });
|
|
125
|
+
Object.defineProperty(exports, "DEFAULT_IGNORE_PATTERNS", { enumerable: true, get: function () { return globMatcher_1.DEFAULT_IGNORE_PATTERNS; } });
|
|
126
|
+
var settleStat_1 = require("./triggers/settleStat");
|
|
127
|
+
Object.defineProperty(exports, "settleStat", { enumerable: true, get: function () { return settleStat_1.settleStat; } });
|
|
128
|
+
var fsIdentity_1 = require("./triggers/fsIdentity");
|
|
129
|
+
Object.defineProperty(exports, "computeFileKey", { enumerable: true, get: function () { return fsIdentity_1.computeFileKey; } });
|
|
130
|
+
// ── v4.5 Phase 3 — webhook trigger ───────────────────────────────────────
|
|
131
|
+
var webhook_1 = require("./triggers/webhook");
|
|
132
|
+
Object.defineProperty(exports, "mountWebhookRoutes", { enumerable: true, get: function () { return webhook_1.mountWebhookRoutes; } });
|
|
133
|
+
Object.defineProperty(exports, "assertSafeBind", { enumerable: true, get: function () { return webhook_1.assertSafeBind; } });
|
|
134
|
+
var webhookSpec_1 = require("./triggers/webhookSpec");
|
|
135
|
+
Object.defineProperty(exports, "parseWebhookSpec", { enumerable: true, get: function () { return webhookSpec_1.parseWebhookSpec; } });
|
|
136
|
+
Object.defineProperty(exports, "DEFAULT_WEBHOOK_SPEC", { enumerable: true, get: function () { return webhookSpec_1.DEFAULT_WEBHOOK_SPEC; } });
|
|
137
|
+
Object.defineProperty(exports, "INSECURE_NO_AUTH", { enumerable: true, get: function () { return webhookSpec_1.INSECURE_NO_AUTH; } });
|
|
138
|
+
var webhookVerifier_1 = require("./triggers/webhookVerifier");
|
|
139
|
+
Object.defineProperty(exports, "verifyWebhookSignature", { enumerable: true, get: function () { return webhookVerifier_1.verifyWebhookSignature; } });
|
|
140
|
+
Object.defineProperty(exports, "deriveEventName", { enumerable: true, get: function () { return webhookVerifier_1.deriveEventName; } });
|
|
141
|
+
var webhookRateLimit_1 = require("./triggers/webhookRateLimit");
|
|
142
|
+
Object.defineProperty(exports, "createRateLimiter", { enumerable: true, get: function () { return webhookRateLimit_1.createRateLimiter; } });
|
|
143
|
+
var webhookIdempotency_1 = require("./triggers/webhookIdempotency");
|
|
144
|
+
Object.defineProperty(exports, "deriveIdempotencyKey", { enumerable: true, get: function () { return webhookIdempotency_1.deriveIdempotencyKey; } });
|
|
145
|
+
var webhookDeliveriesStore_1 = require("./triggers/webhookDeliveriesStore");
|
|
146
|
+
Object.defineProperty(exports, "createWebhookDeliveriesStore", { enumerable: true, get: function () { return webhookDeliveriesStore_1.createWebhookDeliveriesStore; } });
|
|
147
|
+
// ── v4.5 Phase 4a — email IMAP trigger ───────────────────────────────────
|
|
148
|
+
var email_1 = require("./triggers/email");
|
|
149
|
+
Object.defineProperty(exports, "createEmailTrigger", { enumerable: true, get: function () { return email_1.createEmailTrigger; } });
|
|
150
|
+
var emailSpec_1 = require("./triggers/email/emailSpec");
|
|
151
|
+
Object.defineProperty(exports, "parseEmailSpec", { enumerable: true, get: function () { return emailSpec_1.parseEmailSpec; } });
|
|
152
|
+
Object.defineProperty(exports, "DEFAULT_EMAIL_SPEC", { enumerable: true, get: function () { return emailSpec_1.DEFAULT_EMAIL_SPEC; } });
|
|
153
|
+
Object.defineProperty(exports, "DEFAULT_IMAP", { enumerable: true, get: function () { return emailSpec_1.DEFAULT_IMAP; } });
|
|
154
|
+
var automatedSender_1 = require("./triggers/email/automatedSender");
|
|
155
|
+
Object.defineProperty(exports, "isAutomatedSender", { enumerable: true, get: function () { return automatedSender_1.isAutomatedSender; } });
|
|
156
|
+
Object.defineProperty(exports, "NOREPLY_PATTERNS", { enumerable: true, get: function () { return automatedSender_1.NOREPLY_PATTERNS; } });
|
|
157
|
+
Object.defineProperty(exports, "AUTOMATED_HEADERS", { enumerable: true, get: function () { return automatedSender_1.AUTOMATED_HEADERS; } });
|
|
158
|
+
var allowlist_1 = require("./triggers/email/allowlist");
|
|
159
|
+
Object.defineProperty(exports, "compileSenderAllowlist", { enumerable: true, get: function () { return allowlist_1.compileSenderAllowlist; } });
|
|
160
|
+
var seenUids_1 = require("./triggers/email/seenUids");
|
|
161
|
+
Object.defineProperty(exports, "createSeenUids", { enumerable: true, get: function () { return seenUids_1.createSeenUids; } });
|
|
162
|
+
Object.defineProperty(exports, "DEFAULT_MAX_SEEN_UIDS", { enumerable: true, get: function () { return seenUids_1.DEFAULT_MAX_SEEN_UIDS; } });
|
|
163
|
+
var emailSeenStore_1 = require("./triggers/email/emailSeenStore");
|
|
164
|
+
Object.defineProperty(exports, "createEmailSeenStore", { enumerable: true, get: function () { return emailSeenStore_1.createEmailSeenStore; } });
|
|
165
|
+
var bodyExtractor_1 = require("./triggers/email/bodyExtractor");
|
|
166
|
+
Object.defineProperty(exports, "extractEmailBody", { enumerable: true, get: function () { return bodyExtractor_1.extractEmailBody; } });
|
|
167
|
+
var imapConnection_1 = require("./triggers/email/imapConnection");
|
|
168
|
+
Object.defineProperty(exports, "createImapConnection", { enumerable: true, get: function () { return imapConnection_1.createImapConnection; } });
|
|
169
|
+
Object.defineProperty(exports, "nextBackoffMs", { enumerable: true, get: function () { return imapConnection_1.nextBackoffMs; } });
|
|
170
|
+
Object.defineProperty(exports, "BACKOFF_CONSTANTS", { enumerable: true, get: function () { return imapConnection_1.BACKOFF_CONSTANTS; } });
|
|
171
|
+
var eventLoopLag_1 = require("./eventLoopLag");
|
|
172
|
+
Object.defineProperty(exports, "startEventLoopLagSampler", { enumerable: true, get: function () { return eventLoopLag_1.startEventLoopLagSampler; } });
|
|
173
|
+
Object.defineProperty(exports, "stopEventLoopLagSampler", { enumerable: true, get: function () { return eventLoopLag_1.stopEventLoopLagSampler; } });
|
|
174
|
+
Object.defineProperty(exports, "getEventLoopLagMs", { enumerable: true, get: function () { return eventLoopLag_1.getEventLoopLagMs; } });
|
|
175
|
+
Object.defineProperty(exports, "getLastTickAt", { enumerable: true, get: function () { return eventLoopLag_1.getLastTickAt; } });
|
|
176
|
+
Object.defineProperty(exports, "isEventLoopResponsive", { enumerable: true, get: function () { return eventLoopLag_1.isEventLoopResponsive; } });
|
|
177
|
+
var health_1 = require("./health");
|
|
178
|
+
Object.defineProperty(exports, "mountHealthEndpoints", { enumerable: true, get: function () { return health_1.mountHealthEndpoints; } });
|
|
179
|
+
Object.defineProperty(exports, "evaluateDegraded", { enumerable: true, get: function () { return health_1.evaluateDegraded; } });
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* core/v4/daemon/instanceTracker.ts — v4.5 Phase 1: daemon_instances writer.
|
|
10
|
+
*
|
|
11
|
+
* Writes the current process's identity into the `daemon_instances`
|
|
12
|
+
* table, updates `last_heartbeat` every 5s, and marks `shutdown_at`
|
|
13
|
+
* + `shutdown_reason` + `exit_code` on graceful exit.
|
|
14
|
+
*
|
|
15
|
+
* Crash detection — a row whose `shutdown_at IS NULL` and whose
|
|
16
|
+
* `last_heartbeat` is older than 30s on the NEXT daemon's boot is a
|
|
17
|
+
* crash candidate. `cleanShutdown.ts` evaluates this on boot.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.createInstanceTracker = createInstanceTracker;
|
|
21
|
+
const node_crypto_1 = require("node:crypto");
|
|
22
|
+
const daemonConfig_1 = require("./daemonConfig");
|
|
23
|
+
const HEARTBEAT_INTERVAL_MS = 5000;
|
|
24
|
+
function rowToTs(r) {
|
|
25
|
+
return {
|
|
26
|
+
instanceId: r.instance_id,
|
|
27
|
+
pid: r.pid,
|
|
28
|
+
hostname: r.hostname,
|
|
29
|
+
startedAt: r.started_at,
|
|
30
|
+
lastHeartbeat: r.last_heartbeat,
|
|
31
|
+
shutdownAt: r.shutdown_at,
|
|
32
|
+
shutdownReason: r.shutdown_reason,
|
|
33
|
+
exitCode: r.exit_code,
|
|
34
|
+
version: r.version,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function createInstanceTracker(opts) {
|
|
38
|
+
const instanceId = opts.instanceId ?? (0, node_crypto_1.randomUUID)();
|
|
39
|
+
const pid = opts.pid ?? process.pid;
|
|
40
|
+
const hostname = (0, daemonConfig_1.getHostname)();
|
|
41
|
+
const startedAt = Date.now();
|
|
42
|
+
const heartbeatIntervalMs = opts.heartbeatIntervalMs ?? HEARTBEAT_INTERVAL_MS;
|
|
43
|
+
opts.db
|
|
44
|
+
.prepare(`INSERT INTO daemon_instances
|
|
45
|
+
(instance_id, pid, hostname, started_at, last_heartbeat, version)
|
|
46
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
47
|
+
.run(instanceId, pid, hostname, startedAt, startedAt, opts.version);
|
|
48
|
+
let timer = null;
|
|
49
|
+
const beat = () => {
|
|
50
|
+
try {
|
|
51
|
+
opts.db
|
|
52
|
+
.prepare('UPDATE daemon_instances SET last_heartbeat = ? WHERE instance_id = ?')
|
|
53
|
+
.run(Date.now(), instanceId);
|
|
54
|
+
}
|
|
55
|
+
catch { /* never crash the daemon on a heartbeat write failure */ }
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
instanceId,
|
|
59
|
+
start() {
|
|
60
|
+
if (timer)
|
|
61
|
+
return;
|
|
62
|
+
timer = setInterval(beat, heartbeatIntervalMs);
|
|
63
|
+
if (typeof timer.unref === 'function')
|
|
64
|
+
timer.unref();
|
|
65
|
+
},
|
|
66
|
+
stop() {
|
|
67
|
+
if (!timer)
|
|
68
|
+
return;
|
|
69
|
+
clearInterval(timer);
|
|
70
|
+
timer = null;
|
|
71
|
+
},
|
|
72
|
+
markShuttingDown(reason) {
|
|
73
|
+
try {
|
|
74
|
+
opts.db
|
|
75
|
+
.prepare('UPDATE daemon_instances SET shutdown_reason = ? WHERE instance_id = ?')
|
|
76
|
+
.run(reason, instanceId);
|
|
77
|
+
}
|
|
78
|
+
catch { /* best-effort */ }
|
|
79
|
+
},
|
|
80
|
+
markShutdown(reason, exitCode) {
|
|
81
|
+
try {
|
|
82
|
+
opts.db
|
|
83
|
+
.prepare(`UPDATE daemon_instances
|
|
84
|
+
SET shutdown_at = ?,
|
|
85
|
+
shutdown_reason = ?,
|
|
86
|
+
exit_code = ?
|
|
87
|
+
WHERE instance_id = ?`)
|
|
88
|
+
.run(Date.now(), reason, exitCode, instanceId);
|
|
89
|
+
}
|
|
90
|
+
catch { /* best-effort */ }
|
|
91
|
+
},
|
|
92
|
+
current() {
|
|
93
|
+
const r = opts.db
|
|
94
|
+
.prepare('SELECT * FROM daemon_instances WHERE instance_id = ?')
|
|
95
|
+
.get(instanceId);
|
|
96
|
+
return r ? rowToTs(r) : null;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* core/v4/daemon/resourceRegistry.ts — v4.5 Phase 1: unified resource ledger.
|
|
10
|
+
*
|
|
11
|
+
* Single registry for every long-lived resource the daemon owns:
|
|
12
|
+
* - Playwright browser contexts (v4.3)
|
|
13
|
+
* - Docker session containers (v4.4)
|
|
14
|
+
* - HTTP keepalive agents
|
|
15
|
+
* - chokidar file watchers (Phase 2)
|
|
16
|
+
* - Subprocesses spawned by tools
|
|
17
|
+
* - IMAP connections (Phase 4)
|
|
18
|
+
* - SQLite handles
|
|
19
|
+
* - Webhook subrouters (Phase 3)
|
|
20
|
+
*
|
|
21
|
+
* Each resource carries:
|
|
22
|
+
* - kind (typed enum)
|
|
23
|
+
* - owner (sessionId | instanceId | 'global')
|
|
24
|
+
* - lifecycle timestamps
|
|
25
|
+
* - optional ttlMs for soft-reaping idle resources
|
|
26
|
+
* - optional budgetUnits for budget-based eviction
|
|
27
|
+
* - close(): an idempotent disposer
|
|
28
|
+
*
|
|
29
|
+
* The shutdown drain (`drain.ts` step 4) calls `reapAll()` to close
|
|
30
|
+
* everything with a per-item timeout. A periodic 60s sweep calls
|
|
31
|
+
* `sweep()` to close TTL-exceeded resources during normal operation.
|
|
32
|
+
*
|
|
33
|
+
* Diagnostic surface: `GET /api/daemon/resources` returns `list()` +
|
|
34
|
+
* `budgetByKind()` as JSON.
|
|
35
|
+
*/
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.createResourceRegistry = createResourceRegistry;
|
|
38
|
+
exports.getResourceRegistry = getResourceRegistry;
|
|
39
|
+
exports._resetResourceRegistryForTests = _resetResourceRegistryForTests;
|
|
40
|
+
const node_crypto_1 = require("node:crypto");
|
|
41
|
+
const _resources = new Map();
|
|
42
|
+
function withTimeout(p, ms) {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const t = setTimeout(() => reject(new Error(`resource close timed out after ${ms}ms`)), ms);
|
|
45
|
+
p.then((v) => { clearTimeout(t); resolve(v); }, (e) => { clearTimeout(t); reject(e); });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async function safeClose(r, perItemTimeoutMs) {
|
|
49
|
+
try {
|
|
50
|
+
const result = r.close();
|
|
51
|
+
if (result && typeof result.then === 'function') {
|
|
52
|
+
await withTimeout(result, perItemTimeoutMs);
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function createResourceRegistry() {
|
|
61
|
+
return {
|
|
62
|
+
register(r) {
|
|
63
|
+
const id = r.id ?? (0, node_crypto_1.randomUUID)();
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
_resources.set(id, {
|
|
66
|
+
id,
|
|
67
|
+
kind: r.kind,
|
|
68
|
+
owner: r.owner,
|
|
69
|
+
createdAt: now,
|
|
70
|
+
lastUsedAt: now,
|
|
71
|
+
ttlMs: r.ttlMs,
|
|
72
|
+
budgetUnits: r.budgetUnits,
|
|
73
|
+
metadata: r.metadata,
|
|
74
|
+
close: r.close,
|
|
75
|
+
});
|
|
76
|
+
return id;
|
|
77
|
+
},
|
|
78
|
+
touch(id) {
|
|
79
|
+
const r = _resources.get(id);
|
|
80
|
+
if (r)
|
|
81
|
+
r.lastUsedAt = Date.now();
|
|
82
|
+
},
|
|
83
|
+
async release(id) {
|
|
84
|
+
const r = _resources.get(id);
|
|
85
|
+
if (!r)
|
|
86
|
+
return;
|
|
87
|
+
_resources.delete(id);
|
|
88
|
+
await safeClose(r, 5000);
|
|
89
|
+
},
|
|
90
|
+
list(filter) {
|
|
91
|
+
const out = [];
|
|
92
|
+
for (const r of _resources.values()) {
|
|
93
|
+
if (filter?.kind && r.kind !== filter.kind)
|
|
94
|
+
continue;
|
|
95
|
+
if (filter?.owner && r.owner !== filter.owner)
|
|
96
|
+
continue;
|
|
97
|
+
out.push(r);
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
},
|
|
101
|
+
async sweep(now) {
|
|
102
|
+
const cutoff = now ?? Date.now();
|
|
103
|
+
const candidates = [];
|
|
104
|
+
for (const r of _resources.values()) {
|
|
105
|
+
if (r.ttlMs && cutoff - r.lastUsedAt > r.ttlMs)
|
|
106
|
+
candidates.push(r);
|
|
107
|
+
}
|
|
108
|
+
// Pull them out of the registry first so concurrent touches
|
|
109
|
+
// don't extend their lifetime mid-close.
|
|
110
|
+
for (const c of candidates)
|
|
111
|
+
_resources.delete(c.id);
|
|
112
|
+
const settled = await Promise.allSettled(candidates.map((c) => safeClose(c, 3000)));
|
|
113
|
+
return { reaped: settled.filter((s) => s.status === 'fulfilled' && s.value === true).length };
|
|
114
|
+
},
|
|
115
|
+
async reapAll(perItemTimeoutMs = 3000) {
|
|
116
|
+
const all = [..._resources.values()];
|
|
117
|
+
_resources.clear();
|
|
118
|
+
const settled = await Promise.allSettled(all.map((r) => safeClose(r, perItemTimeoutMs)));
|
|
119
|
+
let reaped = 0;
|
|
120
|
+
let failed = 0;
|
|
121
|
+
for (const s of settled) {
|
|
122
|
+
if (s.status === 'fulfilled' && s.value === true)
|
|
123
|
+
reaped++;
|
|
124
|
+
else
|
|
125
|
+
failed++;
|
|
126
|
+
}
|
|
127
|
+
return { reaped, failed };
|
|
128
|
+
},
|
|
129
|
+
budgetByKind() {
|
|
130
|
+
const out = {};
|
|
131
|
+
for (const r of _resources.values()) {
|
|
132
|
+
const slot = out[r.kind] ?? (out[r.kind] = { count: 0, budgetUnits: 0 });
|
|
133
|
+
slot.count += 1;
|
|
134
|
+
slot.budgetUnits += r.budgetUnits ?? 0;
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// ── Process-scope singleton ────────────────────────────────────────────────
|
|
141
|
+
let _singleton = null;
|
|
142
|
+
function getResourceRegistry() {
|
|
143
|
+
if (!_singleton)
|
|
144
|
+
_singleton = createResourceRegistry();
|
|
145
|
+
return _singleton;
|
|
146
|
+
}
|
|
147
|
+
function _resetResourceRegistryForTests() {
|
|
148
|
+
_singleton = null;
|
|
149
|
+
_resources.clear();
|
|
150
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* core/v4/daemon/restartCode.ts — v4.5 Phase 1: graceful-restart exit code.
|
|
10
|
+
*
|
|
11
|
+
* Single source of truth. THREE consumers must use the same value:
|
|
12
|
+
* 1. The in-process drain handler (`drain.ts`) — passes this to
|
|
13
|
+
* `process.exit()` when the daemon is reloading via SIGUSR1.
|
|
14
|
+
* 2. The systemd unit (`templates/systemd.service.template`) —
|
|
15
|
+
* `RestartForceExitStatus=75` triggers an immediate respawn
|
|
16
|
+
* regardless of `Restart=` mode.
|
|
17
|
+
* 3. The launchd plist (`templates/launchd.plist.template`) —
|
|
18
|
+
* uses `KeepAlive.SuccessfulExit=false` which is launchd's
|
|
19
|
+
* analog (any non-zero exit triggers respawn; exit 0 does not).
|
|
20
|
+
*
|
|
21
|
+
* Value 75 == sysexits.h `EX_TEMPFAIL` — semantically "service
|
|
22
|
+
* unavailable, retry later", matching what a service supervisor
|
|
23
|
+
* should do.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DAEMON_RESTART_EXIT_CODE = void 0;
|
|
27
|
+
/**
|
|
28
|
+
* Exit code used by `aiden daemon restart` and the SIGUSR1 handler
|
|
29
|
+
* to signal "respawn me, graceful restart" to systemd / launchd /
|
|
30
|
+
* the internal supervisor.
|
|
31
|
+
*/
|
|
32
|
+
exports.DAEMON_RESTART_EXIT_CODE = 75;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* core/v4/daemon/restartFailureCounter.ts — v4.5 Phase 1.
|
|
10
|
+
*
|
|
11
|
+
* Per-session stuck-loop guard. Each time a daemon crashes mid-turn
|
|
12
|
+
* for a given session, `incrementForSession(sessionId)` bumps the
|
|
13
|
+
* counter. When the counter reaches the configured threshold (default
|
|
14
|
+
* 3, configurable via AIDEN_DAEMON_RESTART_FAILURE_THRESHOLD), the
|
|
15
|
+
* session is auto-suspended: future restarts will refuse to resume it
|
|
16
|
+
* until the user explicitly sends a new message (which calls
|
|
17
|
+
* `resetForSession`).
|
|
18
|
+
*
|
|
19
|
+
* Counter resets to 0 when a turn completes successfully or when the
|
|
20
|
+
* user sends a new message.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.DEFAULT_STUCK_LOOP_THRESHOLD = void 0;
|
|
24
|
+
exports.createRestartFailureCounter = createRestartFailureCounter;
|
|
25
|
+
exports.DEFAULT_STUCK_LOOP_THRESHOLD = 3;
|
|
26
|
+
function createRestartFailureCounter(opts) {
|
|
27
|
+
const threshold = opts.threshold ?? exports.DEFAULT_STUCK_LOOP_THRESHOLD;
|
|
28
|
+
const db = opts.db;
|
|
29
|
+
return {
|
|
30
|
+
incrementForSession(sessionId) {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
const tx = db.transaction(() => {
|
|
33
|
+
const row = db
|
|
34
|
+
.prepare('SELECT count, auto_suspended FROM restart_failure_counts WHERE session_id = ?')
|
|
35
|
+
.get(sessionId);
|
|
36
|
+
const newCount = (row?.count ?? 0) + 1;
|
|
37
|
+
const autoSuspended = newCount >= threshold;
|
|
38
|
+
if (row) {
|
|
39
|
+
db.prepare(`UPDATE restart_failure_counts
|
|
40
|
+
SET count = ?,
|
|
41
|
+
last_failure = ?,
|
|
42
|
+
auto_suspended = ?
|
|
43
|
+
WHERE session_id = ?`).run(newCount, now, autoSuspended ? 1 : 0, sessionId);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
db.prepare(`INSERT INTO restart_failure_counts
|
|
47
|
+
(session_id, count, last_failure, auto_suspended)
|
|
48
|
+
VALUES (?, ?, ?, ?)`).run(sessionId, newCount, now, autoSuspended ? 1 : 0);
|
|
49
|
+
}
|
|
50
|
+
return { newCount, autoSuspended };
|
|
51
|
+
});
|
|
52
|
+
return tx();
|
|
53
|
+
},
|
|
54
|
+
resetForSession(sessionId) {
|
|
55
|
+
db.prepare('DELETE FROM restart_failure_counts WHERE session_id = ?').run(sessionId);
|
|
56
|
+
},
|
|
57
|
+
isAutoSuspended(sessionId) {
|
|
58
|
+
const row = db
|
|
59
|
+
.prepare('SELECT auto_suspended FROM restart_failure_counts WHERE session_id = ?')
|
|
60
|
+
.get(sessionId);
|
|
61
|
+
return row?.auto_suspended === 1;
|
|
62
|
+
},
|
|
63
|
+
listSuspended() {
|
|
64
|
+
const rows = db
|
|
65
|
+
.prepare(`SELECT session_id, count, last_failure
|
|
66
|
+
FROM restart_failure_counts
|
|
67
|
+
WHERE auto_suspended = 1
|
|
68
|
+
ORDER BY last_failure DESC`)
|
|
69
|
+
.all();
|
|
70
|
+
return rows.map((r) => ({
|
|
71
|
+
sessionId: r.session_id,
|
|
72
|
+
count: r.count,
|
|
73
|
+
lastFailure: r.last_failure,
|
|
74
|
+
}));
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 Shiva Deore (Taracod).
|
|
4
|
+
* Licensed under AGPL-3.0. See LICENSE for details.
|
|
5
|
+
*
|
|
6
|
+
* Aiden — local-first agent.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* core/v4/daemon/runStore.ts — v4.5 Phase 1: runs + run_events writers.
|
|
10
|
+
*
|
|
11
|
+
* Daemon-fired runs are persisted in `runs` (one row per turn) with
|
|
12
|
+
* a stream of `run_events` rows for per-event detail (tool calls,
|
|
13
|
+
* verifications, classifications, recovery actions, log lines).
|
|
14
|
+
*
|
|
15
|
+
* CLI-fired turns continue using in-memory trace structures — zero
|
|
16
|
+
* overhead for interactive use. The daemon path opts in by creating
|
|
17
|
+
* a run row + emitting events.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.createRunStore = createRunStore;
|
|
21
|
+
function rowToTs(r) {
|
|
22
|
+
return {
|
|
23
|
+
id: r.id,
|
|
24
|
+
triggerEventId: r.trigger_event_id,
|
|
25
|
+
sessionId: r.session_id,
|
|
26
|
+
instanceId: r.instance_id,
|
|
27
|
+
status: r.status,
|
|
28
|
+
finishReason: r.finish_reason,
|
|
29
|
+
startedAt: r.started_at,
|
|
30
|
+
completedAt: r.completed_at,
|
|
31
|
+
resumePending: r.resume_pending === 1,
|
|
32
|
+
resumeReason: r.resume_reason,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function createRunStore(opts) {
|
|
36
|
+
const db = opts.db;
|
|
37
|
+
return {
|
|
38
|
+
create({ sessionId, instanceId, triggerEventId, status, startedAt }) {
|
|
39
|
+
const now = startedAt ?? Date.now();
|
|
40
|
+
const r = db.prepare(`INSERT INTO runs
|
|
41
|
+
(trigger_event_id, session_id, instance_id, status, started_at,
|
|
42
|
+
resume_pending)
|
|
43
|
+
VALUES (?, ?, ?, ?, ?, 0)`).run(triggerEventId ?? null, sessionId, instanceId, status ?? 'queued', now);
|
|
44
|
+
return Number(r.lastInsertRowid);
|
|
45
|
+
},
|
|
46
|
+
setStatus(runId, status, opts2 = {}) {
|
|
47
|
+
const completedAt = opts2.completedAt
|
|
48
|
+
?? (status === 'completed' || status === 'failed' || status === 'cancelled' || status === 'interrupted'
|
|
49
|
+
? Date.now()
|
|
50
|
+
: null);
|
|
51
|
+
db.prepare(`UPDATE runs
|
|
52
|
+
SET status = ?,
|
|
53
|
+
finish_reason = COALESCE(?, finish_reason),
|
|
54
|
+
completed_at = COALESCE(?, completed_at)
|
|
55
|
+
WHERE id = ?`).run(status, opts2.finishReason ?? null, completedAt, runId);
|
|
56
|
+
},
|
|
57
|
+
markResumePending(runId, reason) {
|
|
58
|
+
db.prepare(`UPDATE runs SET resume_pending = 1, resume_reason = ? WHERE id = ?`).run(reason, runId);
|
|
59
|
+
},
|
|
60
|
+
emitEvent(runId, kind, payload) {
|
|
61
|
+
const json = JSON.stringify(payload).slice(0, 4096);
|
|
62
|
+
db.prepare(`INSERT INTO run_events (run_id, ts, kind, payload) VALUES (?, ?, ?, ?)`).run(runId, Date.now(), kind, json);
|
|
63
|
+
},
|
|
64
|
+
listActive() {
|
|
65
|
+
const rows = db
|
|
66
|
+
.prepare(`SELECT * FROM runs WHERE status IN ('queued','running')`)
|
|
67
|
+
.all();
|
|
68
|
+
return rows.map(rowToTs);
|
|
69
|
+
},
|
|
70
|
+
get(runId) {
|
|
71
|
+
const r = db
|
|
72
|
+
.prepare('SELECT * FROM runs WHERE id = ?')
|
|
73
|
+
.get(runId);
|
|
74
|
+
return r ? rowToTs(r) : null;
|
|
75
|
+
},
|
|
76
|
+
countEvents(runId) {
|
|
77
|
+
const r = db
|
|
78
|
+
.prepare('SELECT COUNT(*) AS c FROM run_events WHERE run_id = ?')
|
|
79
|
+
.get(runId);
|
|
80
|
+
return r.c;
|
|
81
|
+
},
|
|
82
|
+
listRecent(opts2 = {}) {
|
|
83
|
+
const limit = Math.max(1, Math.min(opts2.limit ?? 50, 1000));
|
|
84
|
+
const whereParts = [];
|
|
85
|
+
const params = [];
|
|
86
|
+
if (opts2.status) {
|
|
87
|
+
whereParts.push('r.status = ?');
|
|
88
|
+
params.push(opts2.status);
|
|
89
|
+
}
|
|
90
|
+
if (opts2.source) {
|
|
91
|
+
whereParts.push('te.source = ?');
|
|
92
|
+
params.push(opts2.source);
|
|
93
|
+
}
|
|
94
|
+
if (opts2.sessionIdPrefix) {
|
|
95
|
+
whereParts.push('r.session_id LIKE ?');
|
|
96
|
+
params.push(`${opts2.sessionIdPrefix}%`);
|
|
97
|
+
}
|
|
98
|
+
const where = whereParts.length > 0 ? `WHERE ${whereParts.join(' AND ')}` : '';
|
|
99
|
+
const sql = `
|
|
100
|
+
SELECT r.* FROM runs r
|
|
101
|
+
LEFT JOIN trigger_events te ON r.trigger_event_id = te.id
|
|
102
|
+
${where}
|
|
103
|
+
ORDER BY r.started_at DESC
|
|
104
|
+
LIMIT ?`;
|
|
105
|
+
params.push(limit);
|
|
106
|
+
const rows = db.prepare(sql).all(...params);
|
|
107
|
+
return rows.map(rowToTs);
|
|
108
|
+
},
|
|
109
|
+
listEvents(runId, limit = 200) {
|
|
110
|
+
const rows = db.prepare(`SELECT ts, kind, payload FROM run_events WHERE run_id = ? ORDER BY ts ASC LIMIT ?`).all(runId, Math.max(1, Math.min(limit, 5000)));
|
|
111
|
+
return rows;
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|