talon-agent 4.3.1 → 4.3.3

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.
Files changed (133) hide show
  1. package/package.json +1 -1
  2. package/src/app.ts +1 -1
  3. package/src/backend/claude-sdk/doctor.ts +1 -1
  4. package/src/backend/codex/doctor.ts +1 -1
  5. package/src/backend/openai-agents/doctor.ts +1 -1
  6. package/src/bootstrap.ts +3 -3
  7. package/src/cli/doctor.ts +1 -1
  8. package/src/cli/skill.ts +2 -2
  9. package/src/core/agent-runtime/backend-registry.ts +1 -1
  10. package/src/core/auth/expiry-monitor.ts +1 -1
  11. package/src/core/background/cron-spec.ts +1 -1
  12. package/src/core/background/cron.ts +1 -1
  13. package/src/core/background/heartbeat/agent.ts +1 -1
  14. package/src/core/background/triggers/command.ts +1 -1
  15. package/src/core/background/triggers/exit.ts +1 -1
  16. package/src/core/background/triggers/output.ts +1 -1
  17. package/src/core/background/triggers/resume.ts +1 -1
  18. package/src/core/background/triggers/spawn.ts +1 -1
  19. package/src/core/{doctor.ts → doctor/index.ts} +11 -11
  20. package/src/core/engine/gateway-actions/cron.ts +2 -2
  21. package/src/core/engine/gateway-actions/goals.ts +2 -2
  22. package/src/core/engine/gateway-actions/scripts.ts +1 -1
  23. package/src/core/engine/gateway-actions/skills.ts +1 -1
  24. package/src/core/engine/gateway-actions/triggers.ts +2 -2
  25. package/src/core/engine/gateway-actions/{shared.ts → validation.ts} +2 -2
  26. package/src/core/{notify.ts → frontend-runtime/admin-notify.ts} +1 -1
  27. package/src/core/plugin/native-runtimes.ts +1 -1
  28. package/src/core/prompt/assemble.ts +2 -2
  29. package/src/core/scripts/runner.ts +1 -1
  30. package/src/core/soul/forgetting.ts +2 -2
  31. package/src/core/soul/salience.ts +8 -4
  32. package/src/frontend/discord/actions/{shared.ts → buttons.ts} +3 -56
  33. package/src/frontend/discord/actions/channels.ts +34 -0
  34. package/src/frontend/discord/actions/chat-info.ts +1 -1
  35. package/src/frontend/discord/actions/index.ts +1 -1
  36. package/src/frontend/discord/actions/media.ts +1 -1
  37. package/src/frontend/discord/actions/messaging.ts +4 -2
  38. package/src/frontend/discord/actions/try-action.ts +24 -0
  39. package/src/frontend/discord/admin.ts +2 -2
  40. package/src/frontend/discord/callbacks/components/settings.ts +1 -1
  41. package/src/frontend/discord/callbacks/modals.ts +1 -1
  42. package/src/frontend/discord/commands/admin.ts +3 -3
  43. package/src/frontend/discord/commands/info.ts +2 -2
  44. package/src/frontend/discord/commands/{shared.ts → interaction.ts} +2 -1
  45. package/src/frontend/discord/commands/router.ts +1 -1
  46. package/src/frontend/discord/commands/session.ts +2 -2
  47. package/src/frontend/discord/commands/settings.ts +2 -2
  48. package/src/frontend/discord/{helpers.ts → render.ts} +3 -2
  49. package/src/frontend/native/extensions.ts +1 -1
  50. package/src/frontend/teams/chat-discovery.ts +69 -0
  51. package/src/frontend/teams/commands.ts +141 -0
  52. package/src/frontend/teams/index.ts +24 -350
  53. package/src/frontend/teams/outbound.ts +44 -0
  54. package/src/frontend/teams/poll.ts +101 -0
  55. package/src/frontend/teams/runtime.ts +51 -0
  56. package/src/frontend/teams/turn.ts +97 -0
  57. package/src/frontend/telegram/actions/index.ts +1 -1
  58. package/src/frontend/telegram/actions/messaging.ts +1 -1
  59. package/src/frontend/telegram/actions/moderation/chat.ts +63 -0
  60. package/src/frontend/telegram/actions/moderation/index.ts +74 -0
  61. package/src/frontend/telegram/actions/moderation/members.ts +77 -0
  62. package/src/frontend/telegram/actions/moderation/permissions.ts +69 -0
  63. package/src/frontend/telegram/actions/moderation/topics.ts +48 -0
  64. package/src/frontend/telegram/actions/moderation/types.ts +16 -0
  65. package/src/frontend/telegram/actions/shared.ts +4 -4
  66. package/src/frontend/telegram/admin/background.ts +66 -0
  67. package/src/frontend/telegram/admin/chunked-reply.ts +20 -0
  68. package/src/frontend/telegram/admin/health.ts +81 -0
  69. package/src/frontend/telegram/admin/sessions.ts +105 -0
  70. package/src/frontend/telegram/admin.ts +56 -261
  71. package/src/frontend/telegram/callbacks/model/backend.ts +156 -0
  72. package/src/frontend/telegram/callbacks/model/control.ts +29 -0
  73. package/src/frontend/telegram/callbacks/model/nav.ts +54 -0
  74. package/src/frontend/telegram/callbacks/model/select.ts +100 -0
  75. package/src/frontend/telegram/callbacks/model/types.ts +39 -0
  76. package/src/frontend/telegram/callbacks/model/views.ts +116 -0
  77. package/src/frontend/telegram/callbacks/model.ts +61 -331
  78. package/src/frontend/telegram/commands/admin.ts +108 -77
  79. package/src/frontend/telegram/commands/settings.ts +65 -43
  80. package/src/frontend/telegram/commands/whatsapp-pairing.ts +1 -1
  81. package/src/frontend/telegram/helpers/diagnostics.ts +1 -1
  82. package/src/frontend/telegram/middleware.ts +166 -201
  83. package/src/frontend/telegram/sticker-library.ts +2 -2
  84. package/src/frontend/terminal/builtins/context.ts +184 -0
  85. package/src/frontend/terminal/builtins/help.ts +35 -0
  86. package/src/frontend/terminal/builtins/index.ts +23 -0
  87. package/src/frontend/terminal/builtins/model.ts +198 -0
  88. package/src/frontend/terminal/builtins/session.ts +101 -0
  89. package/src/frontend/terminal/builtins/status.ts +202 -0
  90. package/src/frontend/terminal/command-registry.ts +80 -0
  91. package/src/frontend/terminal/commands.ts +11 -674
  92. package/src/frontend/terminal/input/history.ts +64 -0
  93. package/src/frontend/terminal/input/keys.ts +143 -0
  94. package/src/frontend/terminal/input/parts.ts +33 -0
  95. package/src/frontend/terminal/input/paste.ts +53 -0
  96. package/src/frontend/terminal/input/render.ts +42 -0
  97. package/src/frontend/terminal/input/state.ts +60 -0
  98. package/src/frontend/terminal/input.ts +27 -342
  99. package/src/frontend/whatsapp/actions/account.ts +3 -6
  100. package/src/frontend/whatsapp/actions/chat-info.ts +2 -1
  101. package/src/frontend/whatsapp/actions/coerce.ts +30 -0
  102. package/src/frontend/whatsapp/actions/history.ts +1 -1
  103. package/src/frontend/whatsapp/actions/media-upload.ts +82 -0
  104. package/src/frontend/whatsapp/actions/media.ts +3 -8
  105. package/src/frontend/whatsapp/actions/messaging.ts +2 -7
  106. package/src/frontend/whatsapp/actions/moderation.ts +2 -1
  107. package/src/frontend/whatsapp/actions/{shared.ts → send.ts} +4 -124
  108. package/src/frontend/whatsapp/actions/try-action.ts +24 -0
  109. package/src/frontend/whatsapp/commands.ts +1 -1
  110. package/src/frontend/whatsapp/connection.ts +1 -1
  111. package/src/frontend/whatsapp/inbound.ts +1 -1
  112. package/src/frontend/whatsapp/index.ts +2 -2
  113. package/src/frontend/whatsapp/pairing-service.ts +1 -1
  114. package/src/plugins/github/provision.ts +1 -1
  115. package/src/plugins/mempalace/provision.ts +1 -1
  116. package/src/plugins/playwright/provision.ts +1 -1
  117. package/src/storage/repositories/cron-repo.ts +1 -1
  118. package/src/storage/repositories/goals-repo.ts +1 -1
  119. package/src/storage/repositories/scripts-repo.ts +1 -1
  120. package/src/storage/repositories/triggers-repo.ts +1 -1
  121. package/src/storage/sql/schema.sql +1 -1
  122. package/src/storage/sql/statements.generated.ts +2 -2
  123. package/src/storage/sql/triggers.sql +1 -1
  124. package/src/frontend/telegram/actions/moderation.ts +0 -255
  125. /package/src/core/{doctor-types.ts → doctor/types.ts} +0 -0
  126. /package/src/core/{pairing-broker.ts → frontend-runtime/pairing-broker.ts} +0 -0
  127. /package/src/storage/{cron-store.ts → cron.ts} +0 -0
  128. /package/src/storage/{goal-store.ts → goals.ts} +0 -0
  129. /package/src/storage/{scheduled-store.ts → scheduled.ts} +0 -0
  130. /package/src/storage/{script-store.ts → scripts.ts} +0 -0
  131. /package/src/storage/{skill-store.ts → skills.ts} +0 -0
  132. /package/src/storage/{sticker-store.ts → stickers.ts} +0 -0
  133. /package/src/storage/{trigger-store.ts → triggers.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "talon-agent",
3
- "version": "4.3.1",
3
+ "version": "4.3.3",
4
4
  "description": "Multi-frontend AI agent with full tool access, streaming, cron jobs, and plugin system",
5
5
  "author": "Dylan Neve",
6
6
  "license": "MIT",
package/src/app.ts CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  runStartupCatchup,
24
24
  } from "./core/background/cron.js";
25
25
  import { shutdownTriggers } from "./core/background/triggers/index.js";
26
- import { pruneSettledTriggers } from "./storage/trigger-store.js";
26
+ import { pruneSettledTriggers } from "./storage/triggers.js";
27
27
  import { startWatchdog, stopWatchdog } from "./util/watchdog.js";
28
28
  import { spawnSuccessor } from "./util/respawn.js";
29
29
  import { log, logError, logWarn } from "./util/log.js";
@@ -7,7 +7,7 @@
7
7
  import type {
8
8
  DoctorCheck,
9
9
  DoctorConfigSlice,
10
- } from "../../core/doctor-types.js";
10
+ } from "../../core/doctor/types.js";
11
11
  import { getModels } from "../../core/models/catalog.js";
12
12
  import { binaryOnPath } from "../../util/binary-on-path.js";
13
13
  import { resolveModel } from "./model-provider.js";
@@ -6,7 +6,7 @@
6
6
  import type {
7
7
  DoctorCheck,
8
8
  DoctorConfigSlice,
9
- } from "../../core/doctor-types.js";
9
+ } from "../../core/doctor/types.js";
10
10
  import { binaryOnPath } from "../../util/binary-on-path.js";
11
11
  import { detectCodexAuth } from "./auth.js";
12
12
 
@@ -6,7 +6,7 @@
6
6
  import type {
7
7
  DoctorCheck,
8
8
  DoctorConfigSlice,
9
- } from "../../core/doctor-types.js";
9
+ } from "../../core/doctor/types.js";
10
10
 
11
11
  export async function openAIAgentsDoctorChecks(
12
12
  config: DoctorConfigSlice | undefined,
package/src/bootstrap.ts CHANGED
@@ -13,8 +13,8 @@ import { loadConfig, rebuildSystemPrompt } from "./util/config.js";
13
13
  import { initWorkspace } from "./util/workspace.js";
14
14
  import { loadSessions, resetSession } from "./storage/sessions.js";
15
15
  import { loadChatSettings } from "./storage/chat-settings.js";
16
- import { loadCronJobs } from "./storage/cron-store.js";
17
- import { loadTriggers } from "./storage/trigger-store.js";
16
+ import { loadCronJobs } from "./storage/cron.js";
17
+ import { loadTriggers } from "./storage/triggers.js";
18
18
  import { clearHistory, loadHistory } from "./storage/history.js";
19
19
  import { loadMediaIndex } from "./storage/media-index.js";
20
20
  import { cleanupOldLogs } from "./storage/daily-log.js";
@@ -27,7 +27,7 @@ import { appendToJournal } from "./storage/journal.js";
27
27
  import { initPulse, resetPulseTimer } from "./core/background/pulse.js";
28
28
  import { initCron } from "./core/background/cron.js";
29
29
  import { initPlanAlerts } from "./core/background/plan-alerts.js";
30
- import { setAdminNotifier } from "./core/notify.js";
30
+ import { setAdminNotifier } from "./core/frontend-runtime/admin-notify.js";
31
31
  import { startAuthExpiryMonitor } from "./core/auth/expiry-monitor.js";
32
32
  import {
33
33
  initTriggers,
package/src/cli/doctor.ts CHANGED
@@ -19,7 +19,7 @@ const DOCTOR_ICONS: Record<string, string> = {
19
19
  export async function runDoctor(): Promise<void> {
20
20
  printBanner();
21
21
  console.log(` ${pc.bold("Environment check")}\n`);
22
- const { collectDoctorReport } = await import("../core/doctor.js");
22
+ const { collectDoctorReport } = await import("../core/doctor/index.js");
23
23
  // Doctor composes each backend's own checks off the registry, and the
24
24
  // CLI runs standalone — nothing else has registered them yet.
25
25
  const { loadBuiltinBackends } = await import("../backend/builtins.js");
package/src/cli/skill.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * `talon skill` — install / list / enable / disable / remove SKILL.md
3
3
  * workflow bundles.
4
4
  *
5
- * All lifecycle logic lives in storage/skill-store.ts; this module only
5
+ * All lifecycle logic lives in storage/skills.ts; this module only
6
6
  * resolves install sources and renders outcomes. Installs accept a local
7
7
  * folder, a git URL, or `owner/repo[/subpath]` (so `talon skill install
8
8
  * anthropics/skills/skills/pdf` works). A source folder either IS a skill
@@ -22,7 +22,7 @@ import {
22
22
  listSkills,
23
23
  setSkillEnabled,
24
24
  type Skill,
25
- } from "../storage/skill-store.js";
25
+ } from "../storage/skills.js";
26
26
  import { cloneShallow, resolveSource } from "./install-sources.js";
27
27
 
28
28
  const USAGE = [
@@ -30,7 +30,7 @@
30
30
  */
31
31
 
32
32
  import type { Backend } from "./capabilities.js";
33
- import type { DoctorCheck, DoctorConfigSlice } from "../doctor-types.js";
33
+ import type { DoctorCheck, DoctorConfigSlice } from "../doctor/types.js";
34
34
  import type { TalonConfig } from "../../util/config.js";
35
35
 
36
36
  // ── Types ───────────────────────────────────────────────────────────────────
@@ -9,7 +9,7 @@
9
9
  * fresh login clears it, so the next expiry warns again).
10
10
  */
11
11
 
12
- import { notifyAdmin } from "../notify.js";
12
+ import { notifyAdmin } from "../frontend-runtime/admin-notify.js";
13
13
  import {
14
14
  daysUntil,
15
15
  PROVIDER_LABELS,
@@ -18,7 +18,7 @@ import {
18
18
  type CatchupPolicy,
19
19
  type CronJob,
20
20
  type CronJobType,
21
- } from "../../storage/cron-store.js";
21
+ } from "../../storage/cron.js";
22
22
 
23
23
  /** The scheduler ticks once a minute, so sub-minute intervals are meaningless. */
24
24
  const MIN_INTERVAL_SECONDS = 60;
@@ -31,7 +31,7 @@ import {
31
31
  describeSchedule,
32
32
  type CronJob,
33
33
  type CronRunOutcome,
34
- } from "../../storage/cron-store.js";
34
+ } from "../../storage/cron.js";
35
35
  import { appendDailyLog } from "../../storage/daily-log.js";
36
36
  import { log, logError, logWarn } from "../../util/log.js";
37
37
  import { numericChatIdFor } from "../../util/chat-id.js";
@@ -11,7 +11,7 @@ import { logError, logWarn } from "../../../util/log.js";
11
11
  import { toYMD } from "../../../util/time.js";
12
12
  import { getDefaultModel } from "../../models/catalog.js";
13
13
  import { loadSystemTemplate } from "../../prompt/templates.js";
14
- import { formatGoal, getOpenGoals } from "../../../storage/goal-store.js";
14
+ import { formatGoal, getOpenGoals } from "../../../storage/goals.js";
15
15
  import { taskTable, type TaskHandle } from "../../tasks/index.js";
16
16
  import type { Backend } from "../../agent-runtime/capabilities.js";
17
17
  import type { OneShotAgentParams } from "../../types.js";
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { spawnSync } from "node:child_process";
8
- import type { Trigger } from "../../../storage/trigger-store.js";
8
+ import type { Trigger } from "../../../storage/triggers.js";
9
9
  import { selfInvocation } from "../../../util/mcp-launcher.js";
10
10
  import { LUA_RUN_SUBCOMMAND } from "../../scripting/lua-runner.js";
11
11
 
@@ -11,7 +11,7 @@ import {
11
11
  SHUTDOWN_KILL_ERROR,
12
12
  type Trigger,
13
13
  type TriggerStatus,
14
- } from "../../../storage/trigger-store.js";
14
+ } from "../../../storage/triggers.js";
15
15
  import { log, logDebug, logError } from "../../../util/log.js";
16
16
  import { appendDailyLog } from "../../../storage/daily-log.js";
17
17
  import {
@@ -8,7 +8,7 @@ import {
8
8
  updateTrigger,
9
9
  type TriggerStatus,
10
10
  FIRE_PAYLOAD_MAX_BYTES,
11
- } from "../../../storage/trigger-store.js";
11
+ } from "../../../storage/triggers.js";
12
12
  import { logError } from "../../../util/log.js";
13
13
  import {
14
14
  depsHolder,
@@ -11,7 +11,7 @@ import {
11
11
  RESTART_KILL_ERROR,
12
12
  SHUTDOWN_KILL_ERROR,
13
13
  type Trigger,
14
- } from "../../../storage/trigger-store.js";
14
+ } from "../../../storage/triggers.js";
15
15
  import { log, logError } from "../../../util/log.js";
16
16
  import { depsHolder } from "./state.js";
17
17
  import { fireWake } from "./output.js";
@@ -11,7 +11,7 @@ import {
11
11
  getTrigger,
12
12
  updateTrigger,
13
13
  type Trigger,
14
- } from "../../../storage/trigger-store.js";
14
+ } from "../../../storage/triggers.js";
15
15
  import { log, logError, logWarn } from "../../../util/log.js";
16
16
  import { spawnWarden, type WardenExitEvent } from "../../../native/warden.js";
17
17
  import {
@@ -13,22 +13,22 @@
13
13
 
14
14
  import { existsSync } from "node:fs";
15
15
  import { stat } from "node:fs/promises";
16
- import { NATIVE_MODULES } from "../native/registry.js";
17
- import { dirs } from "../util/paths.js";
18
- import { getBackend, listBackends } from "./agent-runtime/backend-registry.js";
16
+ import { NATIVE_MODULES } from "../../native/registry.js";
17
+ import { dirs } from "../../util/paths.js";
18
+ import { getBackend, listBackends } from "../agent-runtime/backend-registry.js";
19
19
  import type {
20
20
  DoctorCheck,
21
21
  DoctorConfigSlice,
22
22
  DoctorReport,
23
23
  NativeModuleCheck,
24
- } from "./doctor-types.js";
24
+ } from "./types.js";
25
25
 
26
26
  export type {
27
27
  DoctorCheck,
28
28
  DoctorConfigSlice,
29
29
  DoctorReport,
30
30
  NativeModuleCheck,
31
- } from "./doctor-types.js";
31
+ } from "./types.js";
32
32
 
33
33
  function errorNote(err: unknown): string {
34
34
  return err instanceof Error ? err.message : String(err);
@@ -180,7 +180,7 @@ async function checkPluginRuntimes(
180
180
  config: DoctorConfigSlice | undefined,
181
181
  ): Promise<DoctorCheck[]> {
182
182
  const checks: DoctorCheck[] = [];
183
- const { NATIVE_RUNTIMES } = await import("./plugin/native-runtimes.js");
183
+ const { NATIVE_RUNTIMES } = await import("../plugin/native-runtimes.js");
184
184
  for (const runtime of NATIVE_RUNTIMES) {
185
185
  if (!runtime.enabled(config)) continue;
186
186
  try {
@@ -322,7 +322,7 @@ export async function collectDoctorReport(opts: {
322
322
  // on the in-process TS path. When present, report the live version.
323
323
  {
324
324
  const { wardenBinaryPath, wardenVersion } =
325
- await import("../native/warden.js");
325
+ await import("../../native/warden.js");
326
326
  const wardenBin = wardenBinaryPath();
327
327
  if (wardenBin) {
328
328
  const version = wardenVersion();
@@ -350,7 +350,7 @@ export async function collectDoctorReport(opts: {
350
350
  // and on the event loop), so it's informational, not an issue. The
351
351
  // addon was digest-verified at load time by nativeBlake3().
352
352
  {
353
- const { nativeBlake3 } = await import("../native/blake3.js");
353
+ const { nativeBlake3 } = await import("../../native/blake3.js");
354
354
  const addon = nativeBlake3();
355
355
  checks.push(
356
356
  addon
@@ -370,7 +370,7 @@ export async function collectDoctorReport(opts: {
370
370
  // ~/.talon/ns is the symlink farm only (file mounts fine, no live
371
371
  // proc//plugins views), so it's informational, not an issue.
372
372
  {
373
- const { nativeFuseFs } = await import("../native/fusefs.js");
373
+ const { nativeFuseFs } = await import("../../native/fusefs.js");
374
374
  const addon = nativeFuseFs();
375
375
  checks.push(
376
376
  addon
@@ -392,7 +392,7 @@ export async function collectDoctorReport(opts: {
392
392
  // stale or the package is incomplete — caught at check time, not
393
393
  // mid-message when a backend assembles its system prompt.
394
394
  {
395
- const { loadSystemTemplate } = await import("./prompt/index.js");
395
+ const { loadSystemTemplate } = await import("../prompt/index.js");
396
396
  try {
397
397
  const sample = loadSystemTemplate("workspace");
398
398
  checks.push(
@@ -423,7 +423,7 @@ export async function collectDoctorReport(opts: {
423
423
  // is which is the difference between "why didn't my prompt update?"
424
424
  // and a one-line answer.
425
425
  {
426
- const { promptSeedReport } = await import("../util/workspace.js");
426
+ const { promptSeedReport } = await import("../../util/workspace.js");
427
427
  try {
428
428
  const { tracking, edited } = promptSeedReport();
429
429
  if (tracking.length + edited.length > 0) {
@@ -11,7 +11,7 @@ import {
11
11
  generateCronId,
12
12
  describeSchedule,
13
13
  nextRunAt,
14
- } from "../../../storage/cron-store.js";
14
+ } from "../../../storage/cron.js";
15
15
  import { runJobNow } from "../../background/cron.js";
16
16
  import { parseCronSpec } from "../../background/cron-spec.js";
17
17
  import { log } from "../../../util/log.js";
@@ -22,7 +22,7 @@ import {
22
22
  acquireBackendInstance,
23
23
  isModelValidForBackend,
24
24
  } from "../backend-controller/index.js";
25
- import { validateJobModelOverride } from "./shared.js";
25
+ import { validateJobModelOverride } from "./validation.js";
26
26
  import type { SharedActionHandlers } from "./types.js";
27
27
 
28
28
  /**
@@ -20,9 +20,9 @@ import {
20
20
  OPEN_GOAL_STATUSES,
21
21
  type Goal,
22
22
  type GoalStatus,
23
- } from "../../../storage/goal-store.js";
23
+ } from "../../../storage/goals.js";
24
24
  import { log } from "../../../util/log.js";
25
- import { parseDueDate } from "./shared.js";
25
+ import { parseDueDate } from "./validation.js";
26
26
  import type { SharedActionHandlers } from "./types.js";
27
27
 
28
28
  export const goalHandlers: SharedActionHandlers = {
@@ -14,7 +14,7 @@ import {
14
14
  validateScriptLanguage,
15
15
  validateScriptName,
16
16
  validateScriptBody,
17
- } from "../../../storage/script-store.js";
17
+ } from "../../../storage/scripts.js";
18
18
  import {
19
19
  runScript,
20
20
  validateScriptTimeout,
@@ -15,7 +15,7 @@ import {
15
15
  validateSkillBody,
16
16
  validateSkillDescription,
17
17
  validateSkillName,
18
- } from "../../../storage/skill-store.js";
18
+ } from "../../../storage/skills.js";
19
19
  import { log } from "../../../util/log.js";
20
20
  import type { SharedActionHandlers } from "./types.js";
21
21
 
@@ -21,13 +21,13 @@ import {
21
21
  DEFAULT_TIMEOUT_SECONDS,
22
22
  MAX_ACTIVE_PER_CHAT,
23
23
  type TriggerLanguage,
24
- } from "../../../storage/trigger-store.js";
24
+ } from "../../../storage/triggers.js";
25
25
  import {
26
26
  cancelTrigger,
27
27
  spawnTrigger,
28
28
  } from "../../background/triggers/index.js";
29
29
  import { log } from "../../../util/log.js";
30
- import { validateJobModelOverride } from "./shared.js";
30
+ import { validateJobModelOverride } from "./validation.js";
31
31
  import type { SharedActionHandlers } from "./types.js";
32
32
 
33
33
  export const triggerHandlers: SharedActionHandlers = {
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Helpers shared across shared-action domains: due-date parsing and per-job
3
- * model-override validation.
2
+ * Field validation shared by the goal, cron and trigger actions: due-date
3
+ * parsing and per-job model-override validation.
4
4
  */
5
5
 
6
6
  import { resolveExplicitModelRef } from "../../models/active-model.js";
@@ -14,7 +14,7 @@
14
14
  * watches. Alerts about a dead frontend must travel over a LIVE one.
15
15
  */
16
16
 
17
- import { log, logWarn } from "./../util/log.js";
17
+ import { log, logWarn } from "../../util/log.js";
18
18
 
19
19
  let deliver: ((text: string) => Promise<void>) | null = null;
20
20
 
@@ -13,7 +13,7 @@
13
13
  * import-cheap for consumers that only need the id list.
14
14
  */
15
15
 
16
- import type { DoctorCheck } from "../doctor.js";
16
+ import type { DoctorCheck } from "../doctor/index.js";
17
17
  import type { ProvisionOutcome } from "./provision.js";
18
18
  import type { MempalaceSection } from "../../plugins/mempalace/provision.js";
19
19
  import type { PlaywrightSection } from "../../plugins/playwright/provision.js";
@@ -63,8 +63,8 @@ import { log } from "../../util/log.js";
63
63
  import { loadSystemTemplate } from "./templates.js";
64
64
  import { renderMemoryView } from "./memory-view.js";
65
65
  import { renderWorkspaceListing } from "./workspace-listing.js";
66
- import { renderSkillsPrompt } from "../../storage/skill-store.js";
67
- import { renderStickerLibraryPrompt } from "../../storage/sticker-store.js";
66
+ import { renderSkillsPrompt } from "../../storage/skills.js";
67
+ import { renderStickerLibraryPrompt } from "../../storage/stickers.js";
68
68
  import { getSoul } from "../soul/service.js";
69
69
 
70
70
  // ── Types ───────────────────────────────────────────────────────────────────
@@ -16,7 +16,7 @@ import { spawn } from "node:child_process";
16
16
  import { dirs } from "../../util/paths.js";
17
17
  import { log } from "../../util/log.js";
18
18
  import { commandForLanguage } from "../background/triggers/index.js";
19
- import type { Script } from "../../storage/script-store.js";
19
+ import type { Script } from "../../storage/scripts.js";
20
20
 
21
21
  export const DEFAULT_SCRIPT_TIMEOUT_SECONDS = 60;
22
22
  const MAX_SCRIPT_TIMEOUT_SECONDS = 300;
@@ -93,7 +93,7 @@ export function effectiveStrength(
93
93
  );
94
94
  }
95
95
 
96
- export interface FsrsReinforceOpts {
96
+ export interface FsrsReinforceOptions {
97
97
  readonly now: number;
98
98
  readonly cfg: SoulConfig;
99
99
  readonly amount: number;
@@ -111,7 +111,7 @@ export interface FsrsReinforceOpts {
111
111
  */
112
112
  export function reinforceFsrs(
113
113
  state: ActivationState,
114
- opts: FsrsReinforceOpts,
114
+ opts: FsrsReinforceOptions,
115
115
  ): ActivationState {
116
116
  if (!Number.isFinite(halfLifeForKind(opts.cfg, opts.kind))) {
117
117
  state.salience += opts.amount;
@@ -60,7 +60,7 @@ export function confidence(state: ActivationState): number {
60
60
  return Math.tanh(state.evidence / 4);
61
61
  }
62
62
 
63
- export interface ReinforceOpts {
63
+ export interface ReinforceOptions {
64
64
  readonly now: number;
65
65
  readonly halfLifeMs: number;
66
66
  /** Salience increment for this activation (>= 0). */
@@ -74,7 +74,11 @@ export interface ReinforceOpts {
74
74
  * first (so the additive bump composes correctly with time), then adds the
75
75
  * increment and accumulates signed evidence.
76
76
  */
77
- export function reinforce(dag: SoulDag, hash: Hash, opts: ReinforceOpts): void {
77
+ export function reinforce(
78
+ dag: SoulDag,
79
+ hash: Hash,
80
+ opts: ReinforceOptions,
81
+ ): void {
78
82
  const s = dag.stateOf(hash);
79
83
  s.salience = effectiveSalience(s, opts.now, opts.halfLifeMs) + opts.amount;
80
84
  s.evidence += opts.valence;
@@ -111,7 +115,7 @@ export function coactivate(
111
115
  }
112
116
  }
113
117
 
114
- export interface PredictionErrorOpts {
118
+ export interface PredictionErrorOptions {
115
119
  readonly now: number;
116
120
  readonly halfLifeMs: number;
117
121
  /** How strongly the observed signal corrects the prediction, in (0, 1]. */
@@ -129,7 +133,7 @@ export function applyPredictionError(
129
133
  dag: SoulDag,
130
134
  hash: Hash,
131
135
  observed: number,
132
- opts: PredictionErrorOpts,
136
+ opts: PredictionErrorOptions,
133
137
  ): number {
134
138
  const s = dag.stateOf(hash);
135
139
  const predicted = effectiveSalience(s, opts.now, opts.halfLifeMs);
@@ -1,63 +1,10 @@
1
1
  /**
2
- * Shared helpers for Discord action handlers: clean error mapping, channel
3
- * resolution, and button-row construction.
2
+ * Button-row construction for model-authored inline buttons (Discord
3
+ * components), with custom_id namespacing and de-duplication.
4
4
  */
5
5
 
6
- import {
7
- type Client,
8
- type TextBasedChannel,
9
- ActionRowBuilder,
10
- ButtonBuilder,
11
- ButtonStyle,
12
- } from "discord.js";
13
- import type { ActionResult } from "../../../core/types.js";
14
- import { lookupDiscordChat } from "../handlers/index.js";
6
+ import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
15
7
  import { safeSlice } from "../formatting.js";
16
- import { logWarn } from "../../../util/log.js";
17
- import { mapDiscordError } from "../errors.js";
18
-
19
- /** Run a Discord action; convert DiscordAPIError into a clean ActionResult. */
20
- export async function tryAction(
21
- context: string,
22
- fn: () => Promise<ActionResult>,
23
- ): Promise<ActionResult> {
24
- try {
25
- return await fn();
26
- } catch (err) {
27
- const mapped = mapDiscordError(err, context);
28
- if (mapped) return mapped;
29
- return {
30
- ok: false,
31
- error: `${context} failed: ${err instanceof Error ? err.message : err}`,
32
- };
33
- }
34
- }
35
-
36
- export async function resolveChannel(
37
- client: Client,
38
- numericChatId: number,
39
- ): Promise<TextBasedChannel | null> {
40
- const info = lookupDiscordChat(numericChatId);
41
- if (!info) return null;
42
- try {
43
- const ch = await client.channels.fetch(info.channelId);
44
- if (ch && "send" in ch && (ch as TextBasedChannel).isSendable?.()) {
45
- return ch as TextBasedChannel;
46
- }
47
- if (info.userId) {
48
- const user = await client.users.fetch(info.userId);
49
- const dm = await user.createDM();
50
- return dm as TextBasedChannel;
51
- }
52
- return null;
53
- } catch (err) {
54
- logWarn(
55
- "discord",
56
- `resolveChannel failed for chat ${numericChatId}: ${err instanceof Error ? err.message : err}`,
57
- );
58
- return null;
59
- }
60
- }
61
8
 
62
9
  export function buildButtonRows(
63
10
  rows: Array<
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Resolve a registered Discord chat to a sendable channel (guild channel or
3
+ * the user's DM).
4
+ */
5
+
6
+ import type { Client, TextBasedChannel } from "discord.js";
7
+ import { lookupDiscordChat } from "../handlers/index.js";
8
+ import { logWarn } from "../../../util/log.js";
9
+
10
+ export async function resolveChannel(
11
+ client: Client,
12
+ numericChatId: number,
13
+ ): Promise<TextBasedChannel | null> {
14
+ const info = lookupDiscordChat(numericChatId);
15
+ if (!info) return null;
16
+ try {
17
+ const ch = await client.channels.fetch(info.channelId);
18
+ if (ch && "send" in ch && (ch as TextBasedChannel).isSendable?.()) {
19
+ return ch as TextBasedChannel;
20
+ }
21
+ if (info.userId) {
22
+ const user = await client.users.fetch(info.userId);
23
+ const dm = await user.createDM();
24
+ return dm as TextBasedChannel;
25
+ }
26
+ return null;
27
+ } catch (err) {
28
+ logWarn(
29
+ "discord",
30
+ `resolveChannel failed for chat ${numericChatId}: ${err instanceof Error ? err.message : err}`,
31
+ );
32
+ return null;
33
+ }
34
+ }
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { ChannelType } from "discord.js";
8
8
  import { logWarn } from "../../../util/log.js";
9
- import { tryAction } from "./shared.js";
9
+ import { tryAction } from "./try-action.js";
10
10
  import type { DiscordActionHandlers } from "./types.js";
11
11
 
12
12
  export const chatInfoHandlers: DiscordActionHandlers = {
@@ -23,7 +23,7 @@
23
23
  import type { Client } from "discord.js";
24
24
  import type { Gateway } from "../../../core/engine/gateway.js";
25
25
  import type { ActionResult } from "../../../core/types.js";
26
- import { resolveChannel } from "./shared.js";
26
+ import { resolveChannel } from "./channels.js";
27
27
  import { messagingHandlers, restoreScheduledMessages } from "./messaging.js";
28
28
  import { mediaHandlers } from "./media.js";
29
29
  import { chatInfoHandlers } from "./chat-info.js";
@@ -11,7 +11,7 @@ import { withRetry } from "../../../core/engine/gateway.js";
11
11
  import { sendChunked } from "../handlers/index.js";
12
12
  import { suppressMentions, DISCORD_MAX_TEXT } from "../formatting.js";
13
13
  import { maxAttachmentBytes } from "../errors.js";
14
- import { tryAction } from "./shared.js";
14
+ import { tryAction } from "./try-action.js";
15
15
  import type { DiscordActionHandlers } from "./types.js";
16
16
 
17
17
  const sendAttachment: DiscordActionHandlers[string] = (
@@ -19,8 +19,10 @@ import {
19
19
  listScheduledForChat,
20
20
  MAX_OVERDUE_MS,
21
21
  type ScheduledMessage,
22
- } from "../../../storage/scheduled-store.js";
23
- import { tryAction, resolveChannel, buildButtonRows } from "./shared.js";
22
+ } from "../../../storage/scheduled.js";
23
+ import { tryAction } from "./try-action.js";
24
+ import { resolveChannel } from "./channels.js";
25
+ import { buildButtonRows } from "./buttons.js";
24
26
  import type { DiscordActionHandlers } from "./types.js";
25
27
 
26
28
  // ── Scheduled sends (persistent) ─────────────────────────────────────────────
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Run a Discord action with uniform error mapping: DiscordAPIError becomes a
3
+ * clean ActionResult, anything else a labelled failure.
4
+ */
5
+
6
+ import type { ActionResult } from "../../../core/types.js";
7
+ import { mapDiscordError } from "../errors.js";
8
+
9
+ /** Run a Discord action; convert DiscordAPIError into a clean ActionResult. */
10
+ export async function tryAction(
11
+ context: string,
12
+ fn: () => Promise<ActionResult>,
13
+ ): Promise<ActionResult> {
14
+ try {
15
+ return await fn();
16
+ } catch (err) {
17
+ const mapped = mapDiscordError(err, context);
18
+ if (mapped) return mapped;
19
+ return {
20
+ ok: false,
21
+ error: `${context} failed: ${err instanceof Error ? err.message : err}`,
22
+ };
23
+ }
24
+ }