@tekmidian/pai 0.58.0 → 0.60.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/.claude-plugin/plugin.json +8 -33
- package/PLUGIN-ARCHITECTURE.md +4 -6
- package/dist/{aibroker-client-B8Wtasez.mjs → aibroker-client-BYG-GtAg.mjs} +1 -1
- package/dist/{chain-Cltx0NjY.mjs → chain-DFlzAfDE.mjs} +4 -4
- package/dist/{chain-Cltx0NjY.mjs.map → chain-DFlzAfDE.mjs.map} +1 -1
- package/dist/cli/index.mjs +12 -12
- package/dist/cli/program.mjs +12 -12
- package/dist/{config-DCYWFaEi.mjs → config-GceCMUxa.mjs} +1 -1
- package/dist/{config-D1omG_UU.mjs → config-msER8xj_.mjs} +16 -4
- package/dist/config-msER8xj_.mjs.map +1 -0
- package/dist/{context-handover-cache-Dt4HW1Ro.mjs → context-handover-cache-DF0xWVB0.mjs} +4 -4
- package/dist/{context-handover-cache-Dt4HW1Ro.mjs.map → context-handover-cache-DF0xWVB0.mjs.map} +1 -1
- package/dist/daemon/index.mjs +12 -12
- package/dist/daemon-BppwJtrH.mjs +19 -0
- package/dist/{daemon-CmqJfeb9.mjs → daemon-DArRKBlk.mjs} +97 -23
- package/dist/daemon-DArRKBlk.mjs.map +1 -0
- package/dist/daemon-mcp/index.mjs +9 -9
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/{factory-DiuntvwG.mjs → factory-ChfAvCzO.mjs} +7 -7
- package/dist/{factory-DiuntvwG.mjs.map → factory-ChfAvCzO.mjs.map} +1 -1
- package/dist/{factory-C9wGUe30.mjs → factory-D6I2jmjQ.mjs} +1 -1
- package/dist/{fallback-B_2ozQHw.mjs → fallback-B7VEMMRn.mjs} +80 -9
- package/dist/fallback-B7VEMMRn.mjs.map +1 -0
- package/dist/hooks/block-sleep-poll.mjs +7590 -0
- package/dist/hooks/block-sleep-poll.mjs.map +7 -0
- package/dist/hooks/capture-all-events.mjs +8 -4
- package/dist/hooks/capture-all-events.mjs.map +2 -2
- package/dist/hooks/capture-session-summary.mjs.map +1 -1
- package/dist/hooks/capture-tool-output.mjs.map +1 -1
- package/dist/hooks/cleanup-session-files.mjs.map +1 -1
- package/dist/hooks/context-compression-hook.mjs +6 -6
- package/dist/hooks/context-compression-hook.mjs.map +3 -3
- package/dist/hooks/initialize-session.mjs.map +1 -1
- package/dist/hooks/load-core-context.mjs.map +1 -1
- package/dist/hooks/load-project-context.mjs.map +2 -2
- package/dist/hooks/post-compact-inject.mjs +1 -1
- package/dist/hooks/post-compact-inject.mjs.map +2 -2
- package/dist/hooks/route-agents-to-worker.mjs +4 -3
- package/dist/hooks/route-agents-to-worker.mjs.map +3 -3
- package/dist/hooks/security-validator.mjs +4 -3
- package/dist/hooks/security-validator.mjs.map +3 -3
- package/dist/hooks/stop-hook.mjs.map +1 -1
- package/dist/hooks/sync-todo-to-md.mjs.map +1 -1
- package/dist/hooks/whisper-rules.mjs +4 -3
- package/dist/hooks/whisper-rules.mjs.map +3 -3
- package/dist/hooks/worker-proxy.mjs +4 -3
- package/dist/hooks/worker-proxy.mjs.map +3 -3
- package/dist/hooks/worker-status-line.mjs +9 -6
- package/dist/hooks/worker-status-line.mjs.map +3 -3
- package/dist/hooks/worker-supervision.mjs +4 -3
- package/dist/hooks/worker-supervision.mjs.map +3 -3
- package/dist/{main-resolver-DYNxxNwJ.mjs → main-resolver-BqTjt-GL.mjs} +100 -21
- package/dist/main-resolver-BqTjt-GL.mjs.map +1 -0
- package/dist/main-resolver-CCojcYr2.mjs +7 -0
- package/dist/{planner-DsZZEZCA.mjs → planner-DbpsMZqY.mjs} +83 -30
- package/dist/planner-DbpsMZqY.mjs.map +1 -0
- package/dist/{program-D-WkmvuQ.mjs → program-QSuci3RH.mjs} +325 -93
- package/dist/program-QSuci3RH.mjs.map +1 -0
- package/dist/router-C5hPk9YP.mjs +3 -0
- package/dist/{router-BdxdsAvs.mjs → router-DjFZIoDl.mjs} +2 -1
- package/dist/router-DjFZIoDl.mjs.map +1 -0
- package/dist/{run-XaA-UPdW.mjs → run-BFxuNnIJ.mjs} +100 -17
- package/dist/run-BFxuNnIJ.mjs.map +1 -0
- package/dist/{run-env-DyTWgZC9.mjs → run-env-kbWVwUvU.mjs} +2 -2
- package/dist/{run-env-DyTWgZC9.mjs.map → run-env-kbWVwUvU.mjs.map} +1 -1
- package/dist/{server-CzqHGbKt.mjs → server-B0vBmfJt.mjs} +2 -2
- package/dist/{server-CzqHGbKt.mjs.map → server-B0vBmfJt.mjs.map} +1 -1
- package/dist/{session-keepalive-DDsEo81Q.mjs → session-keepalive-CUcFa8ld.mjs} +5 -5
- package/dist/{session-keepalive-DDsEo81Q.mjs.map → session-keepalive-CUcFa8ld.mjs.map} +1 -1
- package/dist/{tools-Diro2s8J.mjs → tools-CaTZnIau.mjs} +2 -2
- package/dist/{tools-Diro2s8J.mjs.map → tools-CaTZnIau.mjs.map} +1 -1
- package/dist/{tools-KgL1rkPD.mjs → tools-_7MF8Ebb.mjs} +3 -3
- package/dist/{wakeup-D0uvqLsE.mjs → wakeup-CTX3rlz-.mjs} +2 -2
- package/dist/wakeup-CTX3rlz-.mjs.map +1 -0
- package/dist/{work-queue-worker-DL9lu8sN.mjs → work-queue-worker-B4eZGy5n.mjs} +2 -2
- package/dist/{work-queue-worker-DL9lu8sN.mjs.map → work-queue-worker-B4eZGy5n.mjs.map} +1 -1
- package/dist/work-queue-worker-DuhZmfDB.mjs +11 -0
- package/docker/init.sql +1 -1
- package/docs/commands/README.md +4 -4
- package/docs/commands/daemon.md +6 -6
- package/docs/commands/session.md +2 -2
- package/docs/commands/worker.md +5 -2
- package/docs/workers-config.md +5 -1
- package/package.json +1 -1
- package/plugins/context-preservation/hooks/hooks.json +38 -31
- package/plugins/context-preservation/plugin.json +1 -4
- package/plugins/core/hooks/hooks.json +51 -46
- package/plugins/core/plugin.json +1 -4
- package/plugins/creative/plugin.json +1 -5
- package/plugins/observability/hooks/hooks.json +87 -72
- package/plugins/observability/plugin.json +1 -5
- package/plugins/productivity/hooks/hooks.json +22 -19
- package/plugins/productivity/plugin.json +2 -5
- package/plugins/semantic-search/plugin.json +1 -16
- package/plugins/ui/hooks/hooks.json +17 -14
- package/plugins/ui/plugin.json +1 -5
- package/plugins/zettelkasten/plugin.json +1 -14
- package/src/hooks/session-autosave.sh +4 -2
- package/src/hooks/session-stop.sh +2 -2
- package/src/hooks/ts/capture-all-events.ts +3 -3
- package/src/hooks/ts/lib/metadata-extraction.ts +3 -2
- package/src/hooks/ts/lib/pai-paths.test.ts +1 -1
- package/src/hooks/ts/lib/sleep-poll-gate.test.ts +62 -0
- package/src/hooks/ts/lib/sleep-poll-gate.ts +77 -0
- package/src/hooks/ts/post-tool-use/capture-tool-output.ts +1 -1
- package/src/hooks/ts/post-tool-use/sync-todo-to-md.ts +1 -1
- package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
- package/src/hooks/ts/pre-tool-use/block-sleep-poll.test.ts +44 -0
- package/src/hooks/ts/pre-tool-use/block-sleep-poll.ts +50 -0
- package/src/hooks/ts/session-end/capture-session-summary.ts +1 -1
- package/src/hooks/ts/session-start/initialize-session.ts +2 -2
- package/src/hooks/ts/session-start/load-core-context.ts +2 -2
- package/src/hooks/ts/session-start/load-project-context.ts +1 -1
- package/src/hooks/ts/stop/stop-hook.ts +1 -1
- package/src/hooks/ts/user-prompt/cleanup-session-files.ts +1 -1
- package/statusline-command.sh +26 -11
- package/dist/config-D1omG_UU.mjs.map +0 -1
- package/dist/daemon-B6hx1Ysz.mjs +0 -19
- package/dist/daemon-CmqJfeb9.mjs.map +0 -1
- package/dist/fallback-B_2ozQHw.mjs.map +0 -1
- package/dist/main-resolver-DYNxxNwJ.mjs.map +0 -1
- package/dist/main-resolver-Df65bPAi.mjs +0 -7
- package/dist/planner-DsZZEZCA.mjs.map +0 -1
- package/dist/program-D-WkmvuQ.mjs.map +0 -1
- package/dist/router-BXOf_e9e.mjs +0 -3
- package/dist/router-BdxdsAvs.mjs.map +0 -1
- package/dist/run-XaA-UPdW.mjs.map +0 -1
- package/dist/wakeup-D0uvqLsE.mjs.map +0 -1
- package/dist/work-queue-worker-BY7xn4pw.mjs +0 -11
|
@@ -3,28 +3,28 @@ import { a as slugify$1, i as parseSessionFilename } from "./migrate-BD7D8EEh.mj
|
|
|
3
3
|
import { n as ensurePaiMarker } from "./pai-marker-D1MMswkz.mjs";
|
|
4
4
|
import { t as STOP_WORDS } from "./stop-words-ClCwO8mZ.mjs";
|
|
5
5
|
import { t as applyRecencyBoost } from "./search-BaTbyWjK.mjs";
|
|
6
|
-
import { a as getStorageBackend, i as getRegistryBackend, r as createStorageBackend, s as humanDuration } from "./factory-
|
|
7
|
-
import { a as formatDetectionJson, i as formatDetection, n as migrateIdentityFile, r as detectProject } from "./wakeup-
|
|
8
|
-
import { B as claudeProjectsDir, C as findLatestNote, H as scanTranscriptFolders, I as resolveHome, L as saveScanConfig, M as cmdScan, N as loadScanConfig, P as migrateScanConfig, R as upsertProject, S as applyContinue, T as readBodyFile, U as transcriptFiles, V as findMovedProjects, d as migrateWorkQueue, g as migrateSummaryCooldowns, t as readContextHandoverCache, v as extractAndStoreTriples, w as findNotesDir$1, x as appendCheckpointToNote, z as upsertSession } from "./context-handover-cache-
|
|
6
|
+
import { a as getStorageBackend, i as getRegistryBackend, r as createStorageBackend, s as humanDuration } from "./factory-ChfAvCzO.mjs";
|
|
7
|
+
import { a as formatDetectionJson, i as formatDetection, n as migrateIdentityFile, r as detectProject } from "./wakeup-CTX3rlz-.mjs";
|
|
8
|
+
import { B as claudeProjectsDir, C as findLatestNote, H as scanTranscriptFolders, I as resolveHome, L as saveScanConfig, M as cmdScan, N as loadScanConfig, P as migrateScanConfig, R as upsertProject, S as applyContinue, T as readBodyFile, U as transcriptFiles, V as findMovedProjects, d as migrateWorkQueue, g as migrateSummaryCooldowns, t as readContextHandoverCache, v as extractAndStoreTriples, w as findNotesDir$1, x as appendCheckpointToNote, z as upsertSession } from "./context-handover-cache-DF0xWVB0.mjs";
|
|
9
9
|
import { a as paiHomePath, i as paiHomeDir, n as migratePaiDir, o as resolvePaiFile, r as migratePaiFile, t as PaiFileMigrationError } from "./pai-home-CeOIYltV.mjs";
|
|
10
|
-
import { b as OWNER_LABEL_PREFIX, c as migrateConfigFile, d as readMainConfigRaw, f as writeMainConfigRaw, h as resolvedMainConfigPath, l as paiConfigFilePath, m as migrateMainConfigToYaml, n as CONFIG_FILE$2, o as expandHome, p as MainConfigError, s as loadConfig, t as CONFIG_DIR, u as paiConfigYamlFilePath, v as readJsonStrict, x as UNROUTED, y as writeJsonAtomic } from "./config-
|
|
10
|
+
import { b as OWNER_LABEL_PREFIX, c as migrateConfigFile, d as readMainConfigRaw, f as writeMainConfigRaw, h as resolvedMainConfigPath, l as paiConfigFilePath, m as migrateMainConfigToYaml, n as CONFIG_FILE$2, o as expandHome, p as MainConfigError, s as loadConfig, t as CONFIG_DIR, u as paiConfigYamlFilePath, v as readJsonStrict, x as UNROUTED, y as writeJsonAtomic } from "./config-msER8xj_.mjs";
|
|
11
11
|
import { a as schedulerLogPath, i as paiSocketPath, n as daemonLogPath, r as daemonPidPath } from "./runtime-paths-BRwDeBEg.mjs";
|
|
12
|
-
import { A as initWorkersYaml, B as stripModelVariant, F as relocateWorkersYaml, I as workersYamlLegacyNotice, L as workersYamlPath, M as migrateWorkersToYaml, N as needsWorkersYamlRelocation, P as parseWorkersYamlDocument, R as DEFAULT_CONTEXT_WINDOW, S as nativeAnthropicProvider, T as readWorkersSection, _ as expandHome$1, d as PROVIDER_TAGS, j as inlineWorkersYamlKeys, p as WorkersConfigError, r as ANTHROPIC_NATIVE, t as buildRunEnv, u as MODEL_CAPABILITIES, v as getProviderOrNative, x as maskKey, y as isModelCapability, z as contextWindowFromModelId } from "./run-env-
|
|
13
|
-
import {
|
|
12
|
+
import { A as initWorkersYaml, B as stripModelVariant, F as relocateWorkersYaml, I as workersYamlLegacyNotice, L as workersYamlPath, M as migrateWorkersToYaml, N as needsWorkersYamlRelocation, P as parseWorkersYamlDocument, R as DEFAULT_CONTEXT_WINDOW, S as nativeAnthropicProvider, T as readWorkersSection, _ as expandHome$1, d as PROVIDER_TAGS, j as inlineWorkersYamlKeys, p as WorkersConfigError, r as ANTHROPIC_NATIVE, t as buildRunEnv, u as MODEL_CAPABILITIES, v as getProviderOrNative, x as maskKey, y as isModelCapability, z as contextWindowFromModelId } from "./run-env-kbWVwUvU.mjs";
|
|
13
|
+
import { A as UNLABELED, E as mergeWorker, G as waitForTerminalStatus, H as ownsPid, I as isChatPane, K as longInlinePromptHint, L as isLive, O as appendLedger, R as loadStatus, U as saveStatus, W as setWorkerLabel, X as expandMcpNames, Y as describeMcp, a as projectLaunchConfig, c as handoffFromInside, f as checkPaneForWorker, g as markControlsHeld, h as clickrControlsArgv, i as usageContextTokens, m as openPaneForWorker, n as runWorker, o as parseWorkerReport, p as openFollowPane, q as parseRunnerArgs, r as testProvider, u as sayToWorker, w as discardWorker, z as loadStatuses } from "./run-BFxuNnIJ.mjs";
|
|
14
14
|
import { t as MergeError } from "./merge-xoyfZQ4W.mjs";
|
|
15
15
|
import { n as oldFederationPath, t as federationDbPath } from "./federation-db-w8e-sKjp.mjs";
|
|
16
16
|
import { r as registryDbPath, t as oldRegistryPath } from "./registry-db-Bkpbp7Gf.mjs";
|
|
17
17
|
import { i as indexProjectWithBackend } from "./async-CLvuY7b-.mjs";
|
|
18
18
|
import { t as PaiClient } from "./ipc-client-Dasm515c.mjs";
|
|
19
|
-
import { A as getConfigValueOp, C as psOutput, D as resolveSpecPath, E as readSpecPrompt, M as setConfigValueOp, N as unsetConfigValueOp, O as MainConfigOpsError, S as followWorkers, T as statusLineOutput, _ as setWorkersEnabled, a as addProvider, b as updateProvider, c as describeModels, d as removeProvider, f as resolveProviderName, g as setProviderModel, h as setProviderEnabled, i as fallbackStatusText, j as listConfigOp, k as formatConfigGetOutput, l as describeProviders, m as setClass, n as fallbackOn, o as classTargetText, p as setCapabilityPreference, r as fallbackStatus, s as describeCapabilities, t as fallbackOff, u as modelPrefsText, v as unsetCapabilityPreference, w as replayOutput, x as useProvider, y as unsetClass } from "./fallback-
|
|
20
|
-
import { _ as
|
|
19
|
+
import { A as getConfigValueOp, C as psOutput, D as resolveSpecPath, E as readSpecPrompt, M as setConfigValueOp, N as unsetConfigValueOp, O as MainConfigOpsError, S as followWorkers, T as statusLineOutput, _ as setWorkersEnabled, a as addProvider, b as updateProvider, c as describeModels, d as removeProvider, f as resolveProviderName, g as setProviderModel, h as setProviderEnabled, i as fallbackStatusText, j as listConfigOp, k as formatConfigGetOutput, l as describeProviders, m as setClass, n as fallbackOn, o as classTargetText, p as setCapabilityPreference, r as fallbackStatus, s as describeCapabilities, t as fallbackOff, u as modelPrefsText, v as unsetCapabilityPreference, w as replayOutput, x as useProvider, y as unsetClass } from "./fallback-B7VEMMRn.mjs";
|
|
20
|
+
import { _ as resolveSessionByNameOrId, a as buildDeduped, c as hasConversation, d as providerResumePlan, f as restoreTopLevel, g as migrateSessionScanCache, h as fmtAge, l as launchInDir, m as printExitDir, o as normalizeName$2, p as resumeArgvText, s as renderDedupedSessions, t as cmdMain, u as launchPrompt, v as scanCacheFilePath, y as scanSessions } from "./main-resolver-BqTjt-GL.mjs";
|
|
21
21
|
import { n as queriesDirPath, t as migrateQueriesDir } from "./query-feedback-xz5axTj3.mjs";
|
|
22
|
-
import { h as ledgerPath, m as eventsPath, n as ensureProxyRunning, p as ensureNoMcpConfig, r as stopProxy, t as DEFAULT_PROXY_PORT, v as workersLogDir } from "./server-
|
|
22
|
+
import { h as ledgerPath, m as eventsPath, n as ensureProxyRunning, p as ensureNoMcpConfig, r as stopProxy, t as DEFAULT_PROXY_PORT, v as workersLogDir } from "./server-B0vBmfJt.mjs";
|
|
23
23
|
import { i as sendToSession, n as fetchLiveSessions, r as revealItermSession, t as callAiBroker } from "./aibroker-client-BK1h--W_.mjs";
|
|
24
|
-
import { a as totalUsageTokens, i as parseSessionUsage, r as sessionKeepaliveLedgerSummary, t as loadSessionKeepaliveState } from "./session-keepalive-
|
|
25
|
-
import { t as runChain } from "./chain-
|
|
24
|
+
import { a as totalUsageTokens, i as parseSessionUsage, r as sessionKeepaliveLedgerSummary, t as loadSessionKeepaliveState } from "./session-keepalive-CUcFa8ld.mjs";
|
|
25
|
+
import { t as runChain } from "./chain-DFlzAfDE.mjs";
|
|
26
26
|
import { appendFileSync, chmodSync, copyFileSync, cpSync, createReadStream, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
27
|
-
import { homedir, platform, tmpdir } from "node:os";
|
|
27
|
+
import { homedir, platform, tmpdir, userInfo } from "node:os";
|
|
28
28
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
29
29
|
import chalk from "chalk";
|
|
30
30
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -161,7 +161,7 @@ async function cmdPromote(opts) {
|
|
|
161
161
|
console.error(dim$1(` Pick a durable location for the new project.`));
|
|
162
162
|
process.exit(1);
|
|
163
163
|
}
|
|
164
|
-
const { getRegistryBackend } = await import("./factory-
|
|
164
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
165
165
|
const registryBackend = await getRegistryBackend();
|
|
166
166
|
const encodedDir = encodeDir(targetPath);
|
|
167
167
|
if (await registryBackend.getProjectBySlug(slug) ?? await registryBackend.getProjectByRootPath(targetPath) ?? await registryBackend.getProjectByEncodedDir(encodedDir)) {
|
|
@@ -2035,7 +2035,7 @@ async function cmdUnregister(slug, opts = {}) {
|
|
|
2035
2035
|
//#region src/cli/commands/project/projects-index.ts
|
|
2036
2036
|
function registerProjectsCommands(projectsCmd) {
|
|
2037
2037
|
projectsCmd.command("list", { isDefault: true }).description("Show the unified deduped listing (same as `pai`).\nUse --all to include cold / zero-session / archived projects.").option("--all", "Show all entries including cold / zero-session / archived projects").option("-n, --n <count>", "Max rows to show", "20").action(async (opts) => {
|
|
2038
|
-
const { cmdMain } = await import("./main-resolver-
|
|
2038
|
+
const { cmdMain } = await import("./main-resolver-CCojcYr2.mjs");
|
|
2039
2039
|
await cmdMain(void 0, void 0, opts);
|
|
2040
2040
|
});
|
|
2041
2041
|
projectsCmd.command("list-raw").description("Raw registry listing with slug, path, status, last_active columns").option("--all", "Include archived projects (default: active only)").option("--status <status>", "Filter by status: active | archived").option("--tag <tag>", "Filter by tag").option("--type <type>", "Filter by type").action(async (opts) => {
|
|
@@ -3247,8 +3247,8 @@ function registerStatsCommands(memoryCmd) {
|
|
|
3247
3247
|
//#region src/cli/commands/memory/sources-cmd.ts
|
|
3248
3248
|
function registerSourcesCommand(memoryCmd) {
|
|
3249
3249
|
memoryCmd.command("sources").description("Show what the indexer has taken in: composition by source, which roots\ncontent enters from, the heaviest single files, and how many chunks are\nrewritten per day (which distinguishes a finite backlog from a treadmill).").option("--limit <n>", "Rows per section (default 8)", "8").action(async (opts) => {
|
|
3250
|
-
const { createStorageBackend } = await import("./factory-
|
|
3251
|
-
const { loadConfig } = await import("./config-
|
|
3250
|
+
const { createStorageBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
3251
|
+
const { loadConfig } = await import("./config-GceCMUxa.mjs");
|
|
3252
3252
|
const { cmdMemorySources } = await import("./sources-BBe3AZ-W.mjs");
|
|
3253
3253
|
let backend;
|
|
3254
3254
|
try {
|
|
@@ -3949,8 +3949,8 @@ async function escalate(task, headline, detail, state, now, opts) {
|
|
|
3949
3949
|
state.alarmedAt[task.id] = now;
|
|
3950
3950
|
let delivered = false;
|
|
3951
3951
|
try {
|
|
3952
|
-
const { routeNotification } = await import("./router-
|
|
3953
|
-
const { loadConfig } = await import("./config-
|
|
3952
|
+
const { routeNotification } = await import("./router-C5hPk9YP.mjs");
|
|
3953
|
+
const { loadConfig } = await import("./config-GceCMUxa.mjs");
|
|
3954
3954
|
delivered = (await routeNotification({
|
|
3955
3955
|
event: "error",
|
|
3956
3956
|
title: `PAI: ${headline}`,
|
|
@@ -3963,6 +3963,35 @@ async function escalate(task, headline, detail, state, now, opts) {
|
|
|
3963
3963
|
} catch {}
|
|
3964
3964
|
}
|
|
3965
3965
|
/**
|
|
3966
|
+
* One best-effort PAILot alert at the moment a task transitions into parked.
|
|
3967
|
+
*
|
|
3968
|
+
* Parking is silent from the phone's point of view: the tracker note and the
|
|
3969
|
+
* scheduler log both say PARKED, but the only person who reads either is the
|
|
3970
|
+
* one who already knows. On 2026-09-27 both morning sweeps were parked on a
|
|
3971
|
+
* FALSE unreachable (the hub misread a statusline) and nothing surfaced it
|
|
3972
|
+
* until the day's run simply did not happen — the exact failure parking's own
|
|
3973
|
+
* docs promise to prevent.
|
|
3974
|
+
*
|
|
3975
|
+
* Deliberately NOT rate-limited beyond its call sites: it runs exactly once
|
|
3976
|
+
* per parking event (on the transition, not on every poll while parked), and
|
|
3977
|
+
* a re-park after a release is a new event that deserves a new alert. The
|
|
3978
|
+
* escalate() quiet window is untouched — this is the announcement, that is
|
|
3979
|
+
* the daily reminder.
|
|
3980
|
+
*
|
|
3981
|
+
* Never allowed to throw or linger: the hub gets a short deadline, and an
|
|
3982
|
+
* unreachable hub falls back to the poller log (launchd sends both streams to
|
|
3983
|
+
* /tmp/pai-scheduler.log, which already carries every PARKED line).
|
|
3984
|
+
*/
|
|
3985
|
+
async function alertParked(task, reason) {
|
|
3986
|
+
const text = `PAI parked "${task.title}" (${task.id}) — the scheduler will not retry it.\nReason: ${reason}\nTo release it: fix the cause, then move the due date — due_string, natural language only (e.g. "tomorrow 9am").`;
|
|
3987
|
+
try {
|
|
3988
|
+
const { callAiBroker } = await import("./aibroker-client-BYG-GtAg.mjs");
|
|
3989
|
+
await callAiBroker("pailot_send", { text }, 8e3);
|
|
3990
|
+
} catch (e) {
|
|
3991
|
+
console.error(`[pai-poller] parked-task alert not delivered to PAILot (${e instanceof Error ? e.message : String(e)}): ${text}`);
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3994
|
+
/**
|
|
3966
3995
|
* Run state is a rebuildable cache, so a damaged file must not block the
|
|
3967
3996
|
* scheduler forever — starting fresh is the correct recovery here, which is
|
|
3968
3997
|
* exactly the case json-store's guard is NOT for.
|
|
@@ -4242,6 +4271,7 @@ async function handleDispatch(task, overdue, opts, state, now) {
|
|
|
4242
4271
|
at: now,
|
|
4243
4272
|
due: task.due ?? void 0
|
|
4244
4273
|
};
|
|
4274
|
+
await alertParked(task, reason);
|
|
4245
4275
|
await escalate(task, "task is not running", `cannot be dispatched: its project directory ${task.owner.rootPath} does not exist (renamed or moved?). It is now PARKED and will not be retried. Repoint the project with \`pai project\` and move the task's due date to release it.`, state, now, opts);
|
|
4246
4276
|
return {
|
|
4247
4277
|
note: `PARKED — ${reason}`,
|
|
@@ -4280,6 +4310,7 @@ async function handleDispatch(task, overdue, opts, state, now) {
|
|
|
4280
4310
|
at: now,
|
|
4281
4311
|
due: task.due ?? void 0
|
|
4282
4312
|
};
|
|
4313
|
+
await alertParked(task, detail);
|
|
4283
4314
|
await escalate(task, "task is not running", `failed to dispatch ${permanent ? "" : `${fails} times `}(${detail}). It is scheduled and nothing is executing it. It is now PARKED and will not be retried until its due date moves — reschedule it once the cause is fixed.`, state, now, opts);
|
|
4284
4315
|
return {
|
|
4285
4316
|
note: `PARKED — ${permanent ? "permanent failure" : `${fails} failed dispatches`}: ${detail}`,
|
|
@@ -4444,7 +4475,28 @@ async function keepTriggeredSchedule(task, opts, state, now) {
|
|
|
4444
4475
|
return `, could NOT keep the schedule: ${e instanceof Error ? e.message : String(e)}`;
|
|
4445
4476
|
}
|
|
4446
4477
|
}
|
|
4447
|
-
|
|
4478
|
+
/** Re-dispatch attempts allowed for one claim before NOT-RECEIVED gives up. */
|
|
4479
|
+
const NOT_RECEIVED_MAX_ATTEMPTS = 3;
|
|
4480
|
+
/** Minutes of backoff per attempt: try 1 waits 2m, try 2 waits 4m, try 3 waits 6m. */
|
|
4481
|
+
const NOT_RECEIVED_BACKOFF_BASE_MIN = 2;
|
|
4482
|
+
/**
|
|
4483
|
+
* Does a probe reply say "alive, but the dispatch never reached me"?
|
|
4484
|
+
*
|
|
4485
|
+
* The session answers the liveness probe with NOT-RECEIVED (or the "alive, not
|
|
4486
|
+
* received" spelling) when it is demonstrably live yet has no knowledge of the
|
|
4487
|
+
* work order — the dispatch was reported delivered and was not. That is not
|
|
4488
|
+
* silence (the session is fine) and not death (nothing needs recovering): it is
|
|
4489
|
+
* an UNDELIVERED dispatch, and the honest response is to send it again.
|
|
4490
|
+
*
|
|
4491
|
+
* Anchored to the first line so a reply merely discussing the phrase —
|
|
4492
|
+
* "we discussed not received earlier" — does not trip it.
|
|
4493
|
+
*/
|
|
4494
|
+
function isNotReceivedReply(reply) {
|
|
4495
|
+
if (!reply) return false;
|
|
4496
|
+
const first = reply.split("\n", 1)[0].trim().toLowerCase();
|
|
4497
|
+
return first.startsWith("not-received") || /^alive[,:]\s*not[ -]received/.test(first);
|
|
4498
|
+
}
|
|
4499
|
+
async function handleProbe(task, elapsed, opts, state, now) {
|
|
4448
4500
|
const project = task.owner.project;
|
|
4449
4501
|
const el = elapsed === null ? "unknown" : `${elapsed}m`;
|
|
4450
4502
|
if (opts.dryRun) return {
|
|
@@ -4458,6 +4510,31 @@ async function handleProbe(task, elapsed, opts, state) {
|
|
|
4458
4510
|
const answer = await opts.prober.ask(project, `Are you still working on the task "${task.title}"? Reply in one short line.`);
|
|
4459
4511
|
if (answer.state === "replied" || answer.state === "busy") {
|
|
4460
4512
|
state.failedProbes[task.id] = 0;
|
|
4513
|
+
if (isNotReceivedReply(answer.reply)) {
|
|
4514
|
+
const attempts = state.notReceivedAttempts[task.id] ?? 0;
|
|
4515
|
+
const retryAt = state.notReceivedRetryAt[task.id] ?? 0;
|
|
4516
|
+
if (now < retryAt) return {
|
|
4517
|
+
note: `alive but NOT-RECEIVED — re-dispatch backed off ${Math.round((retryAt - now) / 6e4)}m (try ${attempts})`,
|
|
4518
|
+
stuck: false
|
|
4519
|
+
};
|
|
4520
|
+
if (attempts >= NOT_RECEIVED_MAX_ATTEMPTS) return {
|
|
4521
|
+
note: `alive but NOT-RECEIVED x${attempts} — dispatch never landed, claim left for a human`,
|
|
4522
|
+
stuck: true
|
|
4523
|
+
};
|
|
4524
|
+
const next = attempts + 1;
|
|
4525
|
+
state.notReceivedAttempts[task.id] = next;
|
|
4526
|
+
state.notReceivedRetryAt[task.id] = now + next * NOT_RECEIVED_BACKOFF_BASE_MIN * 6e4;
|
|
4527
|
+
const r = await handleDispatch(task, 0, opts, state, now);
|
|
4528
|
+
return {
|
|
4529
|
+
note: `alive but NOT-RECEIVED — re-dispatched (try ${next}): ${r.note}`,
|
|
4530
|
+
stuck: r.alarm === true,
|
|
4531
|
+
dispatched: true
|
|
4532
|
+
};
|
|
4533
|
+
}
|
|
4534
|
+
if (answer.state === "replied") {
|
|
4535
|
+
delete state.notReceivedAttempts[task.id];
|
|
4536
|
+
delete state.notReceivedRetryAt[task.id];
|
|
4537
|
+
}
|
|
4461
4538
|
const expected = expectedMinutes(state.history[task.id] ?? []);
|
|
4462
4539
|
if (elapsed !== null && elapsed > expected * GROSS_OVERRUN_FACTOR) return {
|
|
4463
4540
|
note: `alive but ${el} against an expected ${expected}m — ${GROSS_OVERRUN_FACTOR}x over, worth a look`,
|
|
@@ -4649,8 +4726,8 @@ function registerBackupCommands(program) {
|
|
|
4649
4726
|
if (existsSync(CONFIG_FILE$1)) {
|
|
4650
4727
|
const dest = join(backupDir, "config.json");
|
|
4651
4728
|
try {
|
|
4652
|
-
const { copyFileSync } = await import("node:fs");
|
|
4653
4729
|
copyFileSync(CONFIG_FILE$1, dest);
|
|
4730
|
+
chmodSync(dest, 384);
|
|
4654
4731
|
results.push({
|
|
4655
4732
|
label: "Config",
|
|
4656
4733
|
path: dest,
|
|
@@ -6482,6 +6559,40 @@ function registerMcpCommands(mcpCmd) {
|
|
|
6482
6559
|
});
|
|
6483
6560
|
}
|
|
6484
6561
|
|
|
6562
|
+
//#endregion
|
|
6563
|
+
//#region src/module-paths.ts
|
|
6564
|
+
/**
|
|
6565
|
+
* module-paths.ts — locate a file relative to the package root from a running module.
|
|
6566
|
+
*
|
|
6567
|
+
* tsdown bundles shared code into chunks emitted directly under dist/ (e.g.
|
|
6568
|
+
* dist/program-*.mjs) rather than always alongside the entry that needs them
|
|
6569
|
+
* (dist/cli/index.mjs, dist/daemon/index.mjs, ...). A fixed "../daemon/index.mjs"
|
|
6570
|
+
* relative to import.meta.url assumes one specific chunk depth and silently
|
|
6571
|
+
* resolves to the wrong file — or a file under the source tree instead of
|
|
6572
|
+
* dist — whenever the bundler's chunking changes. Walking up from the running
|
|
6573
|
+
* module's own directory until `dir/rel` exists is depth-independent, and works
|
|
6574
|
+
* whether `rel` lives under dist/ (built entries) or is a sibling of dist/ at
|
|
6575
|
+
* the package root (files excluded from the bundle, like docker/migrate-sqlite.ts).
|
|
6576
|
+
*/
|
|
6577
|
+
/**
|
|
6578
|
+
* Resolve `rel` by walking up from the directory containing `moduleUrl`,
|
|
6579
|
+
* returning the first `dir/rel` that exists on disk.
|
|
6580
|
+
*
|
|
6581
|
+
* Throws rather than returning a guessed path, so a caller writing a service
|
|
6582
|
+
* file or spawning a process fails loudly instead of pointing at nothing.
|
|
6583
|
+
*/
|
|
6584
|
+
function resolveFromModule(moduleUrl, rel, maxLevels = 8) {
|
|
6585
|
+
let dir = dirname(fileURLToPath(moduleUrl));
|
|
6586
|
+
for (let i = 0; i < maxLevels; i++) {
|
|
6587
|
+
const candidate = join(dir, rel);
|
|
6588
|
+
if (existsSync(candidate)) return candidate;
|
|
6589
|
+
const parent = dirname(dir);
|
|
6590
|
+
if (parent === dir) break;
|
|
6591
|
+
dir = parent;
|
|
6592
|
+
}
|
|
6593
|
+
throw new Error(`cannot locate "${rel}" above ${dirname(fileURLToPath(moduleUrl))} — is the project built? (bun run build)`);
|
|
6594
|
+
}
|
|
6595
|
+
|
|
6485
6596
|
//#endregion
|
|
6486
6597
|
//#region src/cli/commands/daemon-status.ts
|
|
6487
6598
|
/**
|
|
@@ -6548,20 +6659,21 @@ const PLIST_LABEL = "com.pai.pai-daemon";
|
|
|
6548
6659
|
const LAUNCH_AGENTS_DIR = join(HOME$1, "Library", "LaunchAgents");
|
|
6549
6660
|
const PLIST_PATH$1 = join(LAUNCH_AGENTS_DIR, `${PLIST_LABEL}.plist`);
|
|
6550
6661
|
const DAEMON_LOG = daemonLogPath();
|
|
6662
|
+
const SYSTEMD_UNIT_NAME = "pai-daemon.service";
|
|
6663
|
+
const SYSTEMD_USER_DIR = join(HOME$1, ".config", "systemd", "user");
|
|
6664
|
+
const SYSTEMD_UNIT_PATH = join(SYSTEMD_USER_DIR, SYSTEMD_UNIT_NAME);
|
|
6551
6665
|
/**
|
|
6552
6666
|
* Resolve the absolute path to the built daemon entry point.
|
|
6553
|
-
* tsdown
|
|
6554
|
-
*
|
|
6667
|
+
* tsdown may emit this module's own chunk directly under dist/ rather than
|
|
6668
|
+
* under dist/cli/, so a fixed "../daemon/index.mjs" is not reliable — walk up
|
|
6669
|
+
* from this module until dist/daemon/index.mjs is found instead.
|
|
6555
6670
|
*/
|
|
6556
6671
|
function getDaemonBinPath() {
|
|
6557
|
-
return
|
|
6672
|
+
return resolveFromModule(import.meta.url, "dist/daemon/index.mjs");
|
|
6558
6673
|
}
|
|
6559
|
-
/**
|
|
6560
|
-
* Resolve the absolute path to the built MCP shim entry point.
|
|
6561
|
-
* dist/cli/index.mjs → dist/ → dist/daemon-mcp/index.mjs
|
|
6562
|
-
*/
|
|
6674
|
+
/** Resolve the absolute path to the built MCP shim entry point. Same reasoning as getDaemonBinPath. */
|
|
6563
6675
|
function getShimBinPath() {
|
|
6564
|
-
return
|
|
6676
|
+
return resolveFromModule(import.meta.url, "dist/daemon-mcp/index.mjs");
|
|
6565
6677
|
}
|
|
6566
6678
|
function generatePlist(daemonBin) {
|
|
6567
6679
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -6602,6 +6714,33 @@ function generatePlist(daemonBin) {
|
|
|
6602
6714
|
</plist>
|
|
6603
6715
|
`;
|
|
6604
6716
|
}
|
|
6717
|
+
function generateSystemdUnit(daemonBin, nodeBin) {
|
|
6718
|
+
return `[Unit]
|
|
6719
|
+
Description=PAI Daemon
|
|
6720
|
+
After=network.target
|
|
6721
|
+
|
|
6722
|
+
[Service]
|
|
6723
|
+
ExecStart=${nodeBin} ${daemonBin} serve
|
|
6724
|
+
Restart=on-failure
|
|
6725
|
+
|
|
6726
|
+
[Install]
|
|
6727
|
+
WantedBy=default.target
|
|
6728
|
+
`;
|
|
6729
|
+
}
|
|
6730
|
+
/** Warns (does not fail) when the user's systemd instance is not kept alive after logout. */
|
|
6731
|
+
function warnIfLingerDisabled() {
|
|
6732
|
+
const username = userInfo().username;
|
|
6733
|
+
const result = spawnSync("loginctl", [
|
|
6734
|
+
"show-user",
|
|
6735
|
+
username,
|
|
6736
|
+
"-p",
|
|
6737
|
+
"Linger"
|
|
6738
|
+
], { encoding: "utf8" });
|
|
6739
|
+
if (result.status === 0 && result.stdout.trim() !== "Linger=yes") {
|
|
6740
|
+
console.log(warn$1(` Linger is off for ${username} — the daemon stops when you log out.`));
|
|
6741
|
+
console.log(dim$1(` Enable it: loginctl enable-linger ${username}`));
|
|
6742
|
+
}
|
|
6743
|
+
}
|
|
6605
6744
|
async function cmdStatus$1() {
|
|
6606
6745
|
const client = new PaiClient(loadConfig().socketPath);
|
|
6607
6746
|
try {
|
|
@@ -6641,6 +6780,24 @@ async function cmdStatus$1() {
|
|
|
6641
6780
|
}
|
|
6642
6781
|
}
|
|
6643
6782
|
function cmdRestart() {
|
|
6783
|
+
if (process.platform === "linux") {
|
|
6784
|
+
const result = spawnSync("systemctl", [
|
|
6785
|
+
"--user",
|
|
6786
|
+
"restart",
|
|
6787
|
+
SYSTEMD_UNIT_NAME
|
|
6788
|
+
], { encoding: "utf8" });
|
|
6789
|
+
if (result.status === 0) console.log(ok$1("Restarted via systemd."));
|
|
6790
|
+
else {
|
|
6791
|
+
console.error(err(`systemctl restart failed: ${(result.stderr || "").trim()}`));
|
|
6792
|
+
process.exitCode = 1;
|
|
6793
|
+
}
|
|
6794
|
+
return;
|
|
6795
|
+
}
|
|
6796
|
+
if (process.platform !== "darwin") {
|
|
6797
|
+
console.error(err(`Unsupported platform: ${process.platform}. Daemon restart supports macOS (launchd) and Linux (systemd user) only.`));
|
|
6798
|
+
process.exitCode = 1;
|
|
6799
|
+
return;
|
|
6800
|
+
}
|
|
6644
6801
|
try {
|
|
6645
6802
|
const result = spawnSync("pgrep", ["-f", "pai-daemon.*serve"], { encoding: "utf8" });
|
|
6646
6803
|
if (result.status !== 0 || !result.stdout.trim()) {
|
|
@@ -6667,12 +6824,7 @@ function cmdRestart() {
|
|
|
6667
6824
|
process.exitCode = 1;
|
|
6668
6825
|
}
|
|
6669
6826
|
}
|
|
6670
|
-
function
|
|
6671
|
-
const daemonBin = getDaemonBinPath();
|
|
6672
|
-
const shimBin = getShimBinPath();
|
|
6673
|
-
console.log();
|
|
6674
|
-
console.log(bold$1(" PAI Daemon Install"));
|
|
6675
|
-
console.log();
|
|
6827
|
+
function installServiceDarwin(daemonBin) {
|
|
6676
6828
|
if (!existsSync(LAUNCH_AGENTS_DIR)) mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });
|
|
6677
6829
|
const plistContent = generatePlist(daemonBin);
|
|
6678
6830
|
try {
|
|
@@ -6681,7 +6833,7 @@ function cmdInstall() {
|
|
|
6681
6833
|
} catch (e) {
|
|
6682
6834
|
console.error(err(` Failed to write plist: ${e}`));
|
|
6683
6835
|
process.exitCode = 1;
|
|
6684
|
-
return;
|
|
6836
|
+
return false;
|
|
6685
6837
|
}
|
|
6686
6838
|
try {
|
|
6687
6839
|
spawnSync("launchctl", ["unload", PLIST_PATH$1], { encoding: "utf8" });
|
|
@@ -6692,6 +6844,46 @@ function cmdInstall() {
|
|
|
6692
6844
|
console.log(warn$1(" Could not run launchctl. Load manually:"));
|
|
6693
6845
|
console.log(dim$1(` launchctl load ${PLIST_PATH$1}`));
|
|
6694
6846
|
}
|
|
6847
|
+
return true;
|
|
6848
|
+
}
|
|
6849
|
+
function installServiceLinux(daemonBin) {
|
|
6850
|
+
if (!existsSync(SYSTEMD_USER_DIR)) mkdirSync(SYSTEMD_USER_DIR, { recursive: true });
|
|
6851
|
+
const unitContent = generateSystemdUnit(daemonBin, process.execPath);
|
|
6852
|
+
try {
|
|
6853
|
+
writeFileSync(SYSTEMD_UNIT_PATH, unitContent, "utf8");
|
|
6854
|
+
console.log(ok$1(` Wrote systemd unit: ${SYSTEMD_UNIT_PATH}`));
|
|
6855
|
+
} catch (e) {
|
|
6856
|
+
console.error(err(` Failed to write systemd unit: ${e}`));
|
|
6857
|
+
process.exitCode = 1;
|
|
6858
|
+
return false;
|
|
6859
|
+
}
|
|
6860
|
+
spawnSync("systemctl", ["--user", "daemon-reload"], { encoding: "utf8" });
|
|
6861
|
+
const enableResult = spawnSync("systemctl", [
|
|
6862
|
+
"--user",
|
|
6863
|
+
"enable",
|
|
6864
|
+
"--now",
|
|
6865
|
+
SYSTEMD_UNIT_NAME
|
|
6866
|
+
], { encoding: "utf8" });
|
|
6867
|
+
if (enableResult.status === 0) console.log(ok$1(" Enabled and started via systemd."));
|
|
6868
|
+
else console.log(warn$1(` systemctl enable --now: ${(enableResult.stderr || "").trim()}`));
|
|
6869
|
+
warnIfLingerDisabled();
|
|
6870
|
+
return true;
|
|
6871
|
+
}
|
|
6872
|
+
function cmdInstall() {
|
|
6873
|
+
const daemonBin = getDaemonBinPath();
|
|
6874
|
+
const shimBin = getShimBinPath();
|
|
6875
|
+
console.log();
|
|
6876
|
+
console.log(bold$1(" PAI Daemon Install"));
|
|
6877
|
+
console.log();
|
|
6878
|
+
if (process.platform === "darwin") {
|
|
6879
|
+
if (!installServiceDarwin(daemonBin)) return;
|
|
6880
|
+
} else if (process.platform === "linux") {
|
|
6881
|
+
if (!installServiceLinux(daemonBin)) return;
|
|
6882
|
+
} else {
|
|
6883
|
+
console.error(err(` Unsupported platform: ${process.platform}. Daemon install supports macOS (launchd) and Linux (systemd user) only.`));
|
|
6884
|
+
process.exitCode = 1;
|
|
6885
|
+
return;
|
|
6886
|
+
}
|
|
6695
6887
|
const config = readClaudeJson();
|
|
6696
6888
|
if (typeof config.mcpServers !== "object" || config.mcpServers === null) config.mcpServers = {};
|
|
6697
6889
|
const servers = config.mcpServers;
|
|
@@ -6728,10 +6920,7 @@ function cmdInstall() {
|
|
|
6728
6920
|
console.log(dim$1(" Restart Claude Code to activate the daemon-backed PAI tools."));
|
|
6729
6921
|
console.log();
|
|
6730
6922
|
}
|
|
6731
|
-
function
|
|
6732
|
-
console.log();
|
|
6733
|
-
console.log(bold$1(" PAI Daemon Uninstall"));
|
|
6734
|
-
console.log();
|
|
6923
|
+
function uninstallServiceDarwin() {
|
|
6735
6924
|
if (existsSync(PLIST_PATH$1)) {
|
|
6736
6925
|
try {
|
|
6737
6926
|
spawnSync("launchctl", ["unload", PLIST_PATH$1], { encoding: "utf8" });
|
|
@@ -6746,6 +6935,36 @@ function cmdUninstall() {
|
|
|
6746
6935
|
console.log(warn$1(` Could not remove plist: ${e}`));
|
|
6747
6936
|
}
|
|
6748
6937
|
} else console.log(dim$1(" No launchd plist found."));
|
|
6938
|
+
}
|
|
6939
|
+
function uninstallServiceLinux() {
|
|
6940
|
+
if (existsSync(SYSTEMD_UNIT_PATH)) {
|
|
6941
|
+
spawnSync("systemctl", [
|
|
6942
|
+
"--user",
|
|
6943
|
+
"disable",
|
|
6944
|
+
"--now",
|
|
6945
|
+
SYSTEMD_UNIT_NAME
|
|
6946
|
+
], { encoding: "utf8" });
|
|
6947
|
+
console.log(ok$1(" Disabled and stopped via systemd."));
|
|
6948
|
+
try {
|
|
6949
|
+
unlinkSync(SYSTEMD_UNIT_PATH);
|
|
6950
|
+
console.log(ok$1(` Removed unit: ${SYSTEMD_UNIT_PATH}`));
|
|
6951
|
+
} catch (e) {
|
|
6952
|
+
console.log(warn$1(` Could not remove unit: ${e}`));
|
|
6953
|
+
}
|
|
6954
|
+
spawnSync("systemctl", ["--user", "daemon-reload"], { encoding: "utf8" });
|
|
6955
|
+
} else console.log(dim$1(" No systemd unit found."));
|
|
6956
|
+
}
|
|
6957
|
+
function cmdUninstall() {
|
|
6958
|
+
console.log();
|
|
6959
|
+
console.log(bold$1(" PAI Daemon Uninstall"));
|
|
6960
|
+
console.log();
|
|
6961
|
+
if (process.platform === "darwin") uninstallServiceDarwin();
|
|
6962
|
+
else if (process.platform === "linux") uninstallServiceLinux();
|
|
6963
|
+
else {
|
|
6964
|
+
console.error(err(` Unsupported platform: ${process.platform}. Daemon uninstall supports macOS (launchd) and Linux (systemd user) only.`));
|
|
6965
|
+
process.exitCode = 1;
|
|
6966
|
+
return;
|
|
6967
|
+
}
|
|
6749
6968
|
const config = readClaudeJson();
|
|
6750
6969
|
const servers = typeof config.mcpServers === "object" && config.mcpServers !== null ? config.mcpServers : {};
|
|
6751
6970
|
const legacy = servers["pai-legacy"];
|
|
@@ -6769,9 +6988,7 @@ async function cmdMigrate(connectionString) {
|
|
|
6769
6988
|
console.log();
|
|
6770
6989
|
console.log(dim$1(" Running SQLite → PostgreSQL migration..."));
|
|
6771
6990
|
console.log();
|
|
6772
|
-
const
|
|
6773
|
-
const { dirname: pathDirname, join: pathJoin } = await import("node:path");
|
|
6774
|
-
const migrationScript = pathJoin(pathDirname(fileURLToPath(import.meta.url)), "../..", "docker", "migrate-sqlite.ts");
|
|
6991
|
+
const migrationScript = resolveFromModule(import.meta.url, "docker/migrate-sqlite.ts");
|
|
6775
6992
|
const { spawnSync: spawn } = await import("node:child_process");
|
|
6776
6993
|
const spawnArgs = ["tsx", migrationScript];
|
|
6777
6994
|
if (connectionString) spawnArgs.push("--connection-string", connectionString);
|
|
@@ -6833,8 +7050,8 @@ function cmdLogs(opts) {
|
|
|
6833
7050
|
}
|
|
6834
7051
|
function registerDaemonCommands(daemonCmd) {
|
|
6835
7052
|
daemonCmd.command("serve").description("Start the PAI daemon in the foreground").action(async () => {
|
|
6836
|
-
const { serve } = await import("./daemon-
|
|
6837
|
-
const { loadConfig: lc, ensureConfigDir } = await import("./config-
|
|
7053
|
+
const { serve } = await import("./daemon-BppwJtrH.mjs");
|
|
7054
|
+
const { loadConfig: lc, ensureConfigDir } = await import("./config-GceCMUxa.mjs");
|
|
6838
7055
|
ensureConfigDir();
|
|
6839
7056
|
await serve(lc());
|
|
6840
7057
|
});
|
|
@@ -6844,13 +7061,13 @@ function registerDaemonCommands(daemonCmd) {
|
|
|
6844
7061
|
daemonCmd.command("status").description("Query the running daemon status").action(async () => {
|
|
6845
7062
|
await cmdStatus$1();
|
|
6846
7063
|
});
|
|
6847
|
-
daemonCmd.command("restart").description("
|
|
7064
|
+
daemonCmd.command("restart").description("Restart the running daemon (launchd on macOS, systemd on Linux)").action(() => {
|
|
6848
7065
|
cmdRestart();
|
|
6849
7066
|
});
|
|
6850
|
-
daemonCmd.command("install").description("Install daemon as a launchd
|
|
7067
|
+
daemonCmd.command("install").description("Install daemon as a service (launchd/systemd) and update ~/.claude.json to use the shim").action(() => {
|
|
6851
7068
|
cmdInstall();
|
|
6852
7069
|
});
|
|
6853
|
-
daemonCmd.command("uninstall").description("Remove the
|
|
7070
|
+
daemonCmd.command("uninstall").description("Remove the daemon service (launchd/systemd) and revert to direct MCP").action(() => {
|
|
6854
7071
|
cmdUninstall();
|
|
6855
7072
|
});
|
|
6856
7073
|
daemonCmd.command("keepalive").description("Show interactive-session cache keepalive config, per-session beat counters, and recent ledger lines").action(() => {
|
|
@@ -6993,6 +7210,7 @@ function registerRestoreCommands(program) {
|
|
|
6993
7210
|
if (hasConfig) try {
|
|
6994
7211
|
mkdirSync(dirname(CONFIG_FILE), { recursive: true });
|
|
6995
7212
|
copyFileSync(join(resolvedDir, "config.json"), CONFIG_FILE);
|
|
7213
|
+
chmodSync(CONFIG_FILE, 384);
|
|
6996
7214
|
results.push({
|
|
6997
7215
|
label: "Config",
|
|
6998
7216
|
status: ok$1("restored")
|
|
@@ -14301,6 +14519,12 @@ function generateSchedulePlist(intervalSecs, cli) {
|
|
|
14301
14519
|
`;
|
|
14302
14520
|
}
|
|
14303
14521
|
function installSchedule(intervalSecs = DEFAULT_INTERVAL_SECS) {
|
|
14522
|
+
if (process.platform !== "darwin") return {
|
|
14523
|
+
plistPath: SCHEDULE_PLIST,
|
|
14524
|
+
intervalSecs,
|
|
14525
|
+
loaded: false,
|
|
14526
|
+
message: "scheduler install supports launchd (macOS) only"
|
|
14527
|
+
};
|
|
14304
14528
|
if (!existsSync(LAUNCH_AGENTS)) mkdirSync(LAUNCH_AGENTS, { recursive: true });
|
|
14305
14529
|
writeFileSync(SCHEDULE_PLIST, generateSchedulePlist(intervalSecs, cliPath()), "utf8");
|
|
14306
14530
|
spawnSync("launchctl", ["unload", SCHEDULE_PLIST], { encoding: "utf8" });
|
|
@@ -16389,7 +16613,7 @@ async function getSessionTags(registryBackend, sessionId) {
|
|
|
16389
16613
|
* Session CRUD commands: list, info, rename, slug, tag, route, active, auto-route.
|
|
16390
16614
|
*/
|
|
16391
16615
|
async function cmdList(projectSlug, opts) {
|
|
16392
|
-
const { getRegistryBackend } = await import("./factory-
|
|
16616
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16393
16617
|
const registryBackend = await getRegistryBackend();
|
|
16394
16618
|
const limit = parseInt(opts.limit ?? "20", 10);
|
|
16395
16619
|
let project;
|
|
@@ -16454,7 +16678,7 @@ async function cmdList(projectSlug, opts) {
|
|
|
16454
16678
|
console.log(dim$1(` ${rows.length} session(s) shown (limit: ${limit})`));
|
|
16455
16679
|
}
|
|
16456
16680
|
async function cmdInfo(projectSlug, sessionNumber) {
|
|
16457
|
-
const { getRegistryBackend } = await import("./factory-
|
|
16681
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16458
16682
|
const registryBackend = await getRegistryBackend();
|
|
16459
16683
|
const project = await getProject$1(registryBackend, projectSlug);
|
|
16460
16684
|
if (!project) {
|
|
@@ -16478,7 +16702,7 @@ async function cmdInfo(projectSlug, sessionNumber) {
|
|
|
16478
16702
|
console.log();
|
|
16479
16703
|
}
|
|
16480
16704
|
async function cmdRename(projectSlug, numberOrLatest, newSlug) {
|
|
16481
|
-
const { getRegistryBackend } = await import("./factory-
|
|
16705
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16482
16706
|
await cmdRenameWith(await getRegistryBackend(), projectSlug, numberOrLatest, newSlug);
|
|
16483
16707
|
}
|
|
16484
16708
|
async function cmdRenameWith(registryBackend, projectSlug, numberOrLatest, newSlug) {
|
|
@@ -16541,7 +16765,7 @@ async function cmdRenameWith(registryBackend, projectSlug, numberOrLatest, newSl
|
|
|
16541
16765
|
console.log();
|
|
16542
16766
|
}
|
|
16543
16767
|
async function cmdSlug(projectSlug, numberOrLatest, opts) {
|
|
16544
|
-
const { getRegistryBackend } = await import("./factory-
|
|
16768
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16545
16769
|
const registryBackend = await getRegistryBackend();
|
|
16546
16770
|
const project = await getProject$1(registryBackend, projectSlug);
|
|
16547
16771
|
if (!project) {
|
|
@@ -16571,7 +16795,7 @@ async function cmdSlug(projectSlug, numberOrLatest, opts) {
|
|
|
16571
16795
|
}
|
|
16572
16796
|
}
|
|
16573
16797
|
async function cmdTag(projectSlug, sessionNumber, rawTags) {
|
|
16574
|
-
const { getRegistryBackend } = await import("./factory-
|
|
16798
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16575
16799
|
const registryBackend = await getRegistryBackend();
|
|
16576
16800
|
const project = await getProject$1(registryBackend, projectSlug);
|
|
16577
16801
|
if (!project) {
|
|
@@ -16611,7 +16835,7 @@ async function cmdTag(projectSlug, sessionNumber, rawTags) {
|
|
|
16611
16835
|
console.log();
|
|
16612
16836
|
}
|
|
16613
16837
|
async function cmdRoute(projectSlug, sessionNumber, targetProjectSlug, opts) {
|
|
16614
|
-
const { getRegistryBackend } = await import("./factory-
|
|
16838
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16615
16839
|
const registryBackend = await getRegistryBackend();
|
|
16616
16840
|
const project = await getProject$1(registryBackend, projectSlug);
|
|
16617
16841
|
if (!project) {
|
|
@@ -16653,7 +16877,7 @@ async function cmdRoute(projectSlug, sessionNumber, targetProjectSlug, opts) {
|
|
|
16653
16877
|
console.log();
|
|
16654
16878
|
}
|
|
16655
16879
|
async function cmdActive(opts) {
|
|
16656
|
-
const { getRegistryBackend } = await import("./factory-
|
|
16880
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16657
16881
|
const registryBackend = await getRegistryBackend();
|
|
16658
16882
|
const minutes = parseInt(opts.minutes ?? "60", 10);
|
|
16659
16883
|
const cutoff = Date.now() - minutes * 60 * 1e3;
|
|
@@ -16741,8 +16965,8 @@ async function cmdActive(opts) {
|
|
|
16741
16965
|
}
|
|
16742
16966
|
async function cmdAutoRoute(opts) {
|
|
16743
16967
|
const { autoRoute, formatAutoRouteJson } = await import("./auto-route-CF8WNaoy.mjs");
|
|
16744
|
-
const { getRegistryBackend, createStorageBackend } = await import("./factory-
|
|
16745
|
-
const { loadConfig } = await import("./config-
|
|
16968
|
+
const { getRegistryBackend, createStorageBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16969
|
+
const { loadConfig } = await import("./config-GceCMUxa.mjs");
|
|
16746
16970
|
const config = loadConfig();
|
|
16747
16971
|
const registryBackend = await getRegistryBackend();
|
|
16748
16972
|
const federation = await createStorageBackend(config);
|
|
@@ -16978,7 +17202,7 @@ async function cmdPause(opts) {
|
|
|
16978
17202
|
process.exitCode = 1;
|
|
16979
17203
|
return;
|
|
16980
17204
|
}
|
|
16981
|
-
const { getRegistryBackend } = await import("./factory-
|
|
17205
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
16982
17206
|
const registryBackend = await getRegistryBackend();
|
|
16983
17207
|
const cwd = process.cwd();
|
|
16984
17208
|
const project = await resolveProjectByCwd(registryBackend, cwd);
|
|
@@ -17373,7 +17597,7 @@ function buildStopBody(project, sessionId) {
|
|
|
17373
17597
|
}
|
|
17374
17598
|
}
|
|
17375
17599
|
async function cmdHandover(projectSlug, numberOrLatest, sessionId) {
|
|
17376
|
-
const { getRegistryBackend } = await import("./factory-
|
|
17600
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
17377
17601
|
const registryBackend = await getRegistryBackend();
|
|
17378
17602
|
let project;
|
|
17379
17603
|
if (projectSlug) {
|
|
@@ -17669,7 +17893,7 @@ function touchSentinel(rootPath) {
|
|
|
17669
17893
|
async function cmdAutosave(opts) {
|
|
17670
17894
|
const minGap = parseInt(opts.minGap ?? String(DEFAULT_MIN_GAP), 10);
|
|
17671
17895
|
const cwd = process.cwd();
|
|
17672
|
-
const { getRegistryBackend } = await import("./factory-
|
|
17896
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
17673
17897
|
const registryBackend = await getRegistryBackend();
|
|
17674
17898
|
const project = await resolveProjectByCwd(registryBackend, cwd);
|
|
17675
17899
|
if (!project) return;
|
|
@@ -17858,23 +18082,24 @@ async function cmdRecent(opts) {
|
|
|
17858
18082
|
* (see probeResume in lib/launch.ts — the filesystem answers,
|
|
17859
18083
|
* and only an unrecognised layout falls back to spawning claude)
|
|
17860
18084
|
* b. If probe succeeds:
|
|
17861
|
-
* exec claude --resume <uuid> --name "<friendlyName>" "/Name <friendlyName
|
|
18085
|
+
* exec claude --resume <uuid> --name "<friendlyName>" "/Name <friendlyName>"
|
|
17862
18086
|
* — through the provider the transcript ran on, when its model
|
|
17863
18087
|
* matches one (providerResumePlan in lib/launch.ts)
|
|
17864
18088
|
* c. Else (probe failed):
|
|
17865
18089
|
* print clear stderr line: "Resume failed. Starting fresh session in same dir."
|
|
17866
|
-
* exec claude --name "<friendlyName>" "/Name <friendlyName
|
|
18090
|
+
* exec claude --name "<friendlyName>" "/Name <friendlyName>"
|
|
17867
18091
|
* 4. Else (no uuid known):
|
|
17868
|
-
* exec claude --name "<friendlyName>" "/Name <friendlyName
|
|
18092
|
+
* exec claude --name "<friendlyName>" "/Name <friendlyName>"
|
|
17869
18093
|
*
|
|
17870
18094
|
* Steps 3 and 4 are launchInDir's, shared — this file no longer carries its
|
|
17871
18095
|
* own copy of the spawn dance.
|
|
17872
18096
|
*
|
|
17873
18097
|
* Why both --name AND /Name?
|
|
17874
18098
|
* --name <friendlyName> → sets Claude Code's internal session label
|
|
17875
|
-
* "/Name <friendlyName
|
|
17876
|
-
* iTerm tab title, statusline, and AIBroker session registry
|
|
17877
|
-
*
|
|
18099
|
+
* "/Name <friendlyName>" → runs the /Name slash command via AIBroker, which updates
|
|
18100
|
+
* iTerm tab title, statusline, and AIBroker session registry.
|
|
18101
|
+
* No trailing `go`: the operator types it by hand when the
|
|
18102
|
+
* TODO.md handover is wanted
|
|
17878
18103
|
*
|
|
17879
18104
|
* The probe is two `existsSync` calls on the happy path. On the fallback path, total latency
|
|
17880
18105
|
* is the same as a fresh start.
|
|
@@ -17922,7 +18147,7 @@ async function cmdGoto(query, opts) {
|
|
|
17922
18147
|
if (resumableUuid) {
|
|
17923
18148
|
const plan = providerResumePlan(resumableUuid, projectDir);
|
|
17924
18149
|
const argvResume = resumeArgvText(resumableUuid, name, plan);
|
|
17925
|
-
const argvFresh = `claude --name "${name}" "
|
|
18150
|
+
const argvFresh = `claude --name "${name}" "${launchPrompt(name)}"`;
|
|
17926
18151
|
console.log("\n" + chalk.bold("Dry run — would probe then exec (RESUME path):") + "\n");
|
|
17927
18152
|
console.log(` cwd: ${chalk.cyan(projectDir)}`);
|
|
17928
18153
|
console.log(` probe: claude --resume ${resumableUuid} --print --output-format=json "_"`);
|
|
@@ -17936,7 +18161,7 @@ async function cmdGoto(query, opts) {
|
|
|
17936
18161
|
console.log(` sys: ${resumableSession.topLevelSystemLines} system lines`);
|
|
17937
18162
|
}
|
|
17938
18163
|
} else {
|
|
17939
|
-
const argvFresh = `claude --name "${name}" "
|
|
18164
|
+
const argvFresh = `claude --name "${name}" "${launchPrompt(name)}"`;
|
|
17940
18165
|
console.log("\n" + chalk.bold("Dry run — would exec (FRESH path, no resumable UUID):") + "\n");
|
|
17941
18166
|
console.log(` cwd: ${chalk.cyan(projectDir)}`);
|
|
17942
18167
|
console.log(` argv: ${chalk.white(argvFresh)}`);
|
|
@@ -18204,7 +18429,7 @@ function registerSessionCommands(sessionCmd) {
|
|
|
18204
18429
|
process.stderr.write("Deprecated: `pai session recent` — use `pai session list` or `pai sessions` instead.\n");
|
|
18205
18430
|
await cmdRecent(opts);
|
|
18206
18431
|
});
|
|
18207
|
-
sessionCmd.command("goto <name-or-id>").description("Go to a session: resume if a resumable snapshot exists, start fresh otherwise.\nRecommended short form: pai resume <name>\nResolves by clc/registry name (case-insensitive) or UUID prefix.\nSends '/Name <name
|
|
18432
|
+
sessionCmd.command("goto <name-or-id>").description("Go to a session: resume if a resumable snapshot exists, start fresh otherwise.\nRecommended short form: pai resume <name>\nResolves by clc/registry name (case-insensitive) or UUID prefix.\nSends '/Name <name>' as the initial prompt to label the session.").option("--skip-name", "Do not prepend /Name to set the session name in chrome").option("--skip-go", "Deprecated no-op: 'go' is no longer appended — type it by hand when wanted").option("--dry-run", "Print the exact argv and cwd, then exit without launching").action(async (nameOrId, opts) => {
|
|
18208
18433
|
process.stderr.write("Note: `pai session goto` works but `pai resume` is the new shorter form.\n");
|
|
18209
18434
|
await cmdGoto(nameOrId, {
|
|
18210
18435
|
noName: opts.skipName,
|
|
@@ -18489,10 +18714,10 @@ function registerWorkerProviderCommands(providersCmd) {
|
|
|
18489
18714
|
fail$4(e);
|
|
18490
18715
|
}
|
|
18491
18716
|
});
|
|
18492
|
-
providersCmd.command("use <name>").description("Make this provider the active one
|
|
18717
|
+
providersCmd.command("use <name>").description("Make this provider the active one, re-pointing every class pinned to a provider").action((name) => {
|
|
18493
18718
|
try {
|
|
18494
|
-
useProvider(name);
|
|
18495
|
-
console.log(ok$1(`active provider: ${name}`));
|
|
18719
|
+
const { repointed } = useProvider(name);
|
|
18720
|
+
console.log(ok$1(`active provider: ${name}${repointed ? `; ${repointed} class(es) re-pointed` : ""}`));
|
|
18496
18721
|
} catch (e) {
|
|
18497
18722
|
fail$4(e);
|
|
18498
18723
|
}
|
|
@@ -19107,27 +19332,32 @@ function registerWorkerCommands(workerCmd) {
|
|
|
19107
19332
|
fail(e);
|
|
19108
19333
|
}
|
|
19109
19334
|
});
|
|
19110
|
-
workerCmd.command("controls <id> <who>").description("Hand the desktop controls (clickr) to a worker or take them back.\n<who> is `you` (the
|
|
19335
|
+
workerCmd.command("controls <id> <who>").description("Hand the desktop controls (clickr) to a worker or take them back.\n<who> is `you` (<id> becomes the exclusive controls holder; needs clickr with\n--agent support) or `me` (the operator takes them back);\ninside a worker's pane, typing \"your controls\" does the same.").action((id, who) => {
|
|
19111
19336
|
try {
|
|
19112
19337
|
if (who !== "you" && who !== "me") {
|
|
19113
19338
|
fail(/* @__PURE__ */ new Error(`<who> must be "you" or "me"`));
|
|
19114
19339
|
return;
|
|
19115
19340
|
}
|
|
19116
|
-
|
|
19341
|
+
const logDir = currentLogDir();
|
|
19342
|
+
const status = loadStatus(logDir, id);
|
|
19343
|
+
if (!status) {
|
|
19117
19344
|
fail(/* @__PURE__ */ new Error(`no worker named "${id}"`));
|
|
19118
19345
|
return;
|
|
19119
19346
|
}
|
|
19120
|
-
const proc = spawn("clickr",
|
|
19347
|
+
const proc = spawn("clickr", clickrControlsArgv(id, who, status.pid), { stdio: "inherit" });
|
|
19121
19348
|
proc.on("error", (e) => fail(/* @__PURE__ */ new Error(`cannot run clickr controls: ${e.message} (is clickr installed?)`)));
|
|
19122
19349
|
proc.on("close", (code) => {
|
|
19123
|
-
if (code === 0)
|
|
19350
|
+
if (code === 0) {
|
|
19351
|
+
if (who === "you") markControlsHeld(logDir, id);
|
|
19352
|
+
console.log(`controls → ${who === "you" ? `${id} (exclusive; needs clickr with --agent support)` : "operator"}`);
|
|
19353
|
+
}
|
|
19124
19354
|
process.exitCode = code ?? 1;
|
|
19125
19355
|
});
|
|
19126
19356
|
} catch (e) {
|
|
19127
19357
|
fail(e);
|
|
19128
19358
|
}
|
|
19129
19359
|
});
|
|
19130
|
-
workerCmd.command("resume <id> <text>").description("Continue a finished worker on the same provider: claude --resume <session>").option("--print-id", "Print the new worker id on its own line (pane follow handoff)").option("--no-pane", "Do not open a follow pane for the resumed worker").action(async (id, text, opts) => {
|
|
19360
|
+
workerCmd.command("resume <id> <text>").description("Continue a finished worker on the same provider: claude --resume <session>").option("--print-id", "Print the new worker id on its own line (pane follow handoff)").option("--no-pane", "Do not open a follow pane for the resumed worker").option("--output-format <fmt>", "text (default), json or stream-json — same as `run`").option("--label <text>", "Short task label (default: \"↩ <old label>\")").action(async (id, text, opts) => {
|
|
19131
19361
|
try {
|
|
19132
19362
|
const old = loadStatus(currentLogDir(), id);
|
|
19133
19363
|
if (!old) {
|
|
@@ -19138,18 +19368,20 @@ function registerWorkerCommands(workerCmd) {
|
|
|
19138
19368
|
fail(/* @__PURE__ */ new Error(`worker ${id} recorded no Claude session id — it predates resume support or ran through an engine that does not expose one`));
|
|
19139
19369
|
return;
|
|
19140
19370
|
}
|
|
19371
|
+
const claudeArgs = [
|
|
19372
|
+
"--resume",
|
|
19373
|
+
old.claudeSession,
|
|
19374
|
+
"-p",
|
|
19375
|
+
text
|
|
19376
|
+
];
|
|
19377
|
+
if (opts.outputFormat !== void 0) claudeArgs.push("--output-format", opts.outputFormat);
|
|
19141
19378
|
let newId = "";
|
|
19142
19379
|
const rc = await runWorker({
|
|
19143
19380
|
providerFlag: old.provider,
|
|
19144
19381
|
modelFlag: old.model,
|
|
19145
|
-
label: `↩ ${old.label}`,
|
|
19382
|
+
label: opts.label || `↩ ${old.label}`,
|
|
19146
19383
|
noPane: opts.pane === false,
|
|
19147
|
-
claudeArgs
|
|
19148
|
-
"--resume",
|
|
19149
|
-
old.claudeSession,
|
|
19150
|
-
"-p",
|
|
19151
|
-
text
|
|
19152
|
-
],
|
|
19384
|
+
claudeArgs,
|
|
19153
19385
|
onWorkerStart: (wid) => {
|
|
19154
19386
|
newId = wid;
|
|
19155
19387
|
}
|
|
@@ -19937,8 +20169,8 @@ async function analyzeProject(registryBackend, project) {
|
|
|
19937
20169
|
async function countVectorDbPaths(oldPaths) {
|
|
19938
20170
|
if (oldPaths.length === 0) return 0;
|
|
19939
20171
|
try {
|
|
19940
|
-
const { loadConfig } = await import("./config-
|
|
19941
|
-
const { createStorageBackend } = await import("./factory-
|
|
20172
|
+
const { loadConfig } = await import("./config-GceCMUxa.mjs");
|
|
20173
|
+
const { createStorageBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
19942
20174
|
const config = loadConfig();
|
|
19943
20175
|
if (config.storageBackend !== "postgres") return 0;
|
|
19944
20176
|
const backend = await createStorageBackend(config);
|
|
@@ -19955,8 +20187,8 @@ async function countVectorDbPaths(oldPaths) {
|
|
|
19955
20187
|
async function updateVectorDbPaths(moves) {
|
|
19956
20188
|
if (moves.length === 0) return 0;
|
|
19957
20189
|
try {
|
|
19958
|
-
const { loadConfig } = await import("./config-
|
|
19959
|
-
const { createStorageBackend } = await import("./factory-
|
|
20190
|
+
const { loadConfig } = await import("./config-GceCMUxa.mjs");
|
|
20191
|
+
const { createStorageBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
19960
20192
|
const config = loadConfig();
|
|
19961
20193
|
if (config.storageBackend !== "postgres") return 0;
|
|
19962
20194
|
const backend = await createStorageBackend(config);
|
|
@@ -20043,7 +20275,7 @@ async function displayDryRun(plans) {
|
|
|
20043
20275
|
console.log();
|
|
20044
20276
|
}
|
|
20045
20277
|
async function executeCleanup(plans, skipReindex) {
|
|
20046
|
-
const { getRegistryBackend } = await import("./factory-
|
|
20278
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
20047
20279
|
const registryBackend = await getRegistryBackend();
|
|
20048
20280
|
let deleted = 0;
|
|
20049
20281
|
let renamed = 0;
|
|
@@ -20240,7 +20472,7 @@ async function executeCleanup(plans, skipReindex) {
|
|
|
20240
20472
|
//#region src/cli/commands/session-cleanup/index.ts
|
|
20241
20473
|
function registerSessionCleanupCommand(sessionCmd) {
|
|
20242
20474
|
sessionCmd.command("cleanup [project-slug]").description("Clean up session notes: delete empties, auto-name unnamed, move into YYYY/MM/ hierarchy, renumber").option("--execute", "Actually perform the cleanup (default is dry-run)").option("--no-renumber", "Skip renumbering sessions after deletions").option("--no-reindex", "Skip triggering memory re-index after moves").action(async (projectSlug, opts) => {
|
|
20243
|
-
const { getRegistryBackend } = await import("./factory-
|
|
20475
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
20244
20476
|
const registryBackend = await getRegistryBackend();
|
|
20245
20477
|
const dryRun = !opts.execute;
|
|
20246
20478
|
const skipReindex = opts.reindex === false;
|
|
@@ -20310,7 +20542,7 @@ function finalizeNote(notePath) {
|
|
|
20310
20542
|
}
|
|
20311
20543
|
async function cmdEnd(opts) {
|
|
20312
20544
|
await cmdPause(opts);
|
|
20313
|
-
const { getRegistryBackend } = await import("./factory-
|
|
20545
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
20314
20546
|
const registryBackend = await getRegistryBackend();
|
|
20315
20547
|
const cwd = process.cwd();
|
|
20316
20548
|
const project = await registryBackend.findProjectByCwdPrefix(cwd);
|
|
@@ -20758,7 +20990,7 @@ async function cmdFind(query, opts) {
|
|
|
20758
20990
|
*/
|
|
20759
20991
|
async function getProjects(includeArchived) {
|
|
20760
20992
|
try {
|
|
20761
|
-
const { getRegistryBackend } = await import("./factory-
|
|
20993
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
20762
20994
|
const rows = await (await getRegistryBackend()).listProjectsWithSessionStats();
|
|
20763
20995
|
return includeArchived ? rows : rows.filter((p) => p.status === "active");
|
|
20764
20996
|
} catch {
|
|
@@ -21232,7 +21464,7 @@ async function cmdPick(opts = {}) {
|
|
|
21232
21464
|
const onRemove = async (rec) => {
|
|
21233
21465
|
if (!rec.slug) return false;
|
|
21234
21466
|
try {
|
|
21235
|
-
const { getRegistryBackend } = await import("./factory-
|
|
21467
|
+
const { getRegistryBackend } = await import("./factory-D6I2jmjQ.mjs");
|
|
21236
21468
|
const registryBackend = await getRegistryBackend();
|
|
21237
21469
|
const project = await registryBackend.getProjectBySlug(rec.slug);
|
|
21238
21470
|
if (!project || project.status !== "active") return false;
|
|
@@ -21517,4 +21749,4 @@ claude() {
|
|
|
21517
21749
|
|
|
21518
21750
|
//#endregion
|
|
21519
21751
|
export { drainStdio as n, buildProgram as t };
|
|
21520
|
-
//# sourceMappingURL=program-
|
|
21752
|
+
//# sourceMappingURL=program-QSuci3RH.mjs.map
|