talon-agent 4.3.3 → 4.4.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.
Files changed (105) hide show
  1. package/package.json +1 -1
  2. package/src/app.ts +1 -1
  3. package/src/backend/claude-sdk/state.ts +1 -1
  4. package/src/backend/codex/init.ts +1 -1
  5. package/src/backend/codex/state.ts +1 -1
  6. package/src/backend/openai-agents/init.ts +1 -1
  7. package/src/backend/openai-agents/state.ts +1 -1
  8. package/src/backend/remote-server/factory.ts +1 -1
  9. package/src/backend/remote-server/mcp.ts +1 -1
  10. package/src/backend/remote-server/server-bindings.ts +1 -1
  11. package/src/backend/remote-server/state.ts +1 -1
  12. package/src/backend/shared/system-prompt.ts +1 -1
  13. package/src/bootstrap.ts +2 -2
  14. package/src/cli/chat.ts +1 -1
  15. package/src/cli/config.ts +2 -2
  16. package/src/cli/index.ts +8 -0
  17. package/src/cli/memory.ts +166 -0
  18. package/src/cli/setup.ts +1 -1
  19. package/src/core/agent-runtime/backend-registry.ts +1 -1
  20. package/src/core/agent-runtime/model-ref.ts +2 -2
  21. package/src/{util/config.ts → core/config/index.ts} +8 -8
  22. package/src/core/engine/backend-controller/legacy.ts +1 -1
  23. package/src/core/engine/backend-controller/pool.ts +1 -1
  24. package/src/core/engine/backend-controller/rebind.ts +1 -1
  25. package/src/core/engine/backend-controller/state.ts +1 -1
  26. package/src/core/engine/gateway-actions/plugins.ts +1 -1
  27. package/src/core/engine/model-audit.ts +1 -1
  28. package/src/core/frontend-runtime/capabilities.ts +1 -1
  29. package/src/core/models/active-model.ts +1 -1
  30. package/src/core/plugin/builtins.ts +2 -2
  31. package/src/core/plugin/manage.ts +1 -1
  32. package/src/frontend/discord/admin.ts +1 -1
  33. package/src/frontend/discord/callbacks/components/index.ts +1 -1
  34. package/src/frontend/discord/callbacks/components/settings.ts +1 -1
  35. package/src/frontend/discord/callbacks/components/types.ts +1 -1
  36. package/src/frontend/discord/callbacks/modals.ts +1 -1
  37. package/src/frontend/discord/commands/admin.ts +1 -1
  38. package/src/frontend/discord/commands/definitions.ts +1 -1
  39. package/src/frontend/discord/commands/info.ts +1 -1
  40. package/src/frontend/discord/commands/router.ts +1 -1
  41. package/src/frontend/discord/commands/session.ts +1 -1
  42. package/src/frontend/discord/commands/settings.ts +1 -1
  43. package/src/frontend/discord/handlers/delivery.ts +1 -1
  44. package/src/frontend/discord/handlers/messages.ts +1 -1
  45. package/src/frontend/discord/handlers/queue.ts +1 -1
  46. package/src/frontend/discord/handlers/state.ts +1 -1
  47. package/src/frontend/discord/index.ts +1 -1
  48. package/src/frontend/discord/middleware.ts +1 -1
  49. package/src/frontend/discord/runtime.ts +1 -1
  50. package/src/frontend/native/extensions.ts +4 -1
  51. package/src/frontend/native/index.ts +1 -1
  52. package/src/frontend/native/runtime.ts +1 -1
  53. package/src/frontend/native/settings.ts +1 -1
  54. package/src/frontend/shared/model-commands.ts +1 -1
  55. package/src/frontend/shared/plan-usage-report.ts +1 -1
  56. package/src/frontend/shared/reasoning-levels.ts +1 -1
  57. package/src/frontend/shared/session-status.ts +1 -1
  58. package/src/frontend/teams/index.ts +1 -1
  59. package/src/frontend/teams/runtime.ts +1 -1
  60. package/src/frontend/telegram/actions/chat-info.ts +1 -1
  61. package/src/frontend/telegram/actions/coerce.ts +15 -0
  62. package/src/frontend/telegram/actions/index.ts +1 -1
  63. package/src/frontend/telegram/actions/media.ts +1 -1
  64. package/src/frontend/telegram/actions/messaging.ts +3 -4
  65. package/src/frontend/telegram/actions/moderation/chat.ts +1 -1
  66. package/src/frontend/telegram/actions/moderation/index.ts +1 -1
  67. package/src/frontend/telegram/actions/moderation/topics.ts +1 -1
  68. package/src/frontend/telegram/actions/rich-messages.ts +51 -0
  69. package/src/frontend/telegram/actions/{shared.ts → send.ts} +9 -59
  70. package/src/frontend/telegram/admin/sessions.ts +1 -1
  71. package/src/frontend/telegram/admin.ts +1 -1
  72. package/src/frontend/telegram/callbacks/auth.ts +1 -1
  73. package/src/frontend/telegram/callbacks/effort.ts +1 -1
  74. package/src/frontend/telegram/callbacks/index.ts +3 -3
  75. package/src/frontend/telegram/callbacks/metrics.ts +1 -1
  76. package/src/frontend/telegram/callbacks/model/backend.ts +1 -1
  77. package/src/frontend/telegram/callbacks/model/control.ts +1 -1
  78. package/src/frontend/telegram/callbacks/model/select.ts +1 -1
  79. package/src/frontend/telegram/callbacks/model/types.ts +1 -1
  80. package/src/frontend/telegram/callbacks/model/views.ts +1 -1
  81. package/src/frontend/telegram/callbacks/model.ts +1 -1
  82. package/src/frontend/telegram/callbacks/pulse.ts +1 -1
  83. package/src/frontend/telegram/callbacks/{shared.ts → query.ts} +3 -2
  84. package/src/frontend/telegram/callbacks/settings.ts +1 -1
  85. package/src/frontend/telegram/callbacks/whatsapp.ts +1 -1
  86. package/src/frontend/telegram/commands/admin.ts +1 -1
  87. package/src/frontend/telegram/commands/index.ts +1 -1
  88. package/src/frontend/telegram/commands/state.ts +1 -1
  89. package/src/frontend/telegram/handlers/context.ts +1 -1
  90. package/src/frontend/telegram/handlers/delivery.ts +2 -2
  91. package/src/frontend/telegram/handlers/messages.ts +1 -1
  92. package/src/frontend/telegram/handlers/queue.ts +1 -1
  93. package/src/frontend/telegram/handlers/state.ts +1 -1
  94. package/src/frontend/telegram/index.ts +1 -1
  95. package/src/frontend/telegram/middleware.ts +1 -1
  96. package/src/frontend/telegram/model-menu.ts +1 -1
  97. package/src/frontend/terminal/command-registry.ts +1 -1
  98. package/src/frontend/terminal/index.ts +1 -1
  99. package/src/frontend/whatsapp/index.ts +1 -1
  100. package/src/frontend/whatsapp/runtime.ts +1 -1
  101. package/src/storage/memory.ts +505 -0
  102. package/src/storage/repositories/memory-repo.ts +308 -0
  103. package/src/storage/sql/memory.sql +95 -0
  104. package/src/storage/sql/schema.sql +81 -0
  105. package/src/storage/sql/statements.generated.ts +146 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "talon-agent",
3
- "version": "4.3.3",
3
+ "version": "4.4.0",
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
@@ -6,7 +6,7 @@
6
6
  * are loaded dynamically — only the selected platform's dependencies are required.
7
7
  */
8
8
 
9
- import { getFrontends } from "./util/config.js";
9
+ import { getFrontends } from "./core/config/index.js";
10
10
  import { startUploadCleanup, stopUploadCleanup } from "./util/workspace.js";
11
11
  import { flushDatabase } from "./storage/db.js";
12
12
  import { getActiveCount, stopAllTurns } from "./core/engine/dispatcher.js";
@@ -5,7 +5,7 @@
5
5
  * initialization functions + internal getters for sibling modules.
6
6
  */
7
7
 
8
- import type { TalonConfig } from "../../util/config.js";
8
+ import type { TalonConfig } from "../../core/config/index.js";
9
9
  import { registerClaudeModels } from "./models/index.js";
10
10
 
11
11
  // ── State ────────────────────────────────────────────────────────────────────
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  import { Codex } from "@openai/codex-sdk";
25
- import type { TalonConfig } from "../../util/config.js";
25
+ import type { TalonConfig } from "../../core/config/index.js";
26
26
  import type { FrontendName } from "../../core/agent-runtime/backend-registry.js";
27
27
  import { log, logWarn } from "../../util/log.js";
28
28
  import { nonTerminalFrontends } from "../shared/frontends.js";
@@ -11,7 +11,7 @@
11
11
 
12
12
  import type { Codex } from "@openai/codex-sdk";
13
13
  import type { ReasoningEffortLevel } from "../../core/types.js";
14
- import type { TalonConfig } from "../../util/config.js";
14
+ import type { TalonConfig } from "../../core/config/index.js";
15
15
  import type { FrontendName } from "../../core/agent-runtime/backend-registry.js";
16
16
 
17
17
  /**
@@ -43,7 +43,7 @@
43
43
 
44
44
  import OpenAI from "openai";
45
45
  import { setDefaultOpenAIClient, setOpenAIAPI } from "@openai/agents";
46
- import type { TalonConfig } from "../../util/config.js";
46
+ import type { TalonConfig } from "../../core/config/index.js";
47
47
  import type { FrontendName } from "../../core/agent-runtime/backend-registry.js";
48
48
  import { log, logWarn } from "../../util/log.js";
49
49
  import { nonTerminalFrontends } from "../shared/frontends.js";
@@ -8,7 +8,7 @@
8
8
  * so the resolver, picker, and UIs can read it synchronously.
9
9
  */
10
10
 
11
- import type { TalonConfig } from "../../util/config.js";
11
+ import type { TalonConfig } from "../../core/config/index.js";
12
12
  import type { FrontendName } from "../../core/agent-runtime/backend-registry.js";
13
13
  import { TalonSession } from "./session.js";
14
14
  import type { ReasoningEffortLevel } from "../../core/types.js";
@@ -25,7 +25,7 @@ import {
25
25
  type UsageTelemetry,
26
26
  } from "../../core/agent-runtime/capabilities.js";
27
27
  import type { OneShotAgentParams, OneShotUsage } from "../../core/types.js";
28
- import type { TalonConfig } from "../../util/config.js";
28
+ import type { TalonConfig } from "../../core/config/index.js";
29
29
  import { binaryOnPath } from "../../util/binary-on-path.js";
30
30
  import { log } from "../../util/log.js";
31
31
  import { handlerToEvents } from "../shared/handler-to-events.js";
@@ -44,7 +44,7 @@ import {
44
44
  import type { RemoteAgentClient } from "./client.js";
45
45
  import type { RemoteServerState } from "./state.js";
46
46
  import { errMsg } from "./state.js";
47
- import type { TalonConfig } from "../../util/config.js";
47
+ import type { TalonConfig } from "../../core/config/index.js";
48
48
  import type { FrontendName } from "../../core/agent-runtime/backend-registry.js";
49
49
  import { ALL_TOOLS, nativeTools } from "../../core/tools/index.js";
50
50
  import {
@@ -20,7 +20,7 @@
20
20
  * `vi.mock("../backend/<name>/server.js")` all address.
21
21
  */
22
22
 
23
- import type { TalonConfig } from "../../util/config.js";
23
+ import type { TalonConfig } from "../../core/config/index.js";
24
24
  import type { FrontendName } from "../../core/agent-runtime/backend-registry.js";
25
25
  import {
26
26
  buildDeliveryContract,
@@ -15,7 +15,7 @@
15
15
  * fields) and avoids the "where does this method live" guessing game.
16
16
  */
17
17
 
18
- import type { TalonConfig } from "../../util/config.js";
18
+ import type { TalonConfig } from "../../core/config/index.js";
19
19
  import type { FrontendName } from "../../core/agent-runtime/backend-registry.js";
20
20
  import type { RemoteAgentClient } from "./client.js";
21
21
 
@@ -39,7 +39,7 @@ import {
39
39
  joinSystemPromptParts,
40
40
  type SystemPromptParts,
41
41
  type TalonConfig,
42
- } from "../../util/config.js";
42
+ } from "../../core/config/index.js";
43
43
  import { getPluginPromptAdditions } from "../../core/plugin/index.js";
44
44
  import { onPromptInputsChanged } from "../../core/prompt/invalidation.js";
45
45
  import { frontendForChatId, nonTerminalFrontends } from "./frontends.js";
package/src/bootstrap.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * differ (index.ts selects dynamically, cli.ts always uses terminal).
10
10
  */
11
11
 
12
- import { loadConfig, rebuildSystemPrompt } from "./util/config.js";
12
+ import { loadConfig, rebuildSystemPrompt } from "./core/config/index.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";
@@ -38,7 +38,7 @@ import { initHeartbeat } from "./core/background/heartbeat/index.js";
38
38
  import { log, logWarn, logDebug } from "./util/log.js";
39
39
  import { bootPhase } from "./util/boot-timer.js";
40
40
  import { mapConcurrent } from "./util/concurrency.js";
41
- import type { TalonConfig } from "./util/config.js";
41
+ import type { TalonConfig } from "./core/config/index.js";
42
42
  import { resolveFrontendIdAmong } from "./core/frontend-runtime/routing.js";
43
43
  import type { Frontend } from "./core/frontend-runtime/index.js";
44
44
  import type { ContextManager } from "./core/types.js";
package/src/cli/chat.ts CHANGED
@@ -21,7 +21,7 @@ export async function startChat(): Promise<void> {
21
21
  // spawning telegram-tools or teams-tools MCP servers and ensures the
22
22
  // system prompt loads terminal.md instead of teams.md/telegram.md.
23
23
  (config as Record<string, unknown>).frontend = "terminal";
24
- const { rebuildSystemPrompt } = await import("../util/config.js");
24
+ const { rebuildSystemPrompt } = await import("../core/config/index.js");
25
25
  const { getPluginPromptAdditions } = await import("../core/plugin/index.js");
26
26
  rebuildSystemPrompt(config, getPluginPromptAdditions());
27
27
 
package/src/cli/config.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * CLI config model + load/save/format helpers, plus the banner.
3
3
  *
4
4
  * This is the on-disk `talon.json` shape as the CLI sees it; the runtime has
5
- * its own richer config type in util/config.ts.
5
+ * its own richer config type in core/config/index.ts.
6
6
  */
7
7
 
8
8
  import pc from "picocolors";
@@ -20,7 +20,7 @@ export function printBanner(): void {
20
20
 
21
21
  /**
22
22
  * The subset of ~/.talon/config.json the CLI reads or prompts for — a
23
- * partial view, not the whole schema (that lives in util/config.ts).
23
+ * partial view, not the whole schema (that lives in core/config/index.ts).
24
24
  * Anything absent here is still present at runtime on a loaded config and
25
25
  * MUST be carried through on save: `talon setup` used to rebuild the file
26
26
  * from its own named fields alone and silently dropped every other key.
package/src/cli/index.ts CHANGED
@@ -34,6 +34,7 @@ import { showTasks, killTask } from "./tasks.js";
34
34
  import { showEvents } from "./events.js";
35
35
  import { runPluginCommand } from "./plugin.js";
36
36
  import { runSkillCommand } from "./skill.js";
37
+ import { runMemoryCommand } from "./memory.js";
37
38
  import { mainMenu } from "./menu.js";
38
39
 
39
40
  export * from "./context.js";
@@ -56,6 +57,7 @@ const CLI_COMMANDS = [
56
57
  "events",
57
58
  "plugin",
58
59
  "skill",
60
+ "memory",
59
61
  ];
60
62
 
61
63
  /** Route a `talon <command>` invocation. Called by the entry point. */
@@ -121,6 +123,9 @@ export async function runCli(): Promise<void> {
121
123
  case "skill":
122
124
  await runSkillCommand(process.argv.slice(3));
123
125
  break;
126
+ case "memory":
127
+ runMemoryCommand(process.argv.slice(3));
128
+ break;
124
129
  case "--version":
125
130
  case "-v": {
126
131
  console.log(pkg.version);
@@ -151,6 +156,9 @@ export async function runCli(): Promise<void> {
151
156
  console.log(
152
157
  ` ${pc.cyan("skill")} Manage skills (install/enable/disable)`,
153
158
  );
159
+ console.log(
160
+ ` ${pc.cyan("memory")} Read/edit the memory store (list/search/remember)`,
161
+ );
154
162
  console.log(` ${pc.cyan("config")} View/edit configuration`);
155
163
  console.log(` ${pc.cyan("logs")} Tail log file`);
156
164
  console.log(` ${pc.cyan("doctor")} Validate environment`);
@@ -0,0 +1,166 @@
1
+ /**
2
+ * `talon memory` — read and edit the typed memory store from a terminal.
3
+ *
4
+ * All lifecycle logic lives in storage/memory.ts; this module only parses
5
+ * argv and renders rows. One row per line, in the store's own
6
+ * `formatMemory` shape, so CLI output and the `/memory` surfaces read
7
+ * identically.
8
+ */
9
+
10
+ import pc from "picocolors";
11
+ import {
12
+ assertMemory,
13
+ dropMemory,
14
+ formatMemory,
15
+ getMemory,
16
+ isMemoryKind,
17
+ listMemories,
18
+ memoryHistory,
19
+ replaceStateKey,
20
+ searchMemories,
21
+ MEMORY_KINDS,
22
+ type MemoryKind,
23
+ type MemoryRow,
24
+ } from "../storage/memory.js";
25
+
26
+ const USAGE = [
27
+ ` Usage: ${pc.cyan("talon memory <command>")}`,
28
+ "",
29
+ " Commands:",
30
+ ` ${pc.cyan("list [kind]")} Show live memories, ranked`,
31
+ ` ${pc.cyan("search <query>")} Full-text search`,
32
+ ` ${pc.cyan("show <id>")} One row plus its history`,
33
+ ` ${pc.cyan("remember <kind> <subject> <text>")} Record an operator claim`,
34
+ ` ${pc.cyan("forget <id> [reason]")} Drop a row to the graveyard`,
35
+ ` ${pc.cyan("state <key> <text>")} Replace the row for a state key`,
36
+ "",
37
+ ` Kinds: ${MEMORY_KINDS.join(", ")}`,
38
+ "",
39
+ ].join("\n");
40
+
41
+ function fail(message: string): void {
42
+ console.log(` ${pc.red("✖")} ${message}`);
43
+ }
44
+
45
+ function printRows(rows: readonly MemoryRow[], empty: string): void {
46
+ if (rows.length === 0) {
47
+ console.log(` ${pc.dim(empty)}\n`);
48
+ return;
49
+ }
50
+ for (const row of rows) console.log(` ${formatMemory(row)}`);
51
+ console.log();
52
+ }
53
+
54
+ function parseKind(value: string | undefined): MemoryKind | undefined {
55
+ if (value === undefined) return undefined;
56
+ if (!isMemoryKind(value)) throw new Error(`Unknown kind "${value}"`);
57
+ return value;
58
+ }
59
+
60
+ function cmdList(kindArg: string | undefined): void {
61
+ const kind = parseKind(kindArg);
62
+ const rows = listMemories(kind ? { kind } : {});
63
+ printRows(rows, kind ? `No ${kind} memories yet.` : "No memories yet.");
64
+ }
65
+
66
+ function cmdSearch(query: string): void {
67
+ printRows(searchMemories(query), `No memories matching "${query}".`);
68
+ }
69
+
70
+ function cmdShow(idArg: string | undefined): void {
71
+ const id = Number(idArg);
72
+ if (!Number.isInteger(id)) {
73
+ fail("show needs a numeric memory id");
74
+ return;
75
+ }
76
+ const row = getMemory(id);
77
+ if (!row) {
78
+ fail(`No memory with id ${id}`);
79
+ return;
80
+ }
81
+ console.log(` ${formatMemory(row)}`);
82
+ console.log(
83
+ ` ${pc.dim(`trust=${row.trust} confidence=${row.confidence} hits=${row.hitCount} salience=${row.salience}`)}`,
84
+ );
85
+ for (const entry of memoryHistory(id)) {
86
+ const when = new Date(entry.at).toISOString();
87
+ const why = entry.reason ? ` — ${entry.reason}` : "";
88
+ console.log(` ${pc.dim(when)} ${entry.op}${why}`);
89
+ }
90
+ console.log();
91
+ }
92
+
93
+ function cmdRemember(args: readonly string[]): void {
94
+ const [kindArg, subject, ...rest] = args;
95
+ const text = rest.join(" ");
96
+ if (!kindArg || !subject || !text) {
97
+ fail("remember needs <kind> <subject> <text...>");
98
+ return;
99
+ }
100
+ const kind = parseKind(kindArg);
101
+ const { id, similar } = assertMemory({
102
+ kind: kind!,
103
+ subject,
104
+ text,
105
+ trust: "operator",
106
+ });
107
+ console.log(` ${pc.green("●")} Remembered as #${id}`);
108
+ if (similar.length > 0) {
109
+ console.log(` ${pc.dim("Near-duplicates already stored:")}`);
110
+ for (const row of similar) console.log(` ${formatMemory(row)}`);
111
+ }
112
+ console.log();
113
+ }
114
+
115
+ function cmdForget(args: readonly string[]): void {
116
+ const id = Number(args[0]);
117
+ if (!Number.isInteger(id)) {
118
+ fail("forget needs a numeric memory id");
119
+ return;
120
+ }
121
+ const reason = args.slice(1).join(" ");
122
+ dropMemory(id, reason || undefined);
123
+ console.log(` ${pc.green("●")} Dropped #${id} to the graveyard\n`);
124
+ }
125
+
126
+ function cmdState(args: readonly string[]): void {
127
+ const [key, ...rest] = args;
128
+ const text = rest.join(" ");
129
+ if (!key || !text) {
130
+ fail("state needs <key> <text...>");
131
+ return;
132
+ }
133
+ const id = replaceStateKey(key, text);
134
+ console.log(` ${pc.green("●")} ${key} is now #${id}\n`);
135
+ }
136
+
137
+ /** Route a `talon memory <command>` invocation. */
138
+ export function runMemoryCommand(args: readonly string[]): void {
139
+ try {
140
+ switch (args[0]) {
141
+ case "list":
142
+ cmdList(args[1]);
143
+ break;
144
+ case "search":
145
+ if (!args[1]) fail("search needs a query");
146
+ else cmdSearch(args.slice(1).join(" "));
147
+ break;
148
+ case "show":
149
+ cmdShow(args[1]);
150
+ break;
151
+ case "remember":
152
+ cmdRemember(args.slice(1));
153
+ break;
154
+ case "forget":
155
+ cmdForget(args.slice(1));
156
+ break;
157
+ case "state":
158
+ cmdState(args.slice(1));
159
+ break;
160
+ default:
161
+ console.log(USAGE);
162
+ }
163
+ } catch (err) {
164
+ fail(err instanceof Error ? err.message : String(err));
165
+ }
166
+ }
package/src/cli/setup.ts CHANGED
@@ -650,7 +650,7 @@ export function buildSetupConfig(
650
650
  : existing.discord,
651
651
  // Never dropped. Deselecting WhatsApp shouldn't throw away its
652
652
  // pairing setup, and dropping it while `frontend` still lists
653
- // whatsapp produces a config util/config.ts refuses to load at all
653
+ // whatsapp produces a config core/config/index.ts refuses to load at all
654
654
  // ("WhatsApp frontend requires a whatsapp config block") — a daemon
655
655
  // that won't start. The `??` keeps that impossible even if the
656
656
  // branch that collects the answer is ever skipped.
@@ -31,7 +31,7 @@
31
31
 
32
32
  import type { Backend } from "./capabilities.js";
33
33
  import type { DoctorCheck, DoctorConfigSlice } from "../doctor/types.js";
34
- import type { TalonConfig } from "../../util/config.js";
34
+ import type { TalonConfig } from "../config/index.js";
35
35
 
36
36
  // ── Types ───────────────────────────────────────────────────────────────────
37
37
 
@@ -13,7 +13,7 @@
13
13
  * logs, telemetry, tests) doesn't have to chase it down again.
14
14
  *
15
15
  * This module also pins the canonical `BackendId` union;
16
- * `src/util/config.ts` imports `BACKEND_IDS` directly for its zod
16
+ * `src/core/config/index.ts` imports `BACKEND_IDS` directly for its zod
17
17
  * enums. Adding a backend means updating THIS literal once; the
18
18
  * config schema picks the change up automatically. Don't
19
19
  * reintroduce a manually-mirrored zod tuple — it's a footgun.
@@ -24,7 +24,7 @@ import type { ReasoningEffortLevel } from "../types.js";
24
24
  /**
25
25
  * Canonical backend identifiers — single source of truth for the
26
26
  * typed `BackendId` union AND the runtime zod enums in
27
- * `src/util/config.ts`. Update one place, everything stays in
27
+ * `src/core/config/index.ts`. Update one place, everything stays in
28
28
  * lockstep.
29
29
  */
30
30
  export const BACKEND_IDS = [
@@ -1,16 +1,16 @@
1
1
  import { existsSync, readFileSync, mkdirSync } from "node:fs";
2
2
  import writeFileAtomic from "write-file-atomic";
3
3
  import { z } from "zod";
4
- import { dirs, files as pathFiles } from "./paths.js";
5
- import { hardenTalonPermissions } from "./harden.js";
6
- import { setTimezone } from "./time.js";
7
- import { BACKEND_IDS } from "../core/agent-runtime/model-ref.js";
8
- import { REASONING_LEVEL_ORDER } from "../core/models/reasoning-levels.js";
4
+ import { dirs, files as pathFiles } from "../../util/paths.js";
5
+ import { hardenTalonPermissions } from "../../util/harden.js";
6
+ import { setTimezone } from "../../util/time.js";
7
+ import { BACKEND_IDS } from "../agent-runtime/model-ref.js";
8
+ import { REASONING_LEVEL_ORDER } from "../models/reasoning-levels.js";
9
9
  import {
10
10
  assembleSystemPrompt,
11
11
  joinSystemPromptParts,
12
12
  type SystemPromptParts,
13
- } from "../core/prompt/assemble.js";
13
+ } from "../prompt/assemble.js";
14
14
 
15
15
  /**
16
16
  * Backend-id literal source.
@@ -609,11 +609,11 @@ const configSchema = z.object({
609
609
 
610
610
  // System-prompt assembly lives in core/prompt/ (section pipeline,
611
611
  // templates, workspace listing). Re-exported here so existing
612
- // consumers keep importing from util/config.
612
+ // consumers keep importing from core/config.
613
613
  export {
614
614
  joinSystemPromptParts,
615
615
  type SystemPromptParts,
616
- } from "../core/prompt/assemble.js";
616
+ } from "../prompt/assemble.js";
617
617
 
618
618
  export type TalonConfig = z.infer<typeof configSchema> & {
619
619
  systemPrompt: string;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { Backend } from "../../agent-runtime/capabilities.js";
9
- import type { TalonConfig } from "../../../util/config.js";
9
+ import type { TalonConfig } from "../../config/index.js";
10
10
  import { type BackendInitContext } from "../../agent-runtime/backend-registry.js";
11
11
  import { log } from "../../../util/log.js";
12
12
  import { roleHolder } from "./holders.js";
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import type { Backend } from "../../agent-runtime/capabilities.js";
8
- import type { TalonConfig } from "../../../util/config.js";
8
+ import type { TalonConfig } from "../../config/index.js";
9
9
  import {
10
10
  listBackends,
11
11
  type BackendInitContext,
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { Backend } from "../../agent-runtime/capabilities.js";
7
- import type { TalonConfig } from "../../../util/config.js";
7
+ import type { TalonConfig } from "../../config/index.js";
8
8
  import {
9
9
  getBackend,
10
10
  listBackends,
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import type { Backend } from "../../agent-runtime/capabilities.js";
12
- import type { TalonConfig } from "../../../util/config.js";
12
+ import type { TalonConfig } from "../../config/index.js";
13
13
  import {
14
14
  getBackend,
15
15
  listBackends,
@@ -21,7 +21,7 @@ export async function performPluginReload(
21
21
  ): Promise<{ names: string[] }> {
22
22
  const { reloadPlugins, getPluginPromptAdditions } =
23
23
  await import("../../plugin/index.js");
24
- const { rebuildSystemPrompt } = await import("../../../util/config.js");
24
+ const { rebuildSystemPrompt } = await import("../../config/index.js");
25
25
  const { notifyPromptInputsChanged } =
26
26
  await import("../../prompt/invalidation.js");
27
27
 
@@ -19,7 +19,7 @@
19
19
  */
20
20
 
21
21
  import type { Backend } from "../agent-runtime/capabilities.js";
22
- import type { TalonConfig } from "../../util/config.js";
22
+ import type { TalonConfig } from "../config/index.js";
23
23
  import type { ReasoningEffortLevel } from "../types.js";
24
24
  import {
25
25
  normalizeReasoningLevels,
@@ -25,7 +25,7 @@
25
25
  */
26
26
 
27
27
  import type { ContextManager } from "../types.js";
28
- import type { TalonConfig } from "../../util/config.js";
28
+ import type { TalonConfig } from "../config/index.js";
29
29
  import type { Gateway } from "../engine/gateway.js";
30
30
  import type { FrontendDescriptor } from "./registry.js";
31
31
 
@@ -73,7 +73,7 @@ import {
73
73
  type ModelSource,
74
74
  } from "../agent-runtime/model-ref.js";
75
75
  import type { UnifiedModelInfo } from "../types.js";
76
- import type { TalonConfig } from "../../util/config.js";
76
+ import type { TalonConfig } from "../config/index.js";
77
77
  import { logWarn } from "../../util/log.js";
78
78
 
79
79
  /**
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { log, logError, logWarn } from "../../util/log.js";
7
- import type { TalonConfig } from "../../util/config.js";
7
+ import type { TalonConfig } from "../config/index.js";
8
8
  import { registry, reloadState } from "./registry.js";
9
9
  import type { ProvisionOutcome } from "./provision.js";
10
10
  import { NATIVE_RUNTIMES, type NativePluginId } from "./native-runtimes.js";
@@ -226,7 +226,7 @@ export async function reloadPlugins(
226
226
  ): Promise<{ names: string[]; config: TalonConfig }> {
227
227
  // Validate config BEFORE tearing down existing plugins. If the config is
228
228
  // malformed the error propagates and current plugins stay intact.
229
- const { loadConfig, getFrontends } = await import("../../util/config.js");
229
+ const { loadConfig, getFrontends } = await import("../config/index.js");
230
230
  const config = loadConfig();
231
231
 
232
232
  // Derive frontends from config if not explicitly provided
@@ -8,7 +8,7 @@
8
8
  * talon.json so the surface owns its own write path.
9
9
  */
10
10
 
11
- import type { TalonConfig } from "../../util/config.js";
11
+ import type { TalonConfig } from "../config/index.js";
12
12
  import { isPathPlugin, type PluginEntry } from "./types.js";
13
13
  import {
14
14
  BUILTIN_PLUGINS,
@@ -9,7 +9,7 @@
9
9
  import { readFileSync } from "node:fs";
10
10
  import { files, dirs } from "../../util/paths.js";
11
11
  import { tailFile } from "../../util/tail-file.js";
12
- import type { TalonConfig } from "../../util/config.js";
12
+ import type { TalonConfig } from "../../core/config/index.js";
13
13
  import type { Gateway } from "../../core/engine/gateway.js";
14
14
  import { resetSession, getAllSessions } from "../../storage/sessions.js";
15
15
  import { clearHistory } from "../../storage/history.js";
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  import { MessageFlags } from "discord.js";
25
- import type { TalonConfig } from "../../../../util/config.js";
25
+ import type { TalonConfig } from "../../../../core/config/index.js";
26
26
  import type { Gateway } from "../../../../core/engine/gateway.js";
27
27
  import { deriveNumericChatId } from "../../../../util/chat-id.js";
28
28
  import { logError } from "../../../../util/log.js";
@@ -15,7 +15,7 @@ import {
15
15
  StringSelectMenuBuilder,
16
16
  MessageFlags,
17
17
  } from "discord.js";
18
- import type { TalonConfig } from "../../../../util/config.js";
18
+ import type { TalonConfig } from "../../../../core/config/index.js";
19
19
  import type { Gateway } from "../../../../core/engine/gateway.js";
20
20
  import {
21
21
  getChatSettings,
@@ -12,7 +12,7 @@ import type {
12
12
  ButtonInteraction,
13
13
  StringSelectMenuInteraction,
14
14
  } from "discord.js";
15
- import type { TalonConfig } from "../../../../util/config.js";
15
+ import type { TalonConfig } from "../../../../core/config/index.js";
16
16
  import type { Gateway } from "../../../../core/engine/gateway.js";
17
17
 
18
18
  export type ComponentInteraction =
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { type ModalSubmitInteraction, MessageFlags } from "discord.js";
6
- import type { TalonConfig } from "../../../util/config.js";
6
+ import type { TalonConfig } from "../../../core/config/index.js";
7
7
  import type { Gateway } from "../../../core/engine/gateway.js";
8
8
  import { setChatPulseInterval } from "../../../storage/chat-settings.js";
9
9
  import { registerChat, enablePulse } from "../../../core/background/pulse.js";
@@ -10,7 +10,7 @@ import {
10
10
  ButtonStyle,
11
11
  MessageFlags,
12
12
  } from "discord.js";
13
- import type { TalonConfig } from "../../../util/config.js";
13
+ import type { TalonConfig } from "../../../core/config/index.js";
14
14
  import type { Gateway } from "../../../core/engine/gateway.js";
15
15
  import { respawnSelf } from "../../../util/respawn.js";
16
16
  import { forceDream } from "../../../core/background/dream.js";
@@ -13,7 +13,7 @@
13
13
  */
14
14
 
15
15
  import { type Client, REST, Routes, SlashCommandBuilder } from "discord.js";
16
- import type { TalonConfig } from "../../../util/config.js";
16
+ import type { TalonConfig } from "../../../core/config/index.js";
17
17
  import { log, logError, logWarn } from "../../../util/log.js";
18
18
  import { getRepoRoot } from "../../../core/update/self-update.js";
19
19
 
@@ -12,7 +12,7 @@ import {
12
12
  renderMeshReport,
13
13
  renderUsageMessage,
14
14
  } from "../render.js";
15
- import type { TalonConfig } from "../../../util/config.js";
15
+ import type { TalonConfig } from "../../../core/config/index.js";
16
16
  import { collectPlanUsage } from "../../shared/plan-usage-report.js";
17
17
  import { getLoadedPlugins } from "../../../core/plugin/index.js";
18
18
  import { getMeshService } from "../../../core/mesh/index.js";